diff options
author | Norbert Preining <norbert@preining.info> | 2023-01-16 03:03:27 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2023-01-16 03:03:27 +0000 |
commit | 6f9e1680085e7bb4d258f6f8116369d122e196e1 (patch) | |
tree | 9ac0ecb239240d1d672b188f29c1479de215074b /graphics/pgf/base/tex/generic/basiclayer | |
parent | b8345f39630408bb198e7636381ce4240154ca9b (diff) |
CTAN sync 202301160303
Diffstat (limited to 'graphics/pgf/base/tex/generic/basiclayer')
18 files changed, 10121 insertions, 0 deletions
diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcore.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcore.code.tex new file mode 100644 index 0000000000..b7e47f4ee3 --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcore.code.tex @@ -0,0 +1,41 @@ +% Copyright 2019 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. + +\ProvidesPackageRCS{pgfcore.code.tex} + +\newif\ifpgf@draftmode +\def\pgf@typeout{\immediate\write0} + +\ifdefined\pgfmathloaded\else + \input pgfmath.code.tex +\fi + +\ifdefined\pgfintloaded\else + \input pgfint.code.tex +\fi + +\input pgfcorepoints.code.tex +\input pgfcorepathconstruct.code.tex +\input pgfcorepathusage.code.tex +\input pgfcorescopes.code.tex +\input pgfcoregraphicstate.code.tex +\input pgfcoretransformations.code.tex +\input pgfcorequick.code.tex +\input pgfcoreobjects.code.tex +\input pgfcorepathprocessing.code.tex +\input pgfcorearrows.code.tex +\input pgfcoreshade.code.tex +\input pgfcoreimage.code.tex +\input pgfcoreexternal.code.tex +\input pgfcorelayers.code.tex +\input pgfcoretransparency.code.tex +\input pgfcorepatterns.code.tex +\input pgfcorerdf.code.tex + +\endinput diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcorearrows.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcorearrows.code.tex new file mode 100644 index 0000000000..7f079fa841 --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcorearrows.code.tex @@ -0,0 +1,1253 @@ +% Copyright 2006, 2018 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{pgfcorearrows.code.tex} + + + +% Define a new (meta) arrow or a shorthand +% +% #1 = key--value pairs +% +% Description: +% +% This command is used to define a new arrow tip kind. For more +% details on the description of the keys, please see the pgfmanual. +% +% name = Name of the arrow. If the name contains a dash +% (hyphen), the text before the hyphen is the start name +% and the text behind it the end name. +% +% means = If set, none of the below options may be +% given. The effect is that whenever the arrow is +% used, it gets replaced by this "text", which is +% parsed by the parser. +% +% setup code = Code that does "precomputations". These will be +% executed only once for each combination of the +% dependencies. At the end of this code, you can use +% \savethe and \save to "save" computed values, which +% will then be available inside the "code". Values needed +% only for the "... end" keys and the convex hull do not +% need to be saved since these are also executed only +% once. +% drawing code = Code for drawing the arrow. When the cache key is set to +% true, which is the default, the code will be protocolled +% and the resulting code is inserted using \pgflowlevelobj. +% cache = Boolean that decides whether the arrow can be cached. The +% default is true, so you have to say cache=false to switch +% caching off. In this case, each time the arrow is drawn, +% its code is simply executed. This allows you to put things +% like text or shadings in arrow tips. +% bending mode = Can be set to "orthogonal", "polar", or +% "none". Defaults to "orthogonal". +% defaults = A list of "default" options for the arrow tip. These +% are executed as if they were given to the arrow tip in +% brackets. This is useful for setting up default values. +% parameters = A list of comma-separated macro names on whose values +% the appearance of the arrow tip depends. When an arrow +% tip is used, these macros are expanded. If an +% arrow tip was already installed with the same macro +% names (and caching is true), the cached code is +% used. Note that when you use dimensions here, add \the. +% +% Inside the setup code, the following macros are available: +% +% \pgfarrowssettipend +% The code should draw an arrow pointing "right along the x +% axis". The "tip" key specifies how far the arrow goes +% along the x axis, that is, it should be the x coordinate +% of the very tip of the arrow. In previous versions this +% was called the "right extend". The value passed to this +% key should be some code that sets the dimension +% "\pgfarrowresult", which is \let to be equal to +% \pgf@x. A \relax will be added after the code provided +% here, so you can write things like "\pgfarrowresult=1pt". +% \pgfarrowssetbackend +% The leftmost x-coordinate that is still part of the +% arrow tip (the "back end" of the arrow"). This coordinate +% will be used when multiple arrow tips are +% composed. Defaults to 0pt. +% \pgfarrowssetlineend +% The x-coordinate where a line should stop inside the arrow +% tip so that it gets "obscured" by the arrow. Defaults to 0pt. +% \pgfarrowssetvisualtipend +% When the arrow tip is drawn in flex mode, it is rotated +% such that the x-coordinates of "visual tip end" and "visual +% back end" lie on the path. Defaults to \pgfarrowssettipend. +% \pgfarrowssetvisualbackend +% See above. Defaults to \pgfarrowssetbackend + +\def\pgfdeclarearrow#1{% + \let\pgf@decl@arrow@defaults\pgfutil@empty% + \let\pgf@decl@arrow@means\relax% + \let\pgf@decl@arrow@code\relax% + \pgfkeys{/pgf/@arrows decl/.cd, + name=, + setup code=, + cache=true, + bending mode=orthogonal, + parameters=,% + #1% + }% + \ifx\pgf@decl@arrow@name@end\pgfutil@empty% + \pgferror{Declaring unnamed arrow}% + \else% + \pgf@arrow@letter{name@end}% + \pgf@arrow@letter{name@start}% + \expandafter\let\csname pgf@ar@start@\pgf@decl@arrow@name@start\endcsname\pgf@decl@arrow@name@end% + \expandafter\let\expandafter\pgf@old@code\csname pgf@ar@code@\pgf@decl@arrow@name@end\endcsname% + \expandafter\let\expandafter\pgf@old@means\csname pgf@ar@means@\pgf@decl@arrow@name@end\endcsname% + \ifx\pgf@decl@arrow@code\relax% + \ifx\pgf@decl@arrow@means\relax% + \pgferror{You must set either the 'means' or the drawing code' keys for arrow tip '\pgf@decl@arrow@name@end'}% + \else% + \ifx\pgf@old@code\relax% + \let\pgf@arrow@tip@sequence\pgfutil@empty% + \let\pgf@arrow@translate\relax% + \expandafter\let\expandafter\pgf@arrows@direct\csname pgf@arrows@direct@name@end@\pgf@decl@arrow@means\endcsname% + \ifx\pgf@arrows@direct\relax% + \let\pgf@arrows@options\pgfutil@empty% + \expandafter\pgfarrows@initial@parser\pgf@decl@arrow@means[]\pgf@stop% + \else% + \let\pgf@arrow@tip@sequence\pgf@arrows@direct% + \fi% + \pgf@arrow@letter@\pgf@arrow@tip@sequence{means}% + \expandafter\let\csname pgf@ar@code@\pgf@decl@arrow@name@end\endcsname\relax% + \else% + \pgferror{Arrow tip '\pgf@decl@arrow@name@end' was already + defined with key 'drawing code' previously and you cannot change this}% + \fi% + \fi% + \else% + \ifx\pgf@decl@arrow@means\relax% + \ifx\pgf@old@means\relax% + \pgf@arrow@letter{code}% + \pgf@arrow@letter{defaults}% + \pgf@arrow@letter{setup}% + \pgf@arrow@letter{bending@mode}% + \pgf@arrow@letter{par}% + \expandafter\let\csname pgf@ar@do@cache@\pgf@decl@arrow@name@end\endcsname\pgf@decl@arrow@cache% + \else% + \pgferror{Arrow tip '\pgf@decl@arrow@name@end' was already + defined with key 'means' previously and you cannot change this}% + \fi% + \else% + \pgferror{You cannot set both the 'means' and also the 'drawing code' + keys for arrow tip '\pgf@decl@arrow@name@end'}% + \fi% + \fi% + \fi% +} + +\def\pgf@arrow@letter#1{% + \expandafter\pgf@arrow@letter@\expandafter{\csname pgf@decl@arrow@#1\endcsname}{#1}% +} +\def\pgf@arrow@letter@#1#2{% + \expandafter\let\csname pgf@ar@#2@\pgf@decl@arrow@name@end\endcsname#1% +} + +\pgfkeys{ + /pgf/@arrows decl/.cd, + name/.code={% + \pgfutil@in@-{#1}% + \ifpgfutil@in@% + \pgf@arrows@name@decomp#1\pgf@stop% + \else% + \def\pgf@decl@arrow@name@end{#1}\let\pgf@decl@arrow@name@start\pgf@decl@arrow@name@end% + \fi}, + means/.store in=\pgf@decl@arrow@means, + setup code/.store in=\pgf@decl@arrow@setup, + drawing code/.store in=\pgf@decl@arrow@code, + cache/.store in=\pgf@decl@arrow@cache, + bending mode/.is choice, + bending mode/none/.code=\let\pgf@decl@arrow@bending@mode\pgfutil@empty, + bending mode/orthogonal/.code=\def\pgf@decl@arrow@bending@mode{\pgfpointcurvilinearbezierorthogonal}, + bending mode/polar/.code=\def\pgf@decl@arrow@bending@mode{\pgfpointcurvilinearbezierpolar}, + parameters/.store in=\pgf@decl@arrow@par, + defaults/.code={% + \let\pgf@arrows@options\pgfutil@empty% + \pgfkeys{/pgf/arrow keys/.cd,#1}% + \let\pgf@decl@arrow@defaults\pgf@arrows@options% + } +} + +\def\pgf@arrows@name@decomp#1-#2\pgf@stop{% + \def\pgf@decl@arrow@name@start{#1}% + \def\pgf@decl@arrow@name@end{#2}% +} + + +% Handler for defining arrow tips: +% +% Description: +% +% When you write "my name/.tip = arrow spec", this has the same +% effect as writing \pgfdeclarearrow{name = my name, means = arrow spec}. + +\pgfkeys{/handlers/.tip/.code=% + \expandafter\expandafter\expandafter\pgf@arrows@unravel\pgfkeyscurrentpath/\pgf@stop% + \expandafter\pgf@arrows@key@call\expandafter{\pgf@arrows@unravelled}{#1}} +\def\pgf@arrows@unravel#1/{\pgfutil@ifnextchar\pgf@stop{\def\pgf@arrows@unravelled{#1}\pgfutil@gobble}{\pgf@arrows@unravel}} +\def\pgf@arrows@key@call#1#2{\pgfdeclarearrow{name={#1},means={#2}}} + + + + +% Draw an arrow +% +% #1 = arrow specification +% +% Description: +% +% Draws the arrow in the given specification (and "end" +% specification). The arrow will be drawn such that it touches the +% origin "from the left", that is, the arrow will lie completely in +% the half plane with negative $x$ values and the tip will end exactly +% at the origin. + +\def\pgfarrowdraw#1{% + {% + \pgfsetarrowsend{#1}% + \pgf@arrow@compute@shortening\pgf@end@tip@sequence% + \pgf@arrow@draw@arrow\pgf@end@tip@sequence\pgf@xb% + }% +} + + + +% Compute the length of an arrow +% +% #1 = arrow specification +% +% Description: +% +% In \pgf@x, this will return the total length of the arrow given as +% #1, in \pgf@xa it will return the distance from the tip to the line +% end. + +\def\pgfarrowtotallength#1{% + {% + \pgfsetarrowsend{#1}% + \pgf@arrow@compute@shortening\pgf@end@tip@sequence% + \expandafter\expandafter\expandafter% + }% + \expandafter\expandafter\expandafter\pgf@x\expandafter\the\expandafter\pgf@xb\expandafter\pgf@xa\the\pgf@xa% +} + + + + + +% Sets the end arrow tip +% +% #1 = An arrow specification +% +% Description: +% +% An "arrow specification" is a sequence of names of meta arrow tips +% together with options in brackets. In detail: +% +% In #1, consider the text from the start up to the first bracket. If +% this text is the name of a (meta) arrow tip, we use this arrow tip +% with the provided options. If it is the name of a arrow tip +% shorthand, this shorthand is expanded and the options are applied to +% each arrow tip inside the shorthand. If the text is neither or the +% above, the first letter of text is treated as a shorthand without +% options. +% +% The special arrow tip "." is used to indicate the end of the line. +% +% \pgfsetarrowsend{stealth[reversed]} +% \pgfsetarrowsend{stealth[length=1pt] . stealth[length=2pt]} +% \pgfsetarrowsend{>>>} +% \pgfsetarrowsend{>.>} + +\def\pgfsetarrowsend#1{% + \let\pgf@arrow@tip@sequence\pgfutil@empty% + \pgf@arrows@translatefalse% + \expandafter\let\expandafter\pgf@arrows@direct\csname pgf@arrows@direct@name@end@#1\endcsname% + \ifx\pgf@arrows@direct\relax% + \edef\pgf@marshal{\noexpand\pgfarrows@initial@parser#1[]\noexpand\pgf@stop}% + \pgf@marshal% + \else% + \let\pgf@arrow@tip@sequence\pgf@arrows@direct% + \fi% + \let\pgf@end@tip@sequence\pgf@arrow@tip@sequence% +} + +\newif\ifpgf@arrows@translate + +\def\pgfarrows@initial@parser{% + \pgfutil@ifnextchar[\pgfarrows@initial@parser@{\pgfarrows@initial@parser@[]}}%} + +\def\pgfarrows@initial@parser@[#1]{% + \let\pgf@arrows@options\pgfutil@empty% + \pgfkeys{/pgf/arrow keys/.cd,#1}% + \let\pgf@arrows@options@initial\pgf@arrows@options% + \pgfarrows@parser% +} + +\def\pgfarrows@parser#1[{% + \pgfkeys@spdef\pgf@temp{#1}% + \ifx\pgf@temp\pgfutil@empty% + \let\pgf@next\pgf@arrows@empty% + \else% + \ifx\pgf@temp\pgf@dot@text% + \let\pgf@next\pgf@arrows@dot@parsed% + \else% + \let\pgf@untranslated\pgf@temp% + \ifpgf@arrows@translate% + \pgf@arrow@swapper% + \fi% + % Now, let's see what we do with this... + \expandafter\ifx\csname pgf@ar@code@\pgf@temp\endcsname\relax + \expandafter\ifx\csname pgf@ar@means@\pgf@temp\endcsname\relax + % #1 should start with a single-char shorthands + \let\pgf@next\pgf@arrows@single@char@parser% + \let\pgf@temp\pgf@untranslated% + \else% + % #1 is a shorthand! + \let\pgf@next\pgf@arrows@shorthand@parsed% + \fi% + \else% + % #1 is a meta arrow! + \let\pgf@next\pgf@arrows@meta@parsed% + \fi% + \fi% + \fi% + \expandafter\pgf@next\pgf@temp[% +} + +\def\pgf@arrows@empty[#1]{% + \pgfutil@ifnextchar\pgf@stop\pgf@arrows@parser@done\pgfarrows@parser% +} + +\def\pgf@arrows@single@char@parser#1{% + \def\pgf@temp{#1}% + \ifx\pgf@temp\pgf@dot@text% + \let\pgf@next\pgf@arrows@dot@parsed% + \else% + \let\pgf@untranslated\pgf@temp% + \ifpgf@arrows@translate% + \pgf@arrow@swapper% + \fi% + \expandafter\ifx\csname pgf@ar@code@\pgf@temp\endcsname\relax + \expandafter\ifx\csname pgf@ar@means@\pgf@temp\endcsname\relax + \let\pgf@temp\pgf@untranslated% + \let\pgf@next\pgf@arrows@unknown% + \else% + \let\pgf@next\pgf@arrows@shorthand@parsed% + \fi% + \else% + \let\pgf@next\pgf@arrows@meta@parsed% + \fi + \fi + \expandafter\pgf@next\pgf@temp[]% +} +\def\pgf@arrows@unknown#1[]#2[#3]{% + \pgferror{Unknown arrow tip kind '#1#2'}% +} + +\def\pgf@arrows@meta@parsed#1[#2]{% + % Ok, run the keys #2. This will add commands to \pgf@arrows@options: + % + \let\pgf@arrows@options\pgf@arrows@options@initial% + \pgfkeys{/pgf/arrow keys/.cd,#2}% + % Append the arrow and its options to the arrow tip sequence: + \expandafter\pgf@arrows@meta@set\expandafter{\pgf@arrows@options}{#1}{\pgf@arrow@handle}% + \pgfutil@ifnextchar\pgf@stop\pgf@arrows@parser@done\pgfarrows@parser% +} + +\def\pgf@arrows@parser@done#1{% +} + +\def\pgf@arrows@dot@parsed#1[#2]{% + \pgf@arrows@append@to@tips{\pgf@arrow@handle@dot}% + \pgfutil@ifnextchar\pgf@stop\pgf@arrows@parser@done\pgfarrows@parser% +} + +\def\pgf@arrows@meta@set#1#2#3{% + \pgf@arrows@append@to@tips{#3{#2}{#1}}% +} +\def\pgf@arrows@append@to@tips#1{% + \let\pgf@tempa\pgf@arrow@tip@sequence% + \def\pgf@tempb{#1}% + \ifpgf@arrows@translate% + \let\pgf@tempa\pgf@tempb% + \let\pgf@tempb\pgf@arrow@tip@sequence% + \fi% + \expandafter\expandafter\expandafter\def% + \expandafter\expandafter\expandafter\pgf@arrow@tip@sequence% + \expandafter\expandafter\expandafter{\expandafter\pgf@tempa\pgf@tempb}% +} + +\def\pgf@arrows@shorthand@parsed#1[#2]{% + \let\pgf@arrows@options\pgf@arrows@options@initial% + \pgfkeys{/pgf/arrow keys/.cd,#2}% + \ifx\pgf@arrows@options\pgfutil@empty% + \expandafter\pgf@arrows@append@to@tips\expandafter{% + \expandafter\pgf@arrow@handle@shorthand@empty\expandafter{\csname pgf@ar@means@#1\endcsname}}% + \else% + \expandafter\expandafter\expandafter\pgf@arrows@meta@set\expandafter\expandafter\expandafter{% + \expandafter\pgf@arrows@options\expandafter}\expandafter{\csname pgf@ar@means@#1\endcsname}{\pgf@arrow@handle@shorthand}% + \fi% + \pgfutil@ifnextchar\pgf@stop\pgf@arrows@parser@done\pgfarrows@parser% +} + + +% General handler: + +\def\pgf@arrow@handle@shorthand@empty#1{#1} + +\def\pgf@arrow@handle@shorthand#1#2{% + \def\pgf@temp@opt{#2}% + \expandafter\expandafter\expandafter\def% + \expandafter\expandafter\expandafter\pgf@arrows@nested@options@temp% + \expandafter\expandafter\expandafter{\expandafter\pgf@temp@opt\pgf@arrows@nested@options}% + \expandafter\let\expandafter\pgf@arrows@nested@options\expandafter\pgf@arrows@nested@options@temp% + \expandafter#1% all these expandafters to avoid creating groups, but having the options nest + \expandafter\def\expandafter\pgf@arrows@nested@options\expandafter{\pgf@arrows@nested@options}% +} + +\let\pgf@arrows@nested@options\pgfutil@empty + + + + +% Sets the start arrow tip +% +% #1 = An arrow specification +% +% Description: +% +% This works like \pgfsetarrowsend, only the order of the tips in the +% arrow specification is reversed and the "reversed names" are used. +% +% \pgfsetarrowsend{<<} +% \pgfsetarrowsend{>.>} + +\def\pgfsetarrowsstart#1{% + \let\pgf@arrow@tip@sequence\pgfutil@empty% + \pgf@arrows@translatetrue% + \expandafter\let\expandafter\pgf@arrows@direct\csname pgf@arrows@direct@name@start@#1\endcsname% + \ifx\pgf@arrows@direct\relax% + \edef\pgf@marshal{\noexpand\pgfarrows@initial@parser#1[]\noexpand\pgf@stop}% + \pgf@marshal% + \else% + \let\pgf@arrow@tip@sequence\pgf@arrows@direct% + \fi% + \let\pgf@start@tip@sequence\pgf@arrow@tip@sequence% +} + +\def\pgf@arrow@swapper{% + \expandafter\let\expandafter\pgf@temp\csname pgf@ar@start@\pgf@temp\endcsname% + \ifx\pgf@temp\relax% + \def\pgf@temp{undefined}% + \fi% +} + +\let\pgf@start@tip@sequence\pgfutil@empty +\let\pgf@end@tip@sequence\pgfutil@empty + + +\expandafter\def\csname pgf@arrows@direct@name@start@\endcsname{} +\expandafter\def\csname pgf@arrows@direct@name@end@\endcsname{} + + +% Predefined lengths and ifs + +\newdimen\pgfarrowsep + +\newif\ifpgfarrowswap +\newif\ifpgfarrowreversed +\newif\ifpgfarrowharpoon +\newif\ifpgfarrowopen + +\let\pgf@arrows@stroke@color\pgfutil@empty +\let\pgf@arrows@fill@color\pgfutil@empty + +\def\pgfarrows@length@scale{1} +\def\pgfarrows@width@scale{1} +\def\pgfarrows@slant{0} + +\let\pgfarrows@scale@list\pgfutil@empty +\def\pgfarrowsaddtolengthscalelist#1{\expandafter\def\expandafter\pgfarrows@scale@list\expandafter{\pgfarrows@scale@list#1\pgfarrows@length@scale#1}} +\def\pgfarrowsaddtowidthscalelist#1{\expandafter\def\expandafter\pgfarrows@scale@list\expandafter{\pgfarrows@scale@list#1\pgfarrows@width@scale#1}} + +\pgfkeys{ + /pgf/arrow keys/.cd, + scale/.code={% + \pgfmathparse{#1}% + \expandafter\pgfarrowsaddtooptions\expandafter{\expandafter\def\expandafter\pgfarrows@length@scale\expandafter{\pgfmathresult}}% + \expandafter\pgfarrowsaddtooptions\expandafter{\expandafter\def\expandafter\pgfarrows@width@scale\expandafter{\pgfmathresult}}% + }, + scale length/.code={\pgfmathparse{#1}\expandafter\pgfarrowsaddtooptions\expandafter{\expandafter\def\expandafter\pgfarrows@length@scale\expandafter{\pgfmathresult}}}, + scale width/.code={\pgfmathparse{#1}\expandafter\pgfarrowsaddtooptions\expandafter{\expandafter\def\expandafter\pgfarrows@width@scale\expandafter{\pgfmathresult}}}, + slant/.code={\pgfmathparse{#1}\expandafter\pgfarrowsaddtooptions\expandafter{\expandafter\def\expandafter\pgfarrows@slant\expandafter{\pgfmathresult}}}, + sep/.code={ + \pgfarrowsthreeparameters{#1}% + \expandafter\pgfarrowsaddtooptions\expandafter{\expandafter\pgfarrowslinewidthdependent\pgfarrowstheparameters\pgfarrowsep\pgf@x}% + }, + sep/.default=0.88pt .3 1, + % + swap/.code=\pgfarrowsaddtooptions{\ifpgfarrowswap\pgfarrowswapfalse\else\pgfarrowswaptrue\fi}, + reversed/.code=\pgfarrowsaddtooptions{\ifpgfarrowreversed\pgfarrowreversedfalse\else\pgfarrowreversedtrue\fi}, + harpoon/.is choice, + harpoon/.default=true, + harpoon/true/.code=\pgfarrowsaddtooptions{\pgfarrowharpoontrue}, + harpoon/false/.code=\pgfarrowsaddtooptions{\pgfarrowharpoonfalse}, + left/.style={harpoon}, + right/.style={harpoon,swap}, + % + color/.code=\pgfarrowsaddtooptions{\def\pgf@arrows@stroke@color{#1}}, + fill/.code={% + \def\pgf@temp{#1}% + \ifx\pgf@temp\pgf@nonetext% + \pgfarrowsaddtooptions{\pgfarrowopentrue} + \else + \pgfarrowsaddtooptions{\pgfarrowopenfalse\def\pgf@arrows@fill@color{#1}} + \fi + }, + fill/.value required, + open/.style={fill=none}, + .unknown/.code={ + \expandafter\pgfutil@in@\expandafter!\expandafter{\pgfkeyscurrentname}% + \ifpgfutil@in@% + % this is a color! + \expandafter\pgfarrowsaddtooptions\expandafter{\expandafter\def\expandafter\pgf@arrows@stroke@color\expandafter{\pgfkeyscurrentname}}% + \else% + \pgfutil@doifcolorelse{\pgfkeyscurrentname} + {% + \expandafter\pgfarrowsaddtooptions\expandafter{\expandafter\def\expandafter\pgf@arrows@stroke@color\expandafter{\pgfkeyscurrentname}}% + } + {% + \edef\pgf@temp{\pgfkeyscurrentname}% + \pgfkeys{/errors/unknown key/.expand once=\expandafter{\pgf@temp}{#1}}% + } + \fi + } +} +\def\pgf@nonetext{none} + +\def\pgfarrowsaddtooptions#1{\expandafter\def\expandafter\pgf@arrows@options\expandafter{\pgf@arrows@options#1}} +\def\pgfarrowsaddtolateoptions#1{\expandafter\def\expandafter\pgf@arrows@options\expandafter{\pgf@arrows@options\pgf@arrows@add@to@late@options{#1}}} +\def\pgf@arrows@add@to@late@options#1{\expandafter\def\expandafter\pgf@arrows@late@options\expandafter{\pgf@arrows@late@options#1}} + + + +\def\pgfarrowsthreeparameters#1{% + \pgfarrowsthreeparameters@#1 +0 +0 +0 \pgf@stop% +} +\def\pgfarrowsthreeparameters@#1 #2 #3 #4\pgf@stop{% + \pgfmathsetlength\pgf@x{#1}% + \pgfmathsetmacro\pgf@temp@a{#2}% + \pgfmathsetmacro\pgf@temp@b{#3}% + \edef\pgfarrowstheparameters{{\the\pgf@x}{\pgf@temp@a}{\pgf@temp@b}}% +} + +\def\pgfarrowsfourparameters#1{% + \pgfarrowsfourparameters@#1 +0 +0 +0 \pgf@stop% +} +\def\pgfarrowsfourparameters@#1:#2 #3 #4 #5\pgf@stop{% + \pgfmathsetmacro\pgf@temp@z{#1}% + \pgfmathsetlength\pgf@x{#2}% + \pgfmathsetmacro\pgf@temp@a{#3}% + \pgfmathsetmacro\pgf@temp@b{#4}% + \edef\pgfarrowstheparameters{{\pgf@temp@z}{\the\pgf@x}{\pgf@temp@a}{\pgf@temp@b}}% +} + +\def\pgfarrows@angle@setup#1#2#3#4{% + \pgfarrowslinewidthdependent{#2}{#3}{#4} + \pgf@xc\pgf@x + \pgf@yc#1 pt% + \pgf@yc.5\pgf@yc% + \pgfpointpolar{\pgf@yc}{\pgf@xc} + \pgfarrowlength\pgf@x% + \pgf@y2\pgf@y% + \expandafter\pgf@arrows@add@to@late@options\expandafter{\expandafter\pgfarrowwidth\the\pgf@y}% +} + +\def\pgfarrows@angle@setup@prime#1{% + \pgf@yc#1 pt % + \pgf@yc=0.5\pgf@yc + \pgfmathtan@{\pgf@sys@tonumber\pgf@yc}% + \pgfarrowwidth\pgfmathresult\pgfarrowlength% + \pgfarrowwidth2\pgfarrowwidth% +} + +\def\pgfarrowslinewidthdependent#1#2#3{% + \pgf@x#1% + \ifdim\pgfinnerlinewidth>0pt% + \pgf@arrows@inner@line@width@dep{#2}{#3}% + \else% + \advance\pgf@x by#2\pgflinewidth% + \fi% +} +\def\pgf@arrows@inner@line@width@dep#1#2{% + % #1*((1-#2/2)*full line width - (#2/2) * inner line width) + % Compute "real" line width + \pgf@xa\pgflinewidth% + \pgf@xb-.5\pgflinewidth% + \pgf@xb#2\pgf@xb% + \advance\pgf@xa by\pgf@xb% + \pgf@xb\pgfinnerlinewidth% + \pgf@xb-.5\pgf@xb + \advance\pgf@xa by#2\pgf@xb% + \advance\pgf@x by#1\pgf@xa% +} + + +\def\pgfarrowslengthdependent#1#2#3#4{% + #4#1% + \advance#4by#2\pgfarrowlength% + \advance#4by#3\pgflinewidth% +} + + + +% Build the full name: + +\def\pgf@arrow@fullname#1{pgf@@ar@#1@\the\pgflinewidth @\pgfinnerlinewidth @\ifpgfarrowreversed r\fi @\pgf@arrows@stroke@color @\pgf@arrows@fill@color @\csname pgf@ar@par@#1\endcsname} +\def\pgf@arrow@id@count{0}% + +% Compute the arrow id of an arrow +% +% #1 = arrow name +% #2 = options +% +% Description: +% +% Returns the an id in \pgf@arrow@id that identifies the instantiation +% of the given arrow. If the arrow was not instantiated, this happens now. + +\def\pgfarrows@getid#1#2{% + % Execute options: + \let\pgf@arrows@late@options\pgfutil@empty% + % 1. Defaults: + \csname pgf@ar@defaults@#1\endcsname% + % 2. Scope: + \pgf@arrows@options@scope + % 3. Local: + #2\relax% + % 4. Nested: + \pgf@arrows@nested@options% + % 5. Last options: + \pgf@arrows@late@options% + % 6. Scaling: + \pgfarrows@scale@list% + % Now, test: + \expandafter\global\expandafter\let\expandafter\pgf@arrow@id\csname\pgf@arrow@fullname{#1}\endcsname\relax% + \ifx\pgf@arrow@id\relax% + \pgf@arrows@instantiate{#1} + \fi% +} + +\def\pgf@arrows@instantiate#1{% + % Not defined. Rats! + % Allocate new id: + \pgfutil@tempcnta\pgf@arrow@id@count\relax% + \advance\pgfutil@tempcnta by1\relax% + \xdef\pgf@arrow@id@count{\the\pgfutil@tempcnta}% + \expandafter\global\expandafter\let\csname\pgf@arrow@fullname{#1}\endcsname\pgf@arrow@id@count% + \global\let\pgf@arrow@id\pgf@arrow@id@count% + {% + \pgfclearid% + \csname pgf@ar@setup@#1\endcsname% + % Handle reversal + \ifpgfarrowreversed% + % Compute transformation: + \pgf@arrows@handle@reverse% + \fi% + % Save computed values + \expandafter\global\expandafter\let\csname pgf@ar@saves@\pgf@arrow@id\endcsname\pgf@arrows@saves% + \expandafter\global\expandafter\let\csname pgf@ar@hull@\pgf@arrow@id\endcsname\pgf@arrows@convexhull% + \expandafter\xdef\csname pgf@ar@ends@\pgf@arrow@id\endcsname{{\pgf@arrows@the@tipend}{\pgf@arrows@the@backend}{\pgf@arrows@the@lineend}}% + \expandafter\xdef\csname pgf@ar@visual@\pgf@arrow@id\endcsname{{\pgf@arrows@the@visualtipend}{\pgf@arrows@the@visualbackend}{}}% + % Save code (needed for bending) + \edef\pgf@arrow@code{% + \ifpgfarrowreversed\noexpand\pgftransformxscale{-1}\fi% + \expandafter\noexpand\csname pgf@ar@code@#1\endcsname% + }% + \expandafter\global\expandafter\let\csname pgf@ar@inst@code@\pgf@arrow@id\endcsname\pgf@arrow@code% + % Should we cache? + \expandafter\ifx\csname pgf@ar@do@cache@#1\endcsname\pgf@truetext% + \pgfsysprotocol@getcurrentprotocol\pgf@arrow@temp% + {% + \pgfinterruptpath% + \let\pgfusepath=\pgf@nousepath@here% + \pgf@relevantforpicturesizefalse% + \pgftransformreset% + \pgfsysprotocol@setcurrentprotocol\pgfutil@empty% + \pgfsysprotocol@bufferedtrue% + \pgfscope% + \pgf@arrow@code% + \endpgfscope% + \pgfsysprotocol@getcurrentprotocol\pgf@@arrow@temp% + \expandafter\gdef\expandafter\pgf@arrow@code\expandafter{\expandafter\pgfsysprotocol@literal\expandafter{\pgf@@arrow@temp}}% + \endpgfinterruptpath% + }% + \pgfsysprotocol@setcurrentprotocol\pgf@arrow@temp% + \fi% + \expandafter\global\expandafter\let\csname pgf@ar@cache@\pgf@arrow@id\endcsname\pgf@arrow@code% + }% +} +\def\pgf@truetext{true} + +% Ok, now run setup: +\def\pgf@arrows@copy@tipend{\pgf@arrows@the@tipend} +\def\pgf@arrows@copy@backend{\pgf@arrows@the@backend} +\def\pgf@arrows@copy@lineend{\pgf@arrows@the@lineend} +\def\pgf@arrows@zeropt{0pt}% + +\let\pgf@arrows@saves\pgfutil@empty% +\let\pgf@arrows@convexhull\pgfutil@empty% +\let\pgf@arrows@the@tipend\pgf@arrows@zeropt% +\let\pgf@arrows@the@backend\pgf@arrows@zeropt% +\let\pgf@arrows@the@lineend\pgf@arrows@zeropt% +\let\pgf@arrows@the@visualtipend\pgf@arrows@copy@tipend% +\let\pgf@arrows@the@visualbackend\pgf@arrows@copy@backend% + + +\def\pgf@arrows@handle@reverse{% + \pgf@x\pgf@arrows@the@visualtipend\pgf@x-\pgf@x% + \pgf@y\pgf@arrows@the@visualbackend\pgf@y-\pgf@y + \edef\pgf@arrows@the@visualtipend{\the\pgf@y}% + \edef\pgf@arrows@the@visualbackend{\the\pgf@x}% + \pgf@x\pgf@arrows@the@tipend\pgf@x-\pgf@x% + \pgf@y\pgf@arrows@the@backend\pgf@y-\pgf@y + \edef\pgf@arrows@the@tipend{\the\pgf@y}% + \edef\pgf@arrows@the@backend{\the\pgf@x}% + \pgf@x\pgf@arrows@the@lineend\pgf@x-\pgf@x\edef\pgf@arrows@the@lineend{\the\pgf@x}% + \let\pgf@temp\pgf@arrows@convexhull% + \let\pgf@arrows@convexhull\pgfutil@empty% + \let\pgf@arrow@hull@point\pgf@arrow@hull@point@reverse% + \pgf@temp% +} +\def\pgf@arrow@hull@point@reverse#1#2{% + \pgf@x#1% + \pgfarrowshullpoint{-\pgf@x}{#2}% +} + +\def\pgf@nousepath@here#1{\pgferror{The definition of an arrow may not use \string\pgfusepath}} + +\def\pgfarrowssavethe#1{% + \expandafter\expandafter\expandafter\def% + \expandafter\expandafter\expandafter\pgf@arrows@saves% + \expandafter\expandafter\expandafter{\expandafter\pgf@arrows@saves\expandafter#1\the#1\relax} +} + +\def\pgfarrowssave#1{% + \expandafter\expandafter\expandafter\def% + \expandafter\expandafter\expandafter\pgf@arrows@saves% + \expandafter\expandafter\expandafter{\expandafter\pgf@arrows@saves\expandafter\def\expandafter#1\expandafter{#1}} +} + +\def\pgfarrowshullpoint#1#2{% + \pgf@x#1\relax% + \pgf@y#2\relax% + \edef\pgf@arrows@temp{\noexpand\pgf@arrows@convexhull\noexpand\pgf@arrow@hull@point{\the\pgf@x}{\the\pgf@y}}% + \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\pgf@arrows@convexhull\expandafter\expandafter\expandafter{\pgf@arrows@temp}% +} + +\def\pgfarrowsupperhullpoint#1#2{% + \pgf@x#1\relax% + \pgf@y#2\relax% + \ifdim\pgf@y>0pt + \edef\pgf@arrows@temp{\noexpand\pgf@arrows@convexhull\noexpand\pgf@arrow@hull@point{\the\pgf@x}{\the\pgf@y}\ifpgfarrowharpoon\else\noexpand\pgf@arrow@hull@point{\the\pgf@x}{-\the\pgf@y}\fi}% + \else + \edef\pgf@arrows@temp{\noexpand\pgf@arrows@convexhull\noexpand\pgf@arrow@hull@point{\the\pgf@x}{\the\pgf@y}}% + \fi + \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\pgf@arrows@convexhull\expandafter\expandafter\expandafter{\pgf@arrows@temp}% +} + +\def\pgfarrowssettipend#1{\pgf@x#1\edef\pgf@arrows@the@tipend{\the\pgf@x}} +\def\pgfarrowssetbackend#1{\pgf@x#1\edef\pgf@arrows@the@backend{\the\pgf@x}} +\def\pgfarrowssetlineend#1{\pgf@x#1\edef\pgf@arrows@the@lineend{\the\pgf@x}} +\def\pgfarrowssetvisualtipend#1{\pgf@x#1\edef\pgf@arrows@the@visualtipend{\the\pgf@x}} +\def\pgfarrowssetvisualbackend#1{\pgf@x#1\edef\pgf@arrows@the@visualbackend{\the\pgf@x}} + + +% Internal computation of the line end (shortening) for an arrow +% +% #1 = arrow tip list +% +% Description: +% +% \pgf@xa will contain the necessary path shortening for the given +% arrow tip list, \pgf@xb will contain the total length of the arrow +% tip list (sum of the differences between tip end and back end plus +% the seps). + +\def\pgf@arrow@compute@shortening#1{% + \let\pgf@arrow@handle\pgf@arrow@compute@shortening@ + \let\pgf@arrow@handle@dot\pgf@arrow@after@line@endtrue% + \pgf@arrow@after@line@endfalse% + \pgf@xa0pt% + \pgf@xb0pt% + #1% +} +\newif\ifpgf@arrow@after@line@end + +\def\pgf@arrow@compute@shortening@#1#2{% + {\pgfarrows@getid{#1}{#2}\ifnum\pgf@arrow@flex@mode>0\relax\global\pgf@precise@shorteningtrue\fi\expandafter}\expandafter\pgf@x\the\pgfarrowsep% + \expandafter\expandafter\expandafter\pgf@arrow@cont@short\csname pgf@ar@ends@\pgf@arrow@id\endcsname% +} +\def\pgf@dot@text{.} + +\def\pgf@arrow@cont@short#1#2#3{% tip end, back end, line end, sep + \advance\pgf@xb by#1% + \pgf@xc#2% + \advance\pgf@xb by-\pgf@xc% + \advance\pgf@xb by\pgf@x% + \ifpgf@arrow@after@line@end% + \advance\pgf@xa by#1% + \advance\pgf@xa by\pgf@x% + \pgf@xc#2% + \advance\pgf@xa by-\pgf@xc% + \else% + \pgf@xa#1% + \advance\pgf@xa by\pgf@x% + \pgf@xc#3% + \advance\pgf@xa by-\pgf@xc% + \fi% +} + + + +\def\pgf@arrow@rigid@arrow#1#2{% + {% + \pgf@xb=#2% + \pgftransformxshift{-\pgf@xb}% + \let\pgf@arrow@handle\pgf@arrow@rigid + \let\pgf@arrow@handle@dot\relax% + #1% + }% +} + + +\def\pgf@arrow@rigid#1#2{% + % Prepare: + {% + \pgfarrows@getid{#1}{#2}% + % Do shift: + \expandafter\expandafter\expandafter\pgf@arrow@drawer@shift\csname pgf@ar@ends@\pgf@arrow@id\endcsname% + % Do slant: + \ifdim\pgfarrows@slant pt=0pt% + \else% + \pgftransformxslant{\pgfarrows@slant}% + \fi% + % do swap: + \ifpgfarrowswap% + \pgftransformyscale{-1}% + \fi% + {% + \csname pgf@ar@saves@\pgf@arrow@id\endcsname% + \pgf@arrows@rigid@hull% + }% + \expandafter}% + % Transform to next tip: + \expandafter\pgftransformxshift\expandafter{\the\pgf@xc}% +} + + + + +% Draw an arrow +% +% #1 = arrow tip list +% #2 = total length of the arrow (the value of \pgf@xb computed by +% \pgf@arrow@compute@shortening) +% +% Description: +% +% Draws an arrow tip list. The coordinate system must have been +% transformed so that the to-be-drawn arrow points right and should +% "end" at the origin. + +\def\pgf@arrow@draw@arrow#1#2{% + {% + \pgf@xb=#2% + \pgftransformxshift{-\pgf@xb}% + \let\pgf@arrow@handle\pgf@arrow@drawer + \let\pgf@arrow@handle@dot\relax% + #1% + }% +} + + +\def\pgf@arrow@drawer#1#2{% + % Prepare: + {% + \pgfarrows@getid{#1}{#2}% + % Do shift: + \expandafter\expandafter\expandafter\pgf@arrow@drawer@shift\csname pgf@ar@ends@\pgf@arrow@id\endcsname% + % Do slant: + \ifdim\pgfarrows@slant pt=0pt% + \else% + \pgftransformxslant{\pgfarrows@slant}% + \fi% + % do swap: + \ifpgfarrowswap% + \pgftransformyscale{-1}% + \fi% + {% + \csname pgf@ar@saves@\pgf@arrow@id\endcsname% + \pgfscope% + \pgf@arrows@color@setup% + \pgflowlevelsynccm\csname pgf@ar@cache@\pgf@arrow@id\endcsname% + \endpgfscope% + \pgf@arrows@rigid@hull% + }% + \expandafter}% + % Transform to next tip: + \expandafter\pgftransformxshift\expandafter{\the\pgf@xc}% +} + +\def\pgf@arrows@color@setup@restore@std@colors{% + % we want to allow 'arrows={fill=pgffillcolor}'. To this end, we have to ensure that \string\color@pgffillcolor is known. + % we can safely keep the macro in the current TeX group since it has global character anyway. + % + % Note that declaring \string\color@pgfstrokecolor as \global macro causes save stack issues and should be avoided. + \pgfutil@namelet{\string\color@pgfstrokecolor}{pgf@strokecolor@global}% + \pgfutil@namelet{\string\color@pgffillcolor}{pgf@fillcolor@global}% + % +}% + +\def\pgf@arrows@color@setup{% + \ifx\pgf@arrows@stroke@color\pgfutil@empty\else\pgfsetstrokecolor{\pgf@arrows@stroke@color}\fi% + \ifx\pgf@arrows@fill@color\pgfutil@empty% + \ifx\pgf@strokecolor@global\pgf@fillcolor@global + \else + \pgf@arrows@color@setup@restore@std@colors + \pgfsetfillcolor{pgfstrokecolor}% + \fi% + \else% + \pgf@arrows@color@setup@restore@std@colors + \pgfsetfillcolor{\pgf@arrows@fill@color}% + \fi% +} + +\def\pgf@arrow@drawer@shift#1#2#3{% tip end, back end, line end, sep + \pgf@xb#2\pgftransformxshift{-\pgf@xb}% + \pgf@xc#1% + \advance\pgf@xc by\pgfarrowsep% + \advance\pgf@xc by-\pgf@xb% +} + +\def\pgf@arrows@rigid@hull{% + \ifpgf@relevantforpicturesize% + % Do bb update: + \expandafter\let\expandafter\pgf@temp\csname pgf@ar@hull@\pgf@arrow@id\endcsname% + \ifx\pgf@temp\pgfutil@empty\else% + \let\pgf@arrow@hull@point\pgf@arrow@hull@point@first% + \pgf@temp% + \pgf@arrow@update@bb% + \fi% + \fi +} + + +% Convex hull stuff: + +\def\pgf@arrow@hull@point@first#1#2{% +% {\pgfsys@beginscope\pgfpathcircle{\pgfqpoint{#1}{#2}}{0.5pt}\pgfusepathqfill\pgfsys@endscope}% + \pgf@x#1\pgf@y#2% + \pgf@xa\pgf@pt@aa\pgf@x% + \advance\pgf@xa by\pgf@pt@ba\pgf@y% + \pgf@ya\pgf@pt@ab\pgf@x% + \advance\pgf@ya by\pgf@pt@bb\pgf@y% + \pgf@xb\pgf@xa\pgf@yb\pgf@ya% + \let\pgf@arrow@hull@point\pgf@arrow@hull@point@other% +} +\def\pgf@arrow@hull@point@other#1#2{% +% {\pgfsys@beginscope\pgfpathcircle{\pgfqpoint{#1}{#2}}{0.5pt}\pgfusepathqfill\pgfsys@endscope}% + \pgfutil@tempdima#1\pgfutil@tempdimb#2% + \pgf@x\pgf@pt@aa\pgfutil@tempdima% + \advance\pgf@x by\pgf@pt@ba\pgfutil@tempdimb% + \pgf@y\pgf@pt@ab\pgfutil@tempdima% + \advance\pgf@y by\pgf@pt@bb\pgfutil@tempdimb% + \ifdim\pgf@x<\pgf@xa\pgf@xa\pgf@x\else\ifdim\pgf@x>\pgf@xb\pgf@xb\pgf@x\fi\fi% + \ifdim\pgf@y<\pgf@ya\pgf@ya\pgf@y\else\ifdim\pgf@y>\pgf@yb\pgf@yb\pgf@y\fi\fi% +} + +\def\pgf@arrow@update@bb{% + \advance\pgf@xa by\pgf@pt@x% + \advance\pgf@ya by\pgf@pt@y% + \advance\pgf@xb by\pgf@pt@x% + \advance\pgf@yb by\pgf@pt@y% + \ifdim\pgf@picmaxx=-16000pt\relax% + \global\pgf@picminx\pgf@xa% + \global\pgf@picmaxx\pgf@xb% + \global\pgf@picminy\pgf@ya% + \global\pgf@picmaxy\pgf@yb% + \else% + \ifdim\pgf@xa<\pgf@picminx\global\pgf@picminx\pgf@xa\fi% + \ifdim\pgf@ya<\pgf@picminy\global\pgf@picminy\pgf@ya\fi% + \ifdim\pgf@xb>\pgf@picmaxx\global\pgf@picmaxx\pgf@xb\fi% + \ifdim\pgf@yb>\pgf@picmaxy\global\pgf@picmaxy\pgf@yb\fi% + \fi% +} + + + +% Sets arrows +% +% #1 = An arrow specification of the form +% <start spec>-<end spec>. This will call \pgfsetstartarrow{start +% spec} and \pgfsetendarrow{end spec}. +% +% Alternatively, it may be of the form [options]. In this case, +% the arrow options are set for the local scope and all arrows in +% the current scope will have these options set. +% +% Example: +% +% \pgfsetarrows{-to} + +\def\pgfsetarrows#1{\pgf@arrows#1\pgf@stop} +\def\pgf@arrows{\pgfutil@ifnextchar[\pgf@arrows@test@opt\pgf@arrows@}%} +\def\pgf@arrows@#1-#2\pgf@stop{% + \pgfsetarrowsstart{#1}% + \pgfsetarrowsend{#2}% +} +\def\pgf@arrows@test@opt[{% + \pgfutil@ifnextchar-{\pgf@arrows@[}%} go back to normal reading for compat. reasons. + \pgf@arrows@test@opt@% +} +\def\pgf@arrows@test@opt@#1]{% + \pgfutil@ifnextchar\pgf@stop{% + \let\pgf@arrows@options\pgf@arrows@options@scope% + \pgfkeys{/pgf/arrow keys/.cd,#1}% + \let\pgf@arrows@options@scope\pgf@arrows@options% + % Ok, setup the options + \pgfutil@gobble% + }{% + \pgf@arrows@[#1]% Oops: go back to normal mode + }% +} + +\let\pgf@arrows@options@scope\pgfutil@empty + + + + +% +% Predefined arrows: +% + + +% A dot is used to indicate the end of the line: + +\pgfdeclarearrow{ + name = ., + drawing code = +} + + +% An underscore adds a space as in >_> or >_Â >. However, it will be +% faster to say ">[sep] >" or ">[sep=2pt] >". + +\pgfdeclarearrow{ + name = _, + defaults = {sep}, + drawing code = +} + + + +% Default shorthands: + +\pgfdeclarearrow{ name = To, means = } % forward declaration +\pgfdeclarearrow{ name = Bar, means = } % forward declaration +\pgfkeys{ + <-> /.tip = {To}, + >-< /.tip = {>[reversed]}, + | /.tip = {Bar} +} + + + +% Compatibility with old arrow system: + +\pgfkeys {} + +\def\pgf@arrows@direct@def#1#2{\expandafter\pgf@arrows@direct@def@\expandafter{\csname pgf@ar@means@#2\endcsname}{#1}} +\def\pgf@arrows@direct@def@#1#2{\expandafter\def\csname pgf@arrows@direct@name@#2\endcsname{\pgf@arrow@handle@shorthand@empty{#1}}} +\pgf@arrows@direct@def{start@[}{]} +\pgf@arrows@direct@def{start@]}{[} +\pgf@arrows@direct@def{start@spaced [}{spaced ]} +\pgf@arrows@direct@def{start@spaced ]}{spaced [} +\pgf@arrows@direct@def{end@[}{[} +\pgf@arrows@direct@def{end@]}{]} +\pgf@arrows@direct@def{end@spaced [}{spaced [} +\pgf@arrows@direct@def{end@spaced ]}{spaced ]} + +\def\pgfsetarrowoptions#1#2{\expandafter\def\csname pgf@arrow@compat@opt@#1\endcsname{#2}} +\def\pgfgetarrowoptions#1{\csname pgf@arrow@compat@opt@#1\endcsname} +\def\pgfarrowsdeclare#1#2#3#4{% + \pgfdeclarearrow{ name ={#1}-{#2}, setup code ={#3}, drawing code={#4}, parameters/.expand once={\csname pgf@arrow@compat@opt@#2\endcsname}}% + \expandafter\def\csname pgf@arrow@compat@opt@#2\endcsname{0}} +\def\pgfarrowsleftextend#1{\pgfmathsetlength\pgf@xa{#1}\pgfarrowssetbackend{\pgf@xa}} +\def\pgfarrowsrightextend#1{\pgfmathsetlength\pgf@xb{#1}\pgfarrowssettipend{\pgf@xb}} +\def\pgfarrowsdeclarealias#1#2#3#4{\pgfdeclarearrow{ name ={#1}-{#2}, means ={#4} } } +\def\pgfarrowsdeclarereversed#1#2#3#4{\pgfdeclarearrow{ name ={#1}-{#2}, means={{#4}[reversed]}}} +\def\pgfarrowsdeclarecombine{\pgfutil@ifnextchar*{\pgfarrowsdeclarecombine@star}{\pgf@@arrowsdeclarecombine}} +\def\pgf@@arrowsdeclarecombine{\pgfutil@ifnextchar[{\pgf@arrowsdeclarecombine}{\pgf@arrowsdeclarecombine[0pt]}} +\def\pgf@arrowsdeclarecombine[#1]#2#3#4#5#6#7{\def\pgf@@temp{#1}\ifx\pgf@@temp\pgf@linewidthtext\def\pgf@@temp{+0pt 1}\fi% + \pgfdeclarearrow{name ={#2}-{#3}, means={#5[sep/.expand once=\pgf@@temp]#6}}} +\def\pgf@linewidth@text{\pgflinewidth} +\def\pgfarrowsdeclarecombine@star*{\pgfutil@ifnextchar[{\pgf@arrowsdeclarecombine@star}{\pgf@arrowsdeclarecombine@star[0pt]}} +\def\pgf@arrowsdeclarecombine@star[#1]#2#3#4#5#6#7{\def\pgf@@temp{#1}\ifx\pgf@@temp\pgf@linewidthtext\def\pgf@@temp{+0pt 1}\fi% + \pgfdeclarearrow{name ={#2}-{#3}, means={#5[sep/.expand once=\pgf@@temp].#6}}} +\def\pgfarrowsdeclaredouble{\pgfutil@ifnextchar[{\pgf@arrowsdeclaredouble}{\pgf@arrowsdeclaredouble[0pt]}} +\def\pgf@arrowsdeclaredouble[#1]#2#3#4#5{\pgfarrowsdeclarecombine[#1]{#2}{#3}{#4}{#5}{#4}{#5}} +\def\pgfarrowsdeclaretriple{\pgfutil@ifnextchar[{\pgf@arrowsdeclaretriple}{\pgf@arrowsdeclaretriple[0pt]}} +\def\pgf@arrowsdeclaretriple[#1]#2#3#4#5{ \pgfarrowsdeclarecombine[#1]{pgf@trip@#2}{pgf@trip@#3}{#4}{#5}{#4}{#5}% + \pgfarrowsdeclarecombine[#1]{#2}{#3}{pgf@trip@#2}{pgf@trip@#3}{#4}{#5}} +\def\pgf@linewidthtext{\pgflinewidth} + +\pgfarrowsdeclare{stealth}{stealth} +{ + \pgfutil@tempdima=0.28pt% + \pgfutil@tempdimb=\pgflinewidth% + \ifdim\pgfinnerlinewidth>0pt% + \pgfmathsetlength\pgfutil@tempdimb{.6\pgflinewidth-.4*\pgfinnerlinewidth}% + \fi% + \advance\pgfutil@tempdima by.3\pgfutil@tempdimb% + \pgfarrowsleftextend{+-3\pgfutil@tempdima} + \pgfarrowsrightextend{+5\pgfutil@tempdima} +} +{ + \pgfutil@tempdima=0.28pt% + \pgfutil@tempdimb=\pgflinewidth% + \ifdim\pgfinnerlinewidth>0pt% + \pgfmathsetlength\pgfutil@tempdimb{.6\pgflinewidth-.4*\pgfinnerlinewidth}% + \fi% + \advance\pgfutil@tempdima by.3\pgfutil@tempdimb% + \pgfpathmoveto{\pgfqpoint{5\pgfutil@tempdima}{0pt}} + \pgfpathlineto{\pgfqpoint{-3\pgfutil@tempdima}{4\pgfutil@tempdima}} + \pgfpathlineto{\pgfpointorigin} + \pgfpathlineto{\pgfqpoint{-3\pgfutil@tempdima}{-4\pgfutil@tempdima}} + \pgfusepathqfill +} +\pgfarrowsdeclarereversed{stealth reversed}{stealth reversed}{stealth}{stealth} +\pgfarrowsdeclare{to}{to} +{ + \pgfutil@tempdima=-0.84pt% + \advance\pgfutil@tempdima by-1.3\pgflinewidth% + \pgfutil@tempdimb=0.21pt% + \advance\pgfutil@tempdimb by.625\pgflinewidth% + \pgfarrowsleftextend{+\pgfutil@tempdima} + \pgfarrowsrightextend{+\pgfutil@tempdimb} +} +{ + \pgfutil@tempdima=0.28pt% + \advance\pgfutil@tempdima by.3\pgflinewidth% + \pgfsetlinewidth{0.8\pgflinewidth} + \pgfsetdash{}{+0pt} + \pgfsetroundcap + \pgfsetroundjoin + \pgfpathmoveto{\pgfqpoint{-3\pgfutil@tempdima}{4\pgfutil@tempdima}} + \pgfpathcurveto + {\pgfqpoint{-2.75\pgfutil@tempdima}{2.5\pgfutil@tempdima}} + {\pgfqpoint{0pt}{0.25\pgfutil@tempdima}} + {\pgfqpoint{0.75\pgfutil@tempdima}{0pt}} + \pgfpathcurveto + {\pgfqpoint{0pt}{-0.25\pgfutil@tempdima}} + {\pgfqpoint{-2.75\pgfutil@tempdima}{-2.5\pgfutil@tempdima}} + {\pgfqpoint{-3\pgfutil@tempdima}{-4\pgfutil@tempdima}} + \pgfusepathqstroke +} +\pgfkeys{To /.tip = to} +\pgfarrowsdeclare{to reversed}{to reversed} +{ + \pgfutil@tempdima=-0.21pt% + \advance\pgfutil@tempdima by-0.475\pgflinewidth% + \pgfutil@tempdimb=0.98pt% + \advance\pgfutil@tempdimb by1.45\pgflinewidth% + \pgfarrowsleftextend{+\pgfutil@tempdima} + \pgfarrowsrightextend{+\pgfutil@tempdimb} +} +{ + \pgfutil@tempdima=0.28pt% + \advance\pgfutil@tempdima by.3\pgflinewidth% + \pgfsetlinewidth{+0.8\pgflinewidth} + \pgfsetdash{}{+0pt} + \pgfsetroundcap + \pgfsetroundjoin + \pgfpathmoveto{\pgfqpoint{3.5\pgfutil@tempdima}{4\pgfutil@tempdima}} + \pgfpathcurveto + {\pgfqpoint{3.25\pgfutil@tempdima}{2.5\pgfutil@tempdima}} + {\pgfqpoint{0.5\pgfutil@tempdima}{0.25\pgfutil@tempdima}} + {\pgfqpoint{-0.25\pgfutil@tempdima}{0\pgfutil@tempdima}} + \pgfpathcurveto + {\pgfqpoint{0.5\pgfutil@tempdima}{-0.25\pgfutil@tempdima}} + {\pgfqpoint{3.25\pgfutil@tempdima}{-2.5\pgfutil@tempdima}} + {\pgfqpoint{3.5\pgfutil@tempdima}{-4\pgfutil@tempdima}} + \pgfusepathqstroke +} +\pgfarrowsdeclare{latex}{latex} +{ + \pgfutil@tempdima=0.28pt% + \pgfutil@tempdimb=\pgflinewidth% + \ifdim\pgfinnerlinewidth>0pt% + \pgfmathsetlength\pgfutil@tempdimb{.6\pgflinewidth-.4*\pgfinnerlinewidth}% + \fi% + \advance\pgfutil@tempdima by.3\pgfutil@tempdimb% + \pgfarrowsleftextend{+-1\pgfutil@tempdima} + \pgfarrowsrightextend{+9\pgfutil@tempdima} +} +{ + \pgfutil@tempdima=0.28pt% + \pgfutil@tempdimb=\pgflinewidth% + \ifdim\pgfinnerlinewidth>0pt% + \pgfmathsetlength\pgfutil@tempdimb{.6\pgflinewidth-.4*\pgfinnerlinewidth}% + \fi% + \advance\pgfutil@tempdima by.3\pgfutil@tempdimb% + \pgfpathmoveto{\pgfqpoint{9\pgfutil@tempdima}{0pt}} + \pgfpathcurveto + {\pgfqpoint{6.3333\pgfutil@tempdima}{.5\pgfutil@tempdima}} + {\pgfqpoint{2\pgfutil@tempdima}{2\pgfutil@tempdima}} + {\pgfqpoint{-1\pgfutil@tempdima}{3.75\pgfutil@tempdima}} + \pgfpathlineto{\pgfqpoint{-1\pgfutil@tempdima}{-3.75\pgfutil@tempdima}} + \pgfpathcurveto + {\pgfqpoint{2\pgfutil@tempdima}{-2\pgfutil@tempdima}} + {\pgfqpoint{6.3333\pgfutil@tempdima}{-.5\pgfutil@tempdima}} + {\pgfqpoint{9\pgfutil@tempdima}{0pt}} + \pgfusepathqfill +} +\pgfarrowsdeclarereversed{latex reversed}{latex reversed}{latex}{latex} +\pgfarrowsdeclare{@bar}{@bar} +{ + \pgfarrowsleftextend{+-0.25\pgflinewidth} + \pgfarrowsrightextend{+.75\pgflinewidth} +} +{ + \pgfutil@tempdima=2pt% + \advance\pgfutil@tempdima by1.5\pgflinewidth% + \pgfsetdash{}{+0pt} + \pgfsetrectcap + \pgfpathmoveto{\pgfqpoint{0.25\pgflinewidth}{-\pgfutil@tempdima}} + \pgfpathlineto{\pgfqpoint{0.25\pgflinewidth}{\pgfutil@tempdima}} + \pgfusepathqstroke +} +\pgfkeys{Bar /.tip = @bar} +\pgfarrowsdeclare{space}{space} +{ + \pgfutil@tempdima=0.88pt% + \advance\pgfutil@tempdima by.3\pgflinewidth% + \pgfarrowsleftextend{0pt} + \pgfarrowsrightextend{\pgfutil@tempdima} +} +{} + + + +\endinput diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcoreexternal.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcoreexternal.code.tex new file mode 100644 index 0000000000..f6fef57755 --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcoreexternal.code.tex @@ -0,0 +1,542 @@ +% Copyright 2019 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{pgfcoreexternal.code.tex} + + + +\newif\ifpgfexternal@aux@in@dpth +\newif\ifpgfexternal@info + +\pgfkeys{ + /pgf/images/include external/.code={\pgfimage{#1}}, + /pgf/images/aux in dpth/.is if=pgfexternal@aux@in@dpth, + /pgf/images/aux in dpth/.default=true, + /pgf/images/trim external/.code n args={4}{% + \def\pgf@external@kern@left{#1}% + \def\pgf@external@kern@bottom{#2}% + \def\pgf@external@kern@right{#3}% + \def\pgf@external@kern@top{#4}% + \ifx\pgf@external@kern@left\pgfutil@empty\def\pgf@external@kern@left{0sp}\fi% + \ifx\pgf@external@kern@bottom\pgfutil@empty\def\pgf@external@kern@bottom{0sp}\fi% + \ifx\pgf@external@kern@right\pgfutil@empty\def\pgf@external@kern@right{0sp}\fi% + \ifx\pgf@external@kern@top\pgfutil@empty\def\pgf@external@kern@top{0sp}\fi% + }, + /pgf/images/trim external={1truein}{1truein}{1truein}{1truein}, + /pgf/images/external info/.is if=pgfexternal@info, + /pgf/images/external info/.default=true, +} + +% The external read/write mechanism is used as follows: +% +% In your document, you put a number or all of your pgfpicture (or +% tikzpicture) environments inside a pair of \beginpgfexternal and +% \endpgfexternal. The \beginpgfexternal gets one parameter called the +% graphics name. +% +% Once this is done, the next step is to declare the names of your +% graphics in the document at the beginning using the +% \pgfdeclaregraphicname command. +% +% Now, when you typeset your document, each time a \beginpgfexternal +% command is encountered, it will be checked whether the corresponding +% graphics file exists. If this is the case, it will be included and +% the code between \beginpgfexternal and \endpgfexternal is +% ignored. Otherwise, the code is executed normally. +% +% Things change when you run tex on your file with the \jobname set to +% the name of a declared graphics name. In this case, only your +% graphic will be typeset, the rest of the document will be "thrown away". +% To be more precise, everything is gobbled up to the beginning +% of the first \beginpgfexternal with the given graphics name. Then, +% the content of the "environment" is put in a box (this "environment" +% need not contain a graphics, it may contain anything that can be put +% in a box). Then a single page is output whose size is exactly the +% size of the picture. +% +% So, once you have run tex repeatedly, each time with the jobname set +% to each of the graphics, you can then run tex on the whole document +% and this will cause all graphics to be included rather than begin +% typeset. +% +% Finally, once all the graphics have been created, you can also say +% \input pgfexternal.tex instead of including pgf/TikZ. + + +\newif\ifpgfexternalreadmainaux +\pgfexternalreadmainauxtrue + +% Tells pgf which jobname is the name of the real file +% +% #1 = name +% +% Description: +% +% This command is used to tell pgf that the file named #1 should be +% typeset normally. If \jobname is not equal to #1, only +% the graphic called \jobname will be typeset. +% +% Example: +% +% \pgfrealjobname{survey} +% +% Note that afterwards, \jobname will be set to the argument. In our +% example, \jobname will be 'survey'. This is to accomplish +% compatibility with aux-file generation. + +\def\pgfrealjobname#1{% + \global\let\pgfactualjobname=\jobname + \edef\pgf@tempa{\expandafter\string\csname #1\endcsname}% + \edef\pgf@tempb{\expandafter\string\csname\jobname\endcsname}% + \ifx\pgf@tempa\pgf@tempb% + \else% + \pgf@external@grabshipouttrue% + \pgfexternal@nofiles% see also \pgf@external@init@aux@in@dpth + \ifpgfexternalreadmainaux + % and reset the jobname. This should allow to handle any + % \label/\ref constructions which are stored in \jobname.aux (and + % which won't be found otherwise) + \gdef\jobname{#1}% + \fi + \ifpgfexternal@aux@in@dpth + \csname newwrite\endcsname\w@pgfexternal@auxout + \fi + \pgfexternal@geometry@compatibility + \fi% + \gdef\pgfrealjobname##1{}% avoid multiple calls. +} + +\def\pgfexternal@geometry@compatibility{% + % check if \usepackage{geometry} is loaded: + \pgfutil@ifundefined{geometry}{% + }{% + % The geometry package hooks into \begin{document}, evaluates + % its driver -- and generates \special instructions to set the + % paper size. + % + % Unfortunately, this confuses dvips utterly - and perhaps + % other drivers as well. + % + % Thus, if we currently about to generate some external + % graphics, we WANT to disable geometry (it has no purpose in + % this context anyway). + % + % This here works well: + \pgf@typeout{Package TikZ externalization: calling \string\geometry{driver=none} during externalization.^^J}% + \geometry{driver=none}% + }% +}% + +\def\pgfexternal@nofiles{% + % replace \relax. The \nofiles macros does + % \let\makeglossary=\relax + % but the glossary.sty calls \renewcommand\makeglossary (which + % will fail if \makeglossary=\relax). Stupid, but it works. + \let\pgfexternal@nofiles@=\relax + \def\relax{\relax}% + % + % suppress generation of LaTeX .aux, .toc etc files. + % generation of these files is not thread-safe. + % the \csname \endcsname yields \relax if \nofiles doesn't exist. + \csname nofiles\endcsname + % + \let\relax=\pgfexternal@nofiles@ +}% + +\newif\ifpgf@external@grabshipout +\newbox\pgfexternal@startupbox + +\pgfutil@ifundefined{AtBeginDocument}{}{% + \AtBeginDocument{% + \ifpgf@external@grabshipout% + \global\let\pgfexternal@originalshipout=\shipout% + \global\def\shipout{\setbox\pgfpic=}% + \maxdeadcycles=10000% + % Ok, gather everything we have seen up to now in a box. This box + % will contain any specials that have been used. + {% + \output{\global\setbox\pgfexternal@startupbox=\vbox{\csname @begindvi\endcsname\unvbox255}}% + \hbox{}\eject% + }% + \fi% + } +}% + +\pgfutil@ifundefined{AtEndDocument}{}{% + \AtEndDocument{% + \ifpgf@external@grabshipout + \pgfutil@ifundefined{pgfexternal@did@a@shipout}{% + \pgfexternal@error@no@shipout + }{}% + \fi + }% +} + +% This will be overwritten by the tikz external lib if it is loaded. +\def\pgfexternal@error@no@shipout{% + \pgferror{Sorry, image externalization failed: the resulting image was EMPTY. I tried to externalize '\pgfactualjobname'. Perhaps there was a typo somewhere? Please check that your document contains '\string\beginpgfgraphicnamed{\pgfactualjobname} ... \string\endpgfgraphicnamed'}% +}% + + +% "Environment" for an external graphic. +% +% #1 = graphic name +% +% Example: +% +% \beginpgfgraphicnamed{main-graphic2} +% \begin{tikzpicture} +% ... +% \end{tikzpicture} +% \endpgfgraphicnamed + +\def\pgf@externalbegin#1{% + % First, check whether we wish to grab this graphic: + \let\pgf@next=\pgf@external@normal% + \ifpgf@external@grabshipout% + \edef\pgf@tempa{\expandafter\string\csname #1\endcsname}% + \edef\pgf@tempb{\expandafter\string\csname\pgfactualjobname\endcsname}% + \ifx\pgf@tempa\pgf@tempb% + \let\pgf@next=\pgf@external@grab% + \fi% + \fi% + \pgf@next{#1}% +} + + +\AtBeginDocument{ + \let\beginpgfgraphicnamed=\pgf@externalbegin% overwrite definition of pgfexternal.tex if necessary + \let\endpgfgraphicnamed=\unskip +} + + +% Normal operation: Include an external graphic instead of the +% picture, if such an external picture exists. +\def\pgf@external@normal#1{% + \let\pgf@filename=\pgfutil@empty% + \expandafter\pgf@findfile\pgfsys@imagesuffixlist:+{#1}% + \ifx\pgf@filename\pgfutil@empty% + % Ok, no such image... Just typeset the picture normally. + \let\pgf@next=\relax% + \else% + \let\pgf@next=\pgf@replacepicturebygraphic% + \fi% + \pgf@next% +} + +\long\def\pgf@replacepicturebygraphic#1\endpgfgraphicnamed{% + \expandafter\pgfincludeexternalgraphics\expandafter{\pgf@filename}\unskip +} + +% This is almost the same as \includegraphics{#1}, but it checks +% whether '#1.dpth' exists. In such case, it restores the boxes depth +% stored in #1.dpth. +% +% Furthermore, the .dpth file may contain .aux related information +% collected for the external graphics (references). They start after +% the first line (if any). +\def\pgfincludeexternalgraphics#1{% + \begingroup + \pgfexternalreaddpth{#1}% + \pgfkeysifdefined{/pgf/images/include external/#1/.@cmd}{% + \pgfkeysgetvalue{/pgf/images/include external/#1/.@cmd}\pgf@tempa + \pgfkeyslet{/pgf/images/include external/.@cmd}\pgf@tempa + }{}% + \setbox1=\hbox{\pgfkeysvalueof{/pgf/images/include external/.@cmd}{#1}\pgfeov}% + \ifdim\pgfexternaltrimleft=0sp \else \kern\pgfexternaltrimleft\relax \fi + \ifdim\pgfexternaldepth=0pt + \box1 + \else + \dimen0=\pgfexternaldepth\relax + \hbox{\lower\dimen0 \box1 }% + \fi + \ifdim\pgfexternaltrimright=0sp \else \kern\pgfexternaltrimright\relax \fi + \endgroup +} + +% Reads the .dpth file which contains meta data of the external +% picture. +% +% This command handles the following stuff: +% - it defines \pgfexternaldepth . The macro contains the contents of +% a line which does not start with a control sequence (for example a +% line containing '50pt') +% - it defines \pgfexternaltrimleft and \pgfexternaltrimright +% - it checks if the .dpth file contains content stored by means of +% \pgfexternalstorecommand. If so, the argument of +% \pgfexternalstorecommand will be restored. +% - anything else will be appended to the main .aux file, assuming that +% it contains \label or \ref information (only if the LaTeX switch +% \if@filesw is \iftrue). +% +% +% #1: the image file name (such that #1.dpth exists) +\def\pgfexternalreaddpth#1{% + % no \begingroup. Handle that manually: + \edef\pgfexternalreaddpth@restore{% + \noexpand\endlinechar=\the\endlinechar\space + \noexpand\catcode`\noexpand\@=\the\catcode`\@\space + }% + % + \def\pgfexternaldepth{0sp}% + \def\pgfexternaltrimleft{0sp}% + \def\pgfexternaltrimright{0sp}% + \endlinechar=-1 % suppress white space at end + \catcode`\@=11 + \openin\r@pgf@reada=#1.dpth + \pgfincludeexternalgraphics@read@dpth + % + \pgfexternalreaddpth@restore +}% +% +% The .dpth consists of 0-N lines, where each is either a single +% dimension (the box' depth) or something which belongs to the .aux +% file (such lines will always start with a macro). +\def\pgfincludeexternalgraphics@read@dpth{% + \ifeof\r@pgf@reada + \closein\r@pgf@reada + \else + \read\r@pgf@reada to\pgfincludeexternalgraphics@auxline + \ifx\pgfincludeexternalgraphics@auxline\pgfutil@empty + \else + \expandafter\pgfincludeexternalgraphics@read@dpth@line\pgfincludeexternalgraphics@auxline\pgfincludeexternalgraphics@read@dpth@line@EOI + \fi + \expandafter\pgfincludeexternalgraphics@read@dpth + \fi +}% + +\def\pgfexternal@restore#1{#1}% + +\long\def\pgfincludeexternalgraphics@read@dpth@line@getfirst#1#2\pgfincludeexternalgraphics@read@dpth@line@EOI{% + \def\pgf@first{#1}% +}% +\long\def\pgfincludeexternalgraphics@read@dpth@line#1\pgfincludeexternalgraphics@read@dpth@line@EOI{% + \pgfincludeexternalgraphics@read@dpth@line@getfirst#1\pgfincludeexternalgraphics@read@dpth@line@EOI + \expandafter\ifcat\expandafter\noexpand\pgf@first\relax + % Ah -- the first token is a control sequence. It belongs to + % the .aux file. + % + \expandafter\ifx\pgf@first\pgfexternal@restore + % if the first line in the .dpth file starts with the + % magic string \pgfexternal@restore, the complete line + % will be executed as-is. Example: + % \pgfexternal@restore{\def\somevalue{1}} + #1% + \else + % do NOT execute #1! many LaTeX commands don't support it (\label for example) + \pgfutil@ifundefined{if@filesw}{% + % sorry, .aux file support only for latex + }{% + % append to main .aux file (for forward references) + \if@filesw + {% + \toks0={#1}% + % believe it or not, but the + % \def\dpthimport{...}\dpthimport *makes* a + % difference! In ensures any occurring `##' characters are properly expanded to `#'. + \immediate\write\@auxout{% + \noexpand\def\noexpand\dpthimport{\the\toks0}\noexpand\dpthimport}% + }% + \fi + }% + \fi + \else% it is the depth (which is simply a number for backwards compatibility) + \def\pgfexternaldepth{#1}% + \fi +}% + +% Stores '#1' (expanded!) into the .dpth file of the currently +% exported image. +% +% This command has only an effect if an image is being exported. +% +% The stored contents will be read in the context where +% /pgf/images/include external is active (i.e. by +% \pgfexternalreaddpth). +% +\def\pgfexternalstorecommand#1{% +}% +\def\pgfexternalstorecommand@isexporting#1{% + \immediate\write\w@pgfexternal@auxout{\noexpand\pgfexternal@restore{#1}}% +}% + + + +% Grab operation: If jobname matches the graphic name, typeset this +% picture normal. +% REMARK: +% this method is also invoked from within the tikz external library. +\def\pgf@external@grab#1{% + \def\pgf@filename{#1}% + \ifpgfexternal@aux@in@dpth + \begingroup + \pgf@external@init@aux@in@dpth + \let\G@refundefinedtrue=\pgf@external@grab@refundefinedtrue + \fi + \gdef\pgf@trimleft@final{0sp}% + \gdef\pgf@trimright@final{0sp}% + \setbox\pgfpic=\hbox\bgroup\bgroup% + \let\endpgfgraphicnamed=\pgf@externalend% +} + +{\catcode`\^=12 \gdef\pgfexternal@hat{^}} + +\expandafter\let\expandafter\pgf@external@grab@refundefinedtrue@orig\csname G@refundefinedtrue\endcsname + +\def\pgf@external@grab@refundefinedtrue{% + \pgf@external@grab@refundefinedtrue@orig + \begingroup + \def\n{\pgfexternal@hat\pgfexternal@hat J}% + \pgfexternalstorecommand{% + \pgf@external@grab@refundefinedtrue@code + \noexpand\immediate\noexpand\write16{\pgf@external@grab@refundefinedtrue@warning}% + \noexpand\G@refundefinedtrue + }% + \endgroup +}% + +% A hook. will be overwritten by \usetikzlibrary{external} +\def\pgf@external@grab@refundefinedtrue@code{} + +\def\pgf@external@grab@refundefinedtrue@warning{% + LaTeX Warning: External picture `\pgfactualjobname' contains undefined references\noexpand\on@line.\n +}% + +\let\pgf@external@@protected@write@orig=\protected@write +\long\def\pgf@external@@protected@write@immediate#1#2#3{% + \begingroup + \let\pgf@write@=\write + \def\write{\noexpand\immediate\pgf@write@}% + \pgf@external@@protected@write@orig{#1}{#2}{#3}% + \endgroup +}% + +\def\pgf@external@init@aux@in@dpth{% + \let\pgfexternalstorecommand=\pgfexternalstorecommand@isexporting + % + % tell LaTeX to write aux files... + \csname @fileswtrue\endcsname + % ... but redirect output to the .dpth file! + \immediate\openout\w@pgfexternal@auxout=\pgf@filename.dpth + \let\@auxout=\w@pgfexternal@auxout + % ... and disable the correct page numbers. I can't get that + % (because the correct page number is only available in the + % shipout routine). Use immediate output: + \let\protected@write=\pgf@external@@protected@write@immediate +}% + +\def\pgf@externalend@storeshifts#1{% + \immediate\write#1{\the\dp\pgfpic}% store the depth simply as number for backw. compat. + \ifx\pgf@trimleft@final\pgfutil@empty\else + \immediate\write#1{\noexpand\pgfexternal@restore{\noexpand\def\noexpand\pgfexternaltrimleft{\pgf@trimleft@final}}}% + \fi + \ifx\pgf@trimright@final\pgfutil@empty\else + \immediate\write#1{\noexpand\pgfexternal@restore{\noexpand\def\noexpand\pgfexternaltrimright{\pgf@trimright@final}}}% + \fi + \ifpgfexternal@info + \immediate\write#1{\noexpand\pgfexternal@restore{\noexpand\def\noexpand\pgfexternalwidth{\the\wd\pgfpic}}}% + \immediate\write#1{\noexpand\pgfexternal@restore{\noexpand\def\noexpand\pgfexternalheight{\the\dimen0}}}% + \fi +} +% REMARK: +% this method is also invoked from within the tikz external library. +\def\pgf@externalend{% + \unskip\egroup\egroup% + {% + \def\pgf@external@trim{0}% + \def\pgf@external@store@dpth{0}% + % + \ifpgf@trim@lowlevel + \gdef\pgf@trimleft@final{}% + \gdef\pgf@trimright@final{}% + \else + \ifdim\pgf@trimleft@final=0sp \gdef\pgf@trimleft@final{} \else\def\pgf@external@trim{1}\fi + \ifdim\pgf@trimright@final=0sp \gdef\pgf@trimright@final{} \else\def\pgf@external@trim{1}\fi + \if1\pgf@external@trim + % UNDO the trimming! export to pdf doesn't supported trimmed + % bounding boxes (has to do with the mediabox/trimbox etc). + % I'll keep the bounding box intact and store the trim information + % into the .dpth file. + \setbox\pgfpic=\hbox{% + \ifx\pgf@trimleft@final\pgfutil@empty\else\kern-\pgf@trimleft@final\fi + \box\pgfpic + \ifx\pgf@trimright@final\pgfutil@empty\else\kern-\pgf@trimright@final\fi + }% + \def\pgf@external@store@dpth{1}% + \fi + \fi + % + \parindent0pt % leave the space +% \leftmargin0pt% +% \rightmargin0pt% + \hoffset=0pt % reset to default + \voffset=0pt + \dimen0\ht\pgfpic% + \advance\dimen0\dp\pgfpic% + \ifdim\dp\pgfpic=0pt\relax + \else% store the picture's depth. Otherwise, it would be lost. + \def\pgf@external@store@dpth{1}% + \fi + \ifpgfexternal@info + \def\pgf@external@store@dpth{1}% + \fi + % + \if1\pgf@external@store@dpth + \ifpgfexternal@aux@in@dpth + \pgf@externalend@storeshifts\@auxout + \immediate\closeout\@auxout + \else + \immediate\openout\pgf@plotwrite=\pgf@filename.dpth + \pgf@externalend@storeshifts\pgf@plotwrite + \immediate\closeout\pgf@plotwrite + \fi + \fi + \pgfsys@prepare@papersize{\the\wd\pgfpic}{\the\dimen0}% + % + \setbox0=\vbox{% + % I admit that I don't know why there is this kerning: + \kern -\pgf@external@kern@top\relax% + \hbox{% + \kern -\pgf@external@kern@left\relax% + \hbox to0pt{% + \wd\pgfexternal@startupbox=0pt % + \ht\pgfexternal@startupbox=0pt % + \dp\pgfexternal@startupbox=0pt % + \box\pgfexternal@startupbox% + \pgfsys@atbegindocument\hss}% + \box\pgfpic% + \kern\pgf@external@kern@right\relax% + }% + \kern\pgf@external@kern@bottom\relax% + }% + % + % compatibility with eso-pic package: \nointerlineskip is not + % allowed here, but the eso-pic package uses \nointerlineskip in + % its shipout routine. + \let\pgfexternal@nointerlineskip@orig=\nointerlineskip + \let\nointerlineskip=\pgfexternal@nointerlineskip + % + \pgfexternal@originalshipout\box0 % + \gdef\pgfexternal@did@a@shipout{1}% + }% + \ifpgfexternal@aux@in@dpth + \endgroup + \fi +} + +\def\pgfexternal@nointerlineskip{% + \ifvmode + \pgfexternal@nointerlineskip@orig + \else + \relax% \nointerlineskip in horizontal mode not allowed. Silently ignore the error message. + \fi +}% + +\endinput +% vi: tabstop=4 shiftwidth=2 expandtab diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcoregraphicstate.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcoregraphicstate.code.tex new file mode 100644 index 0000000000..f7783dcd98 --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcoregraphicstate.code.tex @@ -0,0 +1,280 @@ +% Copyright 2018 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{pgfcoregraphicstate.code.tex} + +% Globals + +\newdimen\pgflinewidth + + +% Set the line width to #1. +% +% #1 = new line width. +% +% Example: +% +% \pgfsetlinewidth{3pt} + +\def\pgfsetlinewidth#1{% + \pgfmathsetlength\pgflinewidth{#1}% + \global\pgflinewidth=\pgflinewidth% + \pgfsys@setlinewidth{\the\pgflinewidth}% + \ignorespaces} + + +% Set the inner line width to #1. +% +% #1 = new inner line width. +% +% Description: +% +% The inner line width is the width of a second line that is drawn on +% top of the main stroked line. If the inner line width is 0pt, no +% inner line is drawn. The main use of inner lines is for creating +% "double" lines. +% +% Inner lines are not drawn when a path is used for clipping. +% +% The inner line width is local to the current TeX group, it is not +% part of the graphic state. +% +% Example: +% +% \pgfsetinnerlinewidth{1pt} + +\def\pgfsetinnerlinewidth#1{% + \pgfmathsetlength\pgf@x{#1}% + \edef\pgfinnerlinewidth{\the\pgf@x}% +} +\def\pgfinnerlinewidth{0pt} + + +% Set the inner line color to #1. +% +% #1 = color for the inner line +% +% Example: +% +% \pgfsetinnerlinecolor{green} % yikes! + +\def\pgfsetinnerstrokecolor#1{\def\pgfinnerstrokecolor{#1}} +\def\pgfinnerstrokecolor{white} + + +% Set the miter limit to #1. +% +% #1 = new miter limit factor. +% +% Example: +% +% \pgfsetmiterlimit{3} + +\def\pgfsetmiterlimit#1{% + \ifdim#1pt<1pt\pgferror{miter limit cannot be less than 1}\fi% + \pgfsys@setmiterlimit{#1}% + \ignorespaces} + + +% Set the dash pattern to #1 with phase #2/ +% +% #1 = a row of numbers of length of ``on'' and ``off'' points. +% #2 = a phase +% +% Example: +% +% \pgfsetdash{} {0pt} % solid line +% \pgfsetdash{{.1cm}} {0pt} % long dashes +% \pgfsetdash{{1pt}{1ex}}{0pt} % dotted + +\def\pgfsetdash#1#2{% + \def\pgf@temp{}% + \def\pgf@next{\pgf@strip}% + \pgf@strip#1{pgf@stop}% + \pgfmathsetlength\pgf@x{#2}% + \pgfsys@setdash{\pgf@temp}{\the\pgf@x}% + \ignorespaces} + +\def\pgf@strip#1{% + \def\pgf@@temp{#1}% + \ifx\pgf@@temp\pgf@stop% + \let\pgf@next=\relax% + \else% + \pgfmathsetlength\pgf@x{#1}% + \ifx\pgf@temp\pgfutil@empty% + \edef\pgf@temp{\the\pgf@x}% + \else% + \edef\pgf@temp{\pgf@temp,\the\pgf@x}% + \fi% + \fi\pgf@next} + +\def\pgf@stop{pgf@stop} + + +% Set color of strokes. This will overrule the normal color. +% +% Example: +% +% \pgfsetstrokecolor{red} + +\def\pgfsetstrokecolor#1{% + \pgfutil@colorlet{pgfstrokecolor}{#1}% + \pgfutil@ifundefined{applycolormixins}{}{\applycolormixins{pgfstrokecolor}}% + \expandafter\let\expandafter\pgf@temp\csname\string\color@pgfstrokecolor\endcsname + % for arrow tips: + \global\let\pgf@strokecolor@global=\pgf@temp + \expandafter\pgf@setstrokecolor\pgf@temp% +} +\def\pgf@setstrokecolor#1#2#3#4#5{% + \expandafter\ifx\csname pgfsys@color@#4@stroke\endcsname\relax% + \pgferror{Unsupported color model `#4'. Sorry}% + \else% + \edef\pgf@colmarshal{\expandafter\noexpand\csname pgfsys@color@#4@stroke\endcsname}% + \pgf@uncomma#5,,% + \pgf@colmarshal% + \fi} + +\def\pgf@uncomma#1,{% + \def\pgf@coltest{#1}% + \ifx\pgf@coltest\pgfutil@empty% + \let\pgf@colnext=\relax% + \else% + \expandafter\def\expandafter\pgf@colmarshal\expandafter{\pgf@colmarshal{#1}}% + \let\pgf@colnext=\pgf@uncomma% + \fi% + \pgf@colnext% +} + + +% Set color of fills. This will overrule the normal color. +% +% Example: +% +% \pgfsetfillcolor{gray} + +\def\pgfsetfillcolor#1{% + \pgfutil@colorlet{pgffillcolor}{#1}% + \pgfutil@ifundefined{applycolormixins}{}{\applycolormixins{pgffillcolor}}% + \expandafter\let\expandafter\pgf@temp\csname\string\color@pgffillcolor\endcsname + % for arrow tips: + \global\let\pgf@fillcolor@global=\pgf@temp + \expandafter\pgf@setfillcolor\pgf@temp +} +\def\pgf@setfillcolor#1#2#3#4#5{% + \expandafter\ifx\csname pgfsys@color@#4@fill\endcsname\relax% + \pgferror{Unsupported color model `#4'. Sorry}% + \else% + \edef\pgf@colmarshal{\expandafter\noexpand\csname pgfsys@color@#4@fill\endcsname}% + \pgf@uncomma#5,,% + \pgf@colmarshal% + \fi} + + + +% Sets both the stroke and fill color. +% +% Example: +% +% \pgfsetcolor{blue} + +\def\pgfsetcolor#1{% + \pgfutil@colorlet{pgfstrokecolor}{#1}% + \pgfutil@ifundefined{applycolormixins}{}{\applycolormixins{pgfstrokecolor}}% + \expandafter\let\expandafter\pgf@temp\csname\string\color@pgfstrokecolor\endcsname + % for arrow tips: + \global\let\pgf@strokecolor@global=\pgf@temp + \global\let\pgf@fillcolor@global=\pgf@temp + \expandafter\pgf@setcolor\pgf@temp% +} +\def\pgf@setcolor#1#2#3#4#5{% + \expandafter\ifx\csname pgfsys@color@#4\endcsname\relax% + \pgferror{Unsupported color model `#4'. Sorry}% + \else% + \edef\pgf@colmarshal{\expandafter\noexpand\csname pgfsys@color@#4\endcsname}% + \pgf@uncomma#5,,% + \pgf@colmarshal% + \fi} + +% Code for ensuring the stroke/fill colors are correctly reset. +\def\XC@bcolor{\pgfsys@color@reset} + +% Set a butt line cap. +% +% Example: +% +% \pgfsetbuttcap + +\def\pgfsetbuttcap{\pgfsys@buttcap\ignorespaces} + + +% Set a round line cap. +% +% Example: +% +% \pgfsetroundcap + +\def\pgfsetroundcap{\pgfsys@roundcap\ignorespaces} + + +% Set a rectangular line cap. +% +% Example: +% +% \pgfsetrectcap + +\def\pgfsetrectcap{\pgfsys@rectcap\ignorespaces} + + +% Set a miter line join. +% +% Example: +% +% \pgfsetmiterjoin + +\def\pgfsetmiterjoin{\pgfsys@miterjoin\ignorespaces} + + +% Set a bevel line join. +% +% Example: +% +% \pgfsetbeveljoin + +\def\pgfsetbeveljoin{\pgfsys@beveljoin\ignorespaces} + + +% Set a round line join. +% +% Example: +% +% \pgfsetroundjoin + +\def\pgfsetroundjoin{\pgfsys@roundjoin\ignorespaces} + + +% Sets the even-odd rule for filling and clipping. +% +% Example: +% +% \pgfseteorule + +\def\pgfseteorule{\pgfsys@eoruletrue\ignorespaces} + + +% Sets the non-zero winding number rule for filling and clipping. +% +% Example: +% +% \pgfsetnonzerorule + +\def\pgfsetnonzerorule{\pgfsys@eorulefalse\ignorespaces} + + + +\endinput diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcoreimage.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcoreimage.code.tex new file mode 100644 index 0000000000..fd1c0c48db --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcoreimage.code.tex @@ -0,0 +1,242 @@ +% Copyright 2018 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{pgfcoreimage.code.tex} + + + +% Declare an image +% +% #1 = optional argument: width, height, page specification +% #2 = name of the image for later use +% #4 = filename without extension, automatic extensions are .pdf, +% .jpg, and .png for PDF and .ps, .eps, .epsi for postscript. +% +% Description: +% +% This command declares an image file for later use. Even if the image +% is used several times in the document, in PDF it will only be stored +% once. +% +% Example: +% +% \pgfdeclareimage[width=2cm,page=2]{myimage}{imagefilename} + +\def\pgfdeclareimage{\pgfutil@ifnextchar[{\pgf@declareimage}{\pgf@declareimage[]}} +\def\pgf@declareimage[#1]#2#3{% + \pgfqkeys{/pgf/images}{height=,width=,page=,interpolate=false,mask=,#1}% + % Try to find the file + \gdef\pgf@filename{}% + % If page= parameter is not empty, try that file first: + \ifx\pgf@imagepage\pgfutil@empty% + \else% + \expandafter\pgf@findfile\pgfsys@imagesuffixlist:+{#3.page\pgf@imagepage}% + \fi% + \ifx\pgf@filename\pgfutil@empty% + \expandafter\pgf@findfile\pgfsys@imagesuffixlist:+{#3}% + \else% + \pgfkeys{/pgf/images/page=}% make page empty + \fi% + \ifx\pgf@filename\pgfutil@empty% + \pgfwarning% + {File "#3" not found when defining image "#2". + Tried all extensions in "\pgfsys@imagesuffixlist"}% + \pgf@declaredraftimage{#2}{#3}% + \else% + \ifpgf@draftmode% + \pgf@declaredraftimage{#2}{#3}% + \else% + \pgfsys@defineimage% + \fi% + \fi% + \expandafter\global\expandafter\let\csname pgf@image@#2!\endcsname=\pgf@image% +} + + +\pgfkeys{ + /pgf/images/draft/.is if=pgf@draftmode, + /pgf/images/draft/.default=true} +\pgfkeys{/pgf/images/width/.estore in=\pgf@imagewidth} +\pgfkeys{/pgf/images/height/.estore in=\pgf@imageheight} +\pgfkeys{/pgf/images/page/.estore in=\pgf@imagepage} +\pgfkeys{/pgf/images/interpolate/.cd,.code=\edef\pgf@imageinterpolate{#1},.default=true} +\let\pgf@imageinterpolate\pgfutil@empty +\pgfkeys{/pgf/images/mask/.code=% + {% + \edef\pgf@imagemask{#1}% + \ifx\pgf@imagemask\pgfutil@empty% + \else% + \pgfutil@ifundefined{pgf@mask@#1}% + {\pgferror{Undefined mask "#1".}% + \edef\pgf@imagemask{}}% + {\edef\pgf@imagemask{\csname pgf@mask@#1\endcsname}% + }% + \fi% + }} + + +\def\pgf@findfile#1:#2+#3{% + \pgfutil@IfFileExists{#3#1}% + {\xdef\pgf@filename{#3#1}}% + {\def\pgf@mightbeempty{#2}% + \ifx\pgf@mightbeempty\pgfutil@empty\else% + \pgf@findfile#2+{#3}% + \fi}} + +% #1: image name +% #2: file name +\def\pgf@declaredraftimage#1#2{% + \ifx\pgf@imagewidth\pgfutil@empty% + \pgfwarning{Missing width for image "#1" ("#2") in draft mode. Using 1cm instead}% + \edef\pgf@imagewidth{1cm}% + \fi% + \ifx\pgf@imageheight\pgfutil@empty% + \pgfwarning{Missing height for image "#1" ("#2") in draft mode. Using 1cm instead}% + \edef\pgf@imageheight{1cm}% + \fi% + \ifx\pgf@imagepage\pgfutil@empty\else\edef\pgf@imagepagetext{ page \pgf@imagepage}\fi% + \edef\pgf@image{% + \hbox to \pgf@imagewidth{% + \vrule\kern-0.4pt% + \vbox to \pgf@imageheight{% + \hrule\vfil% + \hbox to \pgf@imagewidth{\hskip-10cm\hfil\noexpand\pgfutil@font@tiny#2\pgf@imagepage\hfil\hskip-10cm}% + \vfil\hrule}% + \kern-0.4pt\vrule}% + }% +} + + + +% Declare a soft mask +% +% #1 = optional argument: matte specification. default matte is +% white. +% #2 = name of the mask for later use +% #3 = filename without extension, automatic extensions are .pdf, +% .jpg, and .png for PDF. Postscript is not supported. +% +% Description: +% +% This command declares a soft mask for later masking an image. The +% declared mask should be used together with an image of exactly the +% same height/width if matte is defined. Matte should be the +% preblended background color (see pdf spec for details). +% +% Example: +% +% \pgfdeclaremask[matte=white]{maskname}{maskfilename} +% \pgfdeclareimage[mask=maskname]{image}{imagefilename} + +\def\pgfdeclaremask{\pgfutil@ifnextchar[\pgf@declaremask{\pgf@declaremask[]}} +\def\pgf@declaremask[#1]#2#3{% + \pgfqkeys{/pgf/images/mask}{matte={1 1 1},#1}% defaults + \def\pgf@mask{}% + % Try to find the file + \gdef\pgf@filename{}% + \expandafter\pgf@findfile\pgfsys@imagesuffixlist:+{#3}% + \ifx\pgf@filename\pgfutil@empty% + \pgfwarning% + {File "#3" not found when defining mask "#2". + Tried all extensions in "\pgfsys@imagesuffixlist"}% + \else% + \pgfsys@definemask% + \fi% + \expandafter\global\expandafter\let\csname pgf@mask@#2\endcsname=\pgf@mask% +} + +\pgfkeys{/pgf/images/mask/matte/.cd,.estore in=\pgf@maskmatte,.value required} + + + +% Create an alias name for an image +% +% #1 = name of the alias +% #2 = name of the original +% +% Example: +% +% \pgfdeclareimage{image}{1cm}{1cm}{filename +% \pgfaliasimage{alias}{image} +% \pgfuseimage{alias} + +\def\pgfaliasimage#1#2{% + \expandafter\global\expandafter\let\expandafter\pgf@temp\expandafter=\csname pgf@image@#2!\endcsname% + \expandafter\global\expandafter\let\csname pgf@image@#1!\endcsname=\pgf@temp% + } + + +% Use an image +% +% #1 = name of a previously declared image +% +% Example: +% +% \pgfputat{\pgforigin}{\pgfbox[left,base]{\pgfuseimage{myimage}}} + +\def\pgfuseimage#1{% + \def\pgf@imagename{pgf@image@#1}% + \pgf@tryextensions{\pgf@imagename}{\pgfalternateextension}% + \expandafter\pgfutil@ifundefined\expandafter{\pgf@imagename}% + {\pgferror{Undefined image "#1"}}% + {{\leavevmode\csname\pgf@imagename\endcsname}}} + +\def\pgf@tryextensions#1#2{% + \edef\pgf@args{[#2!]}\expandafter\pgf@@tryextensions\pgf@args{#1}} +\def\pgf@@tryextensions[#1!#2]#3{% + \expandafter\pgfutil@ifundefined\expandafter{#3#1!#2}% + {\def\pgf@temp{#2}% + \ifx\pgf@temp\pgfutil@empty% + \edef#3{#3!}% + \else% + \pgf@@tryextensions[#2]{#3}% + \fi}% + {\edef#3{#3#1!#2}}} + + +% Alternate image +% +% Description: +% +% When an image is used, pgf first attempts to use the image with the +% alternate extension added. If this fails, the original image is +% used. If the alternate extension contains ``!'', then the text up to +% the ! is successively removed and the remainder is tried as an +% alternate extension. +% +% Example: +% +% \def\pgfalternateextension{20!white} + +\def\pgfalternateextension{} + + + +% Directly insert an image +% +% #1 = optional argument: width, height, page specification +% #2 = file name +% +% Description: +% +% Directly inserts an image without declaration. You can, however, +% still access this image using the name pgflastimage. By using +% pgfaliasimage, you can also save this image for later. +% +% Example: +% +% \pgfimage[height=2cm]{filename} + +\def\pgfimage{\pgfutil@ifnextchar[\pgf@imagecom{\pgf@imagecom[]}} +\def\pgf@imagecom[#1]#2{% + \pgfdeclareimage[#1]{pgflastimage}{#2}% + \pgfuseimage{pgflastimage}} + + +\endinput diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcorelayers.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcorelayers.code.tex new file mode 100644 index 0000000000..158f33d6ac --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcorelayers.code.tex @@ -0,0 +1,210 @@ +% Copyright 2018 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{pgfcorelayers.code.tex} + + +% Creates a new pgf layer +% +% #1 = layer name +% +% Declares a new layer for pgf. +% +% Example: +% +% \pgfdeclarelayer{background} + +\def\pgfdeclarelayer#1{% + \pgfutil@ifundefined{pgf@layerbox@#1}{% + \expandafter\expandafter\csname pgf@newbox\endcsname\csname pgf@layerbox@#1\endcsname% + \expandafter\expandafter\csname pgf@newbox\endcsname\csname pgf@layerboxsaved@#1\endcsname% + }{}% +} +\let\pgf@newbox=\newbox % avoid plain TeX outer problem + +% Sets the layers that compose the picture +% +% #1 = List of layers +% +% Description: +% +% Sets the list of layers that make up the picture. The layers will be +% put on top of each other in the order given. +% +% This command can also be given inside of a picture in which case it +% applies only to that very picture. +% +% Example: +% +% \pgfsetlayers{background,main} + +\def\pgfsetlayers#1{% + \let\pgf@layerlist\pgfutil@empty% + \pgf@dosetlayer#1,,\relax% +} + +\def\pgf@dosetlayer#1,#2,\relax{% + \ifx\pgf@layerlist\pgfutil@empty% + \edef\pgf@layerlist{\pgfutil@trimspaces{#1}}% + \else + \edef\pgf@layerlist{\pgf@layerlist,\pgfutil@trimspaces{#1}}% + \fi + \def\pgf@test{#2}% + \ifx\pgf@test\pgfutil@empty% + \else% + \pgf@dosetlayer#2,\relax% + \fi% +} + +\pgfsetlayers{main} + +% Adds code to a layer +% +% #1 = layer name +% +% Note: +% +% You cannot add anything to the ``main'' layer using this command. +% +% Example: +% +% \begin{pgfonlayer}{background} +% \fill[red] (0,0) -- (1,1); +% \end{pgfonlayer} + +\def\pgfonlayer@name{main} + +\def\pgfonlayer#1{% + \pgfutil@ifundefined{pgf@layerbox@#1}{% + \pgferror{Sorry, the requested layer '#1' could not be found. Maybe you misspelled it?}% + \bgroup + \begingroup + }{% + \begingroup + \edef\pgf@temp{#1}% + \ifx\pgf@temp\pgfonlayer@name + % we are already on this layer. + \def\pgf@temp{% + \bgroup + \begingroup + }% + \else + \let\pgfonlayer@name=\pgf@temp + \pgfonlayer@assert@is@active + \def\pgf@temp{% + \expandafter\global\expandafter% + \setbox\csname pgf@layerbox@#1\endcsname=\hbox to 0pt% + \bgroup% + \expandafter\box\csname pgf@layerbox@#1\endcsname% + \begingroup% + }% + \fi + \pgfsetlinewidth{0.4pt}% always reset the line width + \pgf@temp + }% +} +\def\endpgfonlayer{% + \endgroup% + \hss + \egroup% + \endgroup +} + +\let\startpgfonlayer=\pgfonlayer +\let\stoppgfonlayer=\endpgfonlayer + +\def\pgfdiscardlayername{discard} + +\def\pgfonlayer@assert@is@active{% + \ifx\pgfonlayer@name\pgfdiscardlayername + % this special layer name can be used as /dev/null without + % warning. + \else + \begingroup + \def\pgfonlayer@isactive{0}% + \expandafter\pgf@assert@layer@is@active@loop\pgf@layerlist,,\relax% + \if0\pgfonlayer@isactive + \pgfonlayer@assert@fail + \fi + \endgroup + \fi +}% +\def\pgfonlayer@assert@fail{% + \pgferror{Sorry, the requested layer '\pgfonlayer@name' is not + part of the layer list. Please verify that you provided + \string\pgfsetlayers\space and that '\pgfonlayer@name' is part of this list}% +}% +\def\pgf@assert@layer@is@active@loop#1,#2,\relax{% + \edef\pgf@test{#1}% + \ifx\pgf@test\pgfonlayer@name + \def\pgfonlayer@isactive{1}% + \else + \def\pgf@test{#2}% + \ifx\pgf@test\pgfutil@empty% + \else% + \pgf@assert@layer@is@active@loop#2,\relax% + \fi% + \fi +} + +% Hooks into the scoping: + +\def\pgf@insertlayers{% + \expandafter\pgf@dolayer\pgf@layerlist,,\relax% +} +\def\pgf@maintext{main}% +\def\pgf@dolayer#1,#2,\relax{% + \def\pgf@test{#1}% + \ifx\pgf@test\pgf@maintext% + \box\pgf@layerbox@main% + \else% + \pgfsys@beginscope% + \expandafter\box\csname pgf@layerbox@#1\endcsname% + \pgfsys@endscope% + \fi% + \def\pgf@test{#2}% + \ifx\pgf@test\pgfutil@empty% + \else% + \pgf@dolayer#2,\relax% + \fi% +} + +\def\pgf@savelayers{% + \expandafter\pgf@dosavelayer\pgf@layerlist,,\relax% +} +\def\pgf@dosavelayer#1,#2,\relax{% + \def\pgf@test{#1}% + \ifx\pgf@test\pgf@maintext% + \else% + \setbox\csname pgf@layerboxsaved@#1\endcsname=\box\csname pgf@layerbox@#1\endcsname% + \fi% + \def\pgf@test{#2}% + \ifx\pgf@test\pgfutil@empty% + \else% + \pgf@dosavelayer#2,\relax% + \fi% +} + +\def\pgf@restorelayers{% + \expandafter\pgf@dorestorelayer\pgf@layerlist,,\relax% +} +\def\pgf@dorestorelayer#1,#2,\relax{% + \def\pgf@test{#1}% + \ifx\pgf@test\pgf@maintext% + \else% + \global\setbox\csname pgf@layerbox@#1\endcsname=\box\csname pgf@layerboxsaved@#1\endcsname% + \fi% + \def\pgf@test{#2}% + \ifx\pgf@test\pgfutil@empty% + \else% + \pgf@dorestorelayer#2,\relax% + \fi% +} + +\endinput diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcoreobjects.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcoreobjects.code.tex new file mode 100644 index 0000000000..6906a9d987 --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcoreobjects.code.tex @@ -0,0 +1,101 @@ +% Copyright 2018 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{pgfcoreobjects.code.tex} + + +% Object reuse + + +% Define a pgf object for reuse. Such objects will be stored +% efficiently internally. +% +% #1 = name for later reuse +% #2 = lower left corner point of bounding box +% #3 = upper right left corner point of bounding box +% #4 = pure pgf code (nothing too fancy!) +% +% Description: +% +% Used to define reusable objects. The object must be composed of +% basic pgf graphic primitives. Nothing fancy can be used. The +% created object will be stored as an xform object in pdf or as a +% postscript procedure in postscript. +% +% Example: +% +% \pgfdefobject{myrect}{\pgfpoint{-1pt}{-1pt}}{\pgfpoint{11pt}{11pt}} +% {\pgfpathqmoveto{0pt}{0pt} +% \pgfpathqmoveto{10pt}{0pt} +% \pgfpathqmoveto{10pt}{10pt} +% \pgfpathqmoveto{0pt}{10pt} +% \pgfpathclose +% \pgfusepath{stroke}} +% +% \begin{pgfpicture}{0cm}{0cm}{1cm}{1cm} +% \pgfuseobject{myrect} +% \end{pgfpicture} + +\def\pgfdefobject#1#2#3#4{% + \pgfinterruptpath% + \pgf@relevantforpicturesizefalse% + \pgfsys@defobject{#1}{#2}{#3}{#4}% + \endpgfinterruptpath% + \ignorespaces% +} + + +% Use an object that was previously defined using pgfdefobject +% +% #1 = name of previously defined object +% +% Example: +% +% \pgfdefobject{myrect}{\pgfpoint{-1pt}{-1pt}}{\pgfpoint{11pt}{11pt}} +% {\pgfqmoveto{0}{0} +% \pgfqmoveto{10}{0} +% \pgfqmoveto{10}{10} +% \pgfqmoveto{0}{10} +% \pgfclosestroke} +% +% \begin{pgfpicture}{0cm}{0cm}{1cm}{1cm} +% \pgfuseobject{myrect} +% \end{pgfpicture} + +\def\pgfuseobject#1{\pgfsys@beginscope\pgfsys@useobject{#1}{}\pgfsys@endscope} + + +% Use an object that was previously defined using pgfdefobject, but +% magnify the object by the current x and y register values +% +% #1 = name of previously defined object +% +% Example: +% +% \pgfdefobject{myrect}{\pgfpoint{-1pt}{-1pt}}{\pgfpoint{11pt}{11pt}} +% {\pgfqmoveto{0}{0} +% \pgfqmoveto{10}{0} +% \pgfqmoveto{10}{10} +% \pgfqmoveto{0}{10} +% \pgfclosestroke} +% +% \begin{pgfpicture}{0cm}{0cm}{1cm}{1cm} +% \pgf@x=2pt% Scale by factor two in x-direction +% \pgf@y=2pt% Scale by factor two in y-direction +% \pgfuseobjectmagnify{myrect} +% \end{pgfpicture} + +\def\pgfuseobjectmagnify#1{% + \pgfsys@beginscope% + \pgfsys@useobject{#1}{\pgfsys@transformxyscale{\pgf@sys@tonumber{\pgf@x}}{\pgf@sys@tonumber{\pgf@y}}}% + \pgfsys@endscope% +} + + +\endinput diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcorepathconstruct.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcorepathconstruct.code.tex new file mode 100644 index 0000000000..cafc532938 --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcorepathconstruct.code.tex @@ -0,0 +1,1477 @@ +% Copyright 2019 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{pgfcorepathconstruct.code.tex} + + +\newdimen\pgf@path@lastx +\newdimen\pgf@path@lasty + +\let\pgfgetpath=\pgfsyssoftpath@getcurrentpath +\let\pgfsetpath=\pgfsyssoftpath@setcurrentpath + + + +% Replace corners by arcs. +% +% #1 = in-size of arc +% #2 = out-size of arc +% +% Description: +% +% This command influences path construction command like +% \pgfpathlineto or \pgfpatharc. It will cause the corners at the end +% of these commands to be replaced by little arcs. If the +% corner is a 90 degrees corner and if #1=#2, a quarter-circle of +% radius #1 is put in place of the corner. If #1 and #2 are different, +% the quarter circle will instead by a quarter ellipse. If the angle +% is different from 90 degrees, a deformed quarter circle will +% result, which may or may not be desirable. For a ``perfect'' arc you +% must use the \pgfpatharc command. +% +% +% Example: One rounded corner. +% +% \pgfpathmoveto{\pgfpointxy{0}{0}} +% \pgfsetcornersarced{4pt}{4pt} +% \pgfpathlineto{\pgfpointxy{0}{1}} +% \pgfpathlineto{\pgfpointxy{1}{1}} +% \pgfstroke +% +% Example: A rounded rectangle +% +% \pgfsetcornersarced{4pt}{4pt} +% \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{1cm}{1cm}} +% \pgfstroke +% +% Example: A rounded triangles +% +% \pgfsetcornersarced{4pt}{4pt} +% \pgfpathmoveto{\pgfpointorigin} +% \pgfpathlineto{\pgfpoint{1cm}{0cm}} +% \pgfpathlineto{\pgfpoint{1cm}{1cm}} +% \pgfpathclose +% \pgfstroke + +\newif\ifpgf@arccorners + +\def\pgfsetcornersarced#1{% + \pgf@process{#1}% + \edef\pgf@corner@arc{{\the\pgf@x}{\the\pgf@y}}% + \pgf@arccornerstrue% + \ifdim\pgf@x=0pt% + \ifdim\pgf@y=0pt\relax% + \pgf@arccornersfalse% + \fi% + \fi% +} + +\def\pgf@roundcornerifneeded{% + \ifpgf@arccorners\expandafter\pgfsyssoftpath@specialround\pgf@corner@arc\fi% +} + + + +% The following protocol the passed sizes and all the corresponding +% softpath commands. The nonlinear transformation (nlt) module +% overwrites these commands. + +\def\pgf@lt@moveto#1#2{% + \pgf@protocolsizes{#1}{#2}% + \pgfsyssoftpath@moveto{\the#1}{\the#2}% +} +\def\pgf@lt@lineto#1#2{% + \pgf@protocolsizes{#1}{#2}% + \pgfsyssoftpath@lineto{\the#1}{\the#2}% +} +\def\pgf@lt@curveto#1#2#3#4#5#6{% + \pgf@protocolsizes{#1}{#2}% + \pgf@protocolsizes{#3}{#4}% + \pgf@protocolsizes{#5}{#6}% + \pgfsyssoftpath@curveto{\the#1}{\the#2}{\the#3}{\the#4}{\the#5}{\the#6}% +} + +\let\pgf@lt@closepath\pgfsyssoftpath@closepath + +\let\pgf@nlt@moveto\pgf@lt@moveto +\let\pgf@nlt@lineto\pgf@lt@lineto +\let\pgf@nlt@curveto\pgf@lt@curveto +\let\pgf@nlt@closepath\pgf@lt@closepath + +\let\pgf@nlt@list\pgfutil@empty % If non-empty, the nlt module is active + + +% Move current point to #1. +% +% #1 = new current point +% +% Example: +% +% \pgfpathmoveto{\pgfxy(0,0)} +% \pgfpathlineto{\pgfxy(0,1)} +% \pgfstroke + +\def\pgfpathmoveto#1{% + \pgfpointtransformed{#1}% + \pgf@nlt@moveto{\pgf@x}{\pgf@y}% + \global\pgf@path@lastx=\pgf@x% + \global\pgf@path@lasty=\pgf@y% +} + +\def\pgf@protocolsizes#1#2{% + \ifpgf@relevantforpicturesize% + \ifdim#1<\pgf@picminx\global\pgf@picminx#1\fi% + \ifdim#1>\pgf@picmaxx\global\pgf@picmaxx#1\fi% + \ifdim#2<\pgf@picminy\global\pgf@picminy#2\fi% + \ifdim#2>\pgf@picmaxy\global\pgf@picmaxy#2\fi% + \ifpgf@size@hooked% + \let\pgf@size@hook@x#1\let\pgf@size@hook@y#2\pgf@path@size@hook% + \fi% + \fi% + \ifdim#1<\pgf@pathminx\global\pgf@pathminx#1\fi% + \ifdim#1>\pgf@pathmaxx\global\pgf@pathmaxx#1\fi% + \ifdim#2<\pgf@pathminy\global\pgf@pathminy#2\fi% + \ifdim#2>\pgf@pathmaxy\global\pgf@pathmaxy#2\fi% +} +\newif\ifpgf@size@hooked +\let\pgf@path@size@hook=\pgfutil@empty% + +\def\pgf@resetpathsizes{% + \global\pgf@pathmaxx=-16000pt\relax% + \global\pgf@pathminx=16000pt\relax% + \global\pgf@pathmaxy=-16000pt\relax% + \global\pgf@pathminy=16000pt\relax% +} + +\def\pgf@getpathsizes#1{% + \edef#1{{\the\pgf@pathmaxx}{\the\pgf@pathminx}{\the\pgf@pathmaxy}{\the\pgf@pathminy}}% +} +\def\pgf@setpathsizes#1{% + \expandafter\pgf@@setpathsizes#1% +} +\def\pgf@@setpathsizes#1#2#3#4{% + \global\pgf@pathmaxx=#1\relax% + \global\pgf@pathminx=#2\relax% + \global\pgf@pathmaxy=#3\relax% + \global\pgf@pathminy=#4\relax% +} + + + + + +% Append a line from the current point to #1 to the current path. +% +% #1 = end of line +% +% Example: +% +% \pgfpathmoveto{\pgfxy(0,0)} +% \pgfpathlineto{\pgfxy(0,1)} +% \pgfstroke + +\def\pgfpathlineto#1{% + \pgfpointtransformed{#1}% + \pgf@roundcornerifneeded% + \pgf@nlt@lineto{\pgf@x}{\pgf@y}% + \global\pgf@path@lastx=\pgf@x% + \global\pgf@path@lasty=\pgf@y% +} + + + +% Close the current path. +% +% Example: +% +% % Draws two triangles +% \pgfpathmoveto{\pgfxy(0,0)} +% \pgfpathlineto{\pgfxy(0,1)} +% \pgfpathlineto{\pgfxy(1,0)} +% \pgfclosepath +% \pgfpathmoveto{\pgfxy(2,0)} +% \pgfpathlineto{\pgfxy(2,1)} +% \pgfpathlineto{\pgfxy(3,0)} +% \pgfpathclose +% \pgfstroke + +\def\pgfpathclose{% + \pgf@roundcornerifneeded% + \pgf@nlt@closepath% +} + + +% Append a cubic bezier spline from the current point to #3 with control +% points #1 and #2 to the current path. +% +% #1 = first control point +% #2 = second control point +% #3 = end point +% +% Example: +% +% \pgfpathmoveto{\pgfpointxy{0}{0}} +% \pgfpathcurveto{\pgfpointxy{0}{1}}{\pgfpointxy{1}{1}}{\pgfpointxy{1}{2}} +% \pgfstroke + +\def\pgfpathcurveto#1#2#3{% + \pgfpointtransformed{#3}% + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + \pgfpointtransformed{#2}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgfpointtransformed{#1}% + \pgf@roundcornerifneeded% + \pgf@nlt@curveto{\pgf@x}{\pgf@y}{\pgf@xa}{\pgf@ya}{\pgf@xb}{\pgf@yb}% + \global\pgf@path@lastx=\pgf@xb% + \global\pgf@path@lasty=\pgf@yb% +} + + + +% Append a quadratic bezier spline from the current point to #2 with +% control point #1 to the current path. +% +% #1 = control point +% #2 = end point +% +% Example: +% +% \pgfpathmoveto{\pgfpointxy{0}{0}} +% \pgfpathquadraticcurveto{\pgfpointxy{1}{1}}{\pgfpointxy{2}{0}} +% \pgfstroke + +\def\pgfpathquadraticcurveto#1#2{% + \pgfpointtransformed{#2}% + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + \pgfpointtransformed{#1}% + \pgf@xc=.6666666\pgf@x% + \pgf@yc=.6666666\pgf@y% + % compute second control point: + \pgf@xa=.33333333\pgf@xb% + \pgf@ya=.33333333\pgf@yb% + \advance\pgf@xa by\pgf@xc% + \advance\pgf@ya by\pgf@yc% + % compute first control point + \advance\pgf@xc by.3333333\pgf@path@lastx% + \advance\pgf@yc by.3333333\pgf@path@lasty% + \pgf@roundcornerifneeded% + \pgf@nlt@curveto{\pgf@xc}{\pgf@yc}{\pgf@xa}{\pgf@ya}{\pgf@xb}{\pgf@yb}% + \global\pgf@path@lastx=\pgf@xb% + \global\pgf@path@lasty=\pgf@yb% +} + + + + +% Append an arc to the current point, where the current point is at +% angle #1 and the end is at angle #2. If #2 > #1, the arc is drawn +% counter-clockwise, otherwise it is clockwise. +% +% #1 = angle of first point +% #2 = angle of second point +% #3 = radius or x-radius/y-radius +% +% Example: +% +% \pgfpathmoveto{\pgfxy(0,0)} +% \pgfpatharc{0}{90}{2cm} +% \pgfstroke + +\def\pgfpatharc#1#2#3{% + {% + \pgfmathparse{#1}\let\pgf@temp@a=\pgfmathresult% + \pgfmathparse{#2}\let\pgf@temp@b=\pgfmathresult% + \pgfutil@in@{and }{#3}% + \ifpgfutil@in@% + \pgf@arc@get@radii#3\pgf@arc@stop% + \else + \pgf@arc@get@radii#3and #3\pgf@arc@stop% + \fi% + \pgf@arc@local@angle@a=\pgf@temp@a pt% + \pgf@arc@local@angle@b=\pgf@temp@b pt% + \loop% + \pgfutil@tempdima=\pgf@arc@local@angle@a% + \advance\pgfutil@tempdima by-\pgf@arc@local@angle@b\relax% + \ifdim\pgfutil@tempdima<0pt\relax% + \pgfutil@tempdima=-\pgfutil@tempdima\relax% + \fi% + \ifdim\pgfutil@tempdima>90pt\relax% + \ifdim\pgfutil@tempdima>115pt\relax% + \pgf@arc@temp=90pt% big skip + \else% + \pgf@arc@temp=60pt% smaller skip to ensure wide segments + % (important shortened end segments because + % of arrow tips) + \fi% + \ifdim\pgf@arc@local@angle@b>\pgf@arc@local@angle@a\relax% + {% + \pgf@arc@local@angle@b=\pgf@arc@local@angle@a\relax% + \advance\pgf@arc@local@angle@b by\pgf@arc@temp\relax% + \pgf@arc% + } + \advance\pgf@arc@local@angle@a by\pgf@arc@temp\relax% + \else + {% + \pgf@arc@local@angle@b=\pgf@arc@local@angle@a\relax% + \advance\pgf@arc@local@angle@b by-\pgf@arc@temp\relax% + \pgf@arc% + }% + \advance\pgf@arc@local@angle@a by-\pgf@arc@temp\relax% + \fi% + \repeat% + \pgf@roundcornerifneeded% + \pgf@arc% + }% +} +\dimendef\pgf@arc@local@angle@a=0 +\dimendef\pgf@arc@local@angle@b=1 +\dimendef\pgf@arc@temp=2 + +\def\pgf@arc@get@radii#1and #2\pgf@arc@stop{% + \pgfmathparse{#1}\let\pgf@arc@radius@a=\pgfmathresult% + \pgfmathparse{#2}\let\pgf@arc@radius@b=\pgfmathresult% +} + + +\def\pgf@arc{% + {% + \pgfutil@tempdima=\pgf@arc@radius@a pt% + \pgfutil@tempdimb=\pgf@arc@radius@b pt% + % + \pgf@xa=\pgf@arc@local@angle@a\relax% + \pgf@xb=\pgf@arc@local@angle@b\relax% + \advance\pgf@xb by-\pgf@xa\relax% + \ifdim\pgf@xb<0pt\relax% + \pgf@xb=-\pgf@xb\relax% + \fi% + \ifdim\pgf@xb=90.0pt% + \def\pgfmathresult{0.55228475}% + \else% + \pgfmathparse{1.333333333*tan(.25*\pgf@sys@tonumber{\pgf@xb})}% many thanks to Ken Starks + \fi% + \pgfutil@tempdima=\pgfmathresult\pgfutil@tempdima% + \pgfutil@tempdimb=\pgfmathresult\pgfutil@tempdimb% + %.. controls +(\pgf@xa+90:\pgfutil@tempdima) and +(\pgf@xb-90:\pgfutil@tempdima) .. +(-(#1:#3)+(#2:#3))% + % store first support vector in xa/ya: + \pgf@xa=\pgf@arc@local@angle@a\relax% + \ifdim\pgf@arc@local@angle@b>\pgf@arc@local@angle@a\relax% + \advance\pgf@xa by 90pt\relax% + \else% + \advance\pgf@xa by -90pt\relax% + \fi% + \edef\pgf@arc@angle{\pgf@sys@tonumber{\pgf@xa}}% + \pgfpointtransformed{\pgfpointpolar{\pgf@arc@angle}{\pgfutil@tempdima and \pgfutil@tempdimb}}% + \advance\pgf@x by-\pgf@pt@x% + \advance\pgf@y by-\pgf@pt@y% + \pgf@xa=\pgf@path@lastx% + \pgf@ya=\pgf@path@lasty% + \advance\pgf@xa by \pgf@x% + \advance\pgf@ya by \pgf@y% + % store target in xb/yb: + \pgfpointtransformed{\pgfpointpolar{\pgf@sys@tonumber{\pgf@arc@local@angle@a}}{\pgf@arc@radius@a pt and \pgf@arc@radius@b pt}}% + \pgf@xb=\pgf@path@lastx% + \pgf@yb=\pgf@path@lasty% + \advance\pgf@xb by -\pgf@x% + \advance\pgf@yb by -\pgf@y% + \pgfpointtransformed{\pgfpointpolar{\pgf@sys@tonumber{\pgf@arc@local@angle@b}}{\pgf@arc@radius@a pt and \pgf@arc@radius@b pt}}% + \advance\pgf@xb by \pgf@x% + \advance\pgf@yb by \pgf@y% + % store second support xc/yc: + \ifdim\pgf@arc@local@angle@b>\pgf@arc@local@angle@a\relax% + \advance\pgf@arc@local@angle@b by -90pt\relax% + \else% + \advance\pgf@arc@local@angle@b by 90pt\relax% + \fi% + \pgfpointtransformed{\pgfpointpolar{\pgf@sys@tonumber{\pgf@arc@local@angle@b}}{\pgfutil@tempdima and \pgfutil@tempdimb}}% + \advance\pgf@x by-\pgf@pt@x% + \advance\pgf@y by-\pgf@pt@y% + \pgf@xc=\pgf@xb\relax% + \pgf@yc=\pgf@yb\relax% + \advance \pgf@xc by \pgf@x\relax% + \advance \pgf@yc by \pgf@y\relax% + \pgf@nlt@curveto{\pgf@xa}{\pgf@ya}{\pgf@xc}{\pgf@yc}{\pgf@xb}{\pgf@yb}% + \global\pgf@path@lastx=\pgf@xb% + \global\pgf@path@lasty=\pgf@yb% + }% +} + + +% Append an arc to the current point, where the arc is on an ellipse +% given by two axis vectors. +% +% #1 = angle of first point +% #2 = angle of second point +% #3 = first axis +% #4 = second axis +% +% Example: +% +% \pgfpathmoveto{\pgfxy(0,0)} +% \pgfpatharcaxes{0}{90}{\pgfpointxy{2}{0}}{\pgfpointxy{0}{2}} +% \pgfstroke + +\def\pgfpatharcaxes#1#2#3#4{% + {% + \pgftransformtriangle{\pgfpointorigin}{#3}{#4}% + \pgfpatharc{#1}{#2}{1pt}% + }% +} + + + +% Append an arc to the current point that ends at a given position. +% +% #1 = x-radius +% #2 = y-radius +% #3 = x-axis-rotation (in degrees) +% #4 = large-arc-sweep-flag (0 or 1) +% #5 = sweep-flag (0 or 1) +% #6 = target point +% +% Description: +% +% This command implements an arc drawing where a given target +% coordinate (#6) is given and the task is to draw an arc of an +% ellipse with the given radii. The center point of the ellipse is not +% give, but computed automatically. +% +% This kind of "endpoint parameterization" of an arc is exactly the +% same as the one specified by the SVG-specification for the "A" and +% "a" path commands. Please see the SVG-specification for details. +% +% Note that the problem is internally converted to drawing an arc +% using \pgfpatharc. This means that there may be a heavy loss of +% accuracy. +% +% Example: +% +% \pgfpathmoveto{\pgfpoint{1cm}{1cm}} +% \pgfpatharcto{1cm}{1cm}{0}{0}{0}{\pgfpoint{0cm}{2cm}} + +\def\pgfpatharcto#1#2#3#4#5#6{% + {% + % The following code is based on the transformation described in svg + % 1.1 specification Section F.6.5 + % + % Step 1: store the simple parameters (xa=x1 since TeX does not + % allow numbers in names) + % + \pgfmathsetmacro\pgf@arcto@rx{abs(#1)}% + \pgfmathsetmacro\pgf@arcto@ry{abs(#2)}% + \ifdim\pgf@arcto@rx pt=0pt% special rule: zero radius=straight line + \gdef\pgf@marshal{\pgfpathlineto{#6}}% + \else + \ifdim\pgf@arcto@ry pt=0pt% special rule: zero radius=straight line + \gdef\pgf@marshal{\pgfpathlineto{#6}}% + \else + \pgfmathsetmacro\pgf@arcto@phi{#3}% + \pgfmathsetmacro\pgf@arcto@fA{#4}% + \ifdim\pgf@arcto@fA pt=0pt + \else + \pgfmathsetmacro\pgf@arcto@fA{1.0} % Special rule: every non-zero value is 1. + \fi + \pgfmathsetmacro\pgf@arcto@fS{#5}% + \ifdim\pgf@arcto@fS pt=0pt + \else + \pgfmathsetmacro\pgf@arcto@fS{1.0} % Special rule: every non-zero value is 1. + \fi + \pgf@process{#6} + \edef\pgf@arcto@xb{\the\pgf@x}% + \edef\pgf@arcto@yb{\the\pgf@y}% + % + % Step 2: x1,y1 is more complicated to compute: It is given by lastx + % and lasty, but these are transformed coordinates, we need the + % untransformed ones. So, we inverse the transformation (arghh...) + % + \pgftransforminvert% + \pgf@process{\pgfpointtransformed{\pgfqpoint{\pgf@path@lastx}{\pgf@path@lasty}}} + \edef\pgf@arcto@xa{\the\pgf@x} + \edef\pgf@arcto@ya{\the\pgf@y} + \edef\pgf@temp@a{\pgf@arcto@xa,\pgf@arcto@ya} + \edef\pgf@temp@b{\pgf@arcto@xb,\pgf@arcto@yb} + \ifx\pgf@temp@a\pgf@temp@b% special rule: skip! + \global\let\pgf@marshal\pgfutil@empty + \else + % + % Ok, now we got all the parameters setup. Now comes the + % computation... + % + % + % Step 3: Start with a new coordinate system and rotate everything + % by the negated phi. + % + \pgftransformreset + \pgftransformrotate{-\pgf@arcto@phi} + % Ok, using \pgfpointtransformed we now get transformed points... + % + % Step 4: Compute x1' and y1' (xaprime and yaprime) + % + \pgf@process{ + \pgfpointtransformed{\pgfpointscale{.5}{\pgfpointdiff + {\pgfqpoint{\pgf@arcto@xb}{\pgf@arcto@yb}} + {\pgfqpoint{\pgf@arcto@xa}{\pgf@arcto@ya}} + } + } + } + \edef\pgf@arcto@xaprime{\pgf@sys@tonumber\pgf@x} + \edef\pgf@arcto@yaprime{\pgf@sys@tonumber\pgf@y} + % + % Compute Lambda + % + \pgfmathsetmacro\pgf@arcto@frac@x{\pgf@arcto@xaprime/\pgf@arcto@rx} + \pgfmathsetmacro\pgf@arcto@frac@y{\pgf@arcto@yaprime/\pgf@arcto@ry} + \pgfmathsetmacro\pgf@arcto@lambda{ + \pgf@arcto@frac@x*\pgf@arcto@frac@x+\pgf@arcto@frac@y*\pgf@arcto@frac@y + } + \ifdim\pgf@arcto@lambda pt>1pt% + \pgfmathsetmacro\pgf@arcto@sqrt@lambda{sqrt(\pgf@arcto@lambda)} + \pgfmathsetmacro\pgf@arcto@rx{\pgf@arcto@sqrt@lambda*\pgf@arcto@rx} + \pgfmathsetmacro\pgf@arcto@ry{\pgf@arcto@sqrt@lambda*\pgf@arcto@ry} + \fi + % + % Do some scaling + % + \pgfmathsetmacro\pgf@arcto@xaprime@abs{abs(\pgf@arcto@xaprime)} + \pgfmathsetmacro\pgf@arcto@yaprime@abs{abs(\pgf@arcto@yaprime)} + \pgfmathmax@{\pgf@arcto@rx,\pgf@arcto@ry,\pgf@arcto@xaprime@abs,\pgf@arcto@yaprime@abs} + \pgfmathsetmacro\pgf@arcto@scaling{20/\pgfmathresult} + \pgfmathsetmacro\pgf@arcto@rx@scaled{\pgf@arcto@scaling*\pgf@arcto@rx} + \pgfmathsetmacro\pgf@arcto@ry@scaled{\pgf@arcto@scaling*\pgf@arcto@ry} + \pgfmathsetmacro\pgf@arcto@xaprime@scaled{\pgf@arcto@scaling*\pgf@arcto@xaprime} + \pgfmathsetmacro\pgf@arcto@yaprime@scaled{\pgf@arcto@scaling*\pgf@arcto@yaprime} + % + % Step 5: Now comes the messy computation of c1' and c2'. + % + \ifdim\pgf@arcto@rx pt>\pgf@arcto@ry pt% + \pgfmathsetmacro\pgf@arcto@rx@over@ry{\pgf@arcto@rx/\pgf@arcto@ry} + \pgfmathsetmacro\pgf@arcto@ry@over@rx{\pgf@arcto@ry/\pgf@arcto@rx} + \pgfmathsetmacro\pgf@arcto@temp{\pgf@arcto@ry@over@rx*\pgf@arcto@xaprime@scaled} + \pgfmathsetmacro\pgf@arcto@numerator{ + \pgf@arcto@ry@scaled*\pgf@arcto@ry@scaled- + \pgf@arcto@yaprime@scaled*\pgf@arcto@yaprime@scaled- + \pgf@arcto@temp*\pgf@arcto@temp + } + \pgfmathsetmacro\pgf@arcto@denominator{ + \pgf@arcto@yaprime@scaled*\pgf@arcto@yaprime@scaled+ + \pgf@arcto@temp*\pgf@arcto@temp + } + \else + \pgfmathsetmacro\pgf@arcto@rx@over@ry{\pgf@arcto@rx/\pgf@arcto@ry} + \pgfmathsetmacro\pgf@arcto@ry@over@rx{\pgf@arcto@ry/\pgf@arcto@rx} + \pgfmathsetmacro\pgf@arcto@temp{\pgf@arcto@rx@over@ry*\pgf@arcto@yaprime@scaled} + \pgfmathsetmacro\pgf@arcto@numerator{ + \pgf@arcto@rx@scaled*\pgf@arcto@rx@scaled- + \pgf@arcto@xaprime@scaled*\pgf@arcto@xaprime@scaled- + \pgf@arcto@temp*\pgf@arcto@temp + } + \pgfmathsetmacro\pgf@arcto@denominator{ + \pgf@arcto@xaprime@scaled*\pgf@arcto@xaprime@scaled+ + \pgf@arcto@temp*\pgf@arcto@temp + } + \fi + \pgfmathsetmacro\pgf@arcto@frac{ + \pgf@arcto@numerator/\pgf@arcto@denominator + } + \ifdim\pgf@arcto@frac pt<0pt + \pgfmathsetmacro\pgf@arcto@factor{0} + \else + \pgfmathsetmacro\pgf@arcto@factor{sqrt(\pgf@arcto@frac)} + \fi + \ifx\pgf@arcto@fA\pgf@arcto@fS + \pgfmathsetmacro\pgf@arcto@factor{-\pgf@arcto@factor} + \fi + \pgfmathsetmacro\pgf@arcto@cxprime{ + \pgf@arcto@factor*\pgf@arcto@rx@over@ry*\pgf@arcto@yaprime + } + \pgfmathsetmacro\pgf@arcto@cyprime{ + -\pgf@arcto@factor*\pgf@arcto@ry@over@rx*\pgf@arcto@xaprime + } + % + % Step 6: Ok, now compute cx,cy + % + \pgftransformreset + \pgftransformrotate{\pgf@arcto@phi} + \pgf@process{ + \pgfpointtransformed{\pgfqpoint{\pgf@arcto@cxprime pt}{\pgf@arcto@cyprime pt}} + } + \edef\pgf@arcto@temp{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}} + \pgf@process{\pgfpointadd{\pgf@arcto@temp}{ + \pgfpointscale{.5}{ + \pgfpointadd + {\pgfqpoint{\pgf@arcto@xa}{\pgf@arcto@ya}} + {\pgfqpoint{\pgf@arcto@xb}{\pgf@arcto@yb}} } + } + } + \edef\pgf@arcto@cx{\the\pgf@x} + \edef\pgf@arcto@cy{\the\pgf@y} + % + % Step 7: Compute start angle: + % + \pgfmathsetmacro\pgf@arcto@vec@x{(\pgf@arcto@xaprime-\pgf@arcto@cxprime)/\pgf@arcto@rx} + \pgfmathsetmacro\pgf@arcto@vec@y{(\pgf@arcto@yaprime-\pgf@arcto@cyprime)/\pgf@arcto@ry} + \pgfmathsetmacro\pgf@arcto@denominator{veclen(\pgf@arcto@vec@x,\pgf@arcto@vec@y)} + \pgfmathsetmacro\pgf@arcto@frac{\pgf@arcto@vec@x/\pgf@arcto@denominator} + \pgfmathsetmacro\pgf@arcto@theta@start{acos(\pgf@arcto@frac)} + \ifdim\pgf@arcto@vec@y pt<0pt + \pgfmathsetmacro\pgf@arcto@theta@start{-\pgf@arcto@theta@start} + \fi + % + % Step 8: Compute end angle: + % + \pgfmathsetmacro\pgf@arcto@vec@x{(-\pgf@arcto@xaprime-\pgf@arcto@cxprime)/\pgf@arcto@rx} + \pgfmathsetmacro\pgf@arcto@vec@y{(-\pgf@arcto@yaprime-\pgf@arcto@cyprime)/\pgf@arcto@ry} + \pgfmathsetmacro\pgf@arcto@denominator{veclen(\pgf@arcto@vec@x,\pgf@arcto@vec@y)} + \pgfmathsetmacro\pgf@arcto@frac{\pgf@arcto@vec@x/\pgf@arcto@denominator} + \pgfmathsetmacro\pgf@arcto@theta@end{acos(\pgf@arcto@frac)} + \ifdim\pgf@arcto@vec@y pt<0pt + \pgfmathsetmacro\pgf@arcto@theta@end{-\pgf@arcto@theta@end} + \fi + \pgfmathsetmacro\pgf@arcto@delta@theta{abs(\pgf@arcto@theta@start-\pgf@arcto@theta@end)} + \ifdim\pgf@arcto@fA pt=0pt% + \ifdim\pgf@arcto@delta@theta pt>180pt% + % Ok, we need to adjust the angle! + \ifdim\pgf@arcto@theta@end pt>\pgf@arcto@theta@start pt + \pgfmathsetmacro\pgf@arcto@theta@end{\pgf@arcto@theta@end-360} + \else + \pgfmathsetmacro\pgf@arcto@theta@end{\pgf@arcto@theta@end+360} + \fi + \fi + \else + \ifdim\pgf@arcto@delta@theta pt<180pt% + % Ok, we need to adjust the angle! + \ifdim\pgf@arcto@theta@end pt>\pgf@arcto@theta@start pt + \pgfmathsetmacro\pgf@arcto@theta@end{\pgf@arcto@theta@end-360} + \else + \pgfmathsetmacro\pgf@arcto@theta@end{\pgf@arcto@theta@end+360} + \fi + \fi + \fi + \xdef\pgf@marshal{\noexpand + \pgfpatharcaxes{\pgf@arcto@theta@start}{\pgf@arcto@theta@end} + {\noexpand\pgfpointpolar{\pgf@arcto@phi}{\pgf@arcto@rx}} + {\noexpand\pgfpointpolar{\pgf@arcto@phi+90}{\pgf@arcto@ry}} + } + \fi\fi\fi + } + \pgf@marshal +} + + + +% the quality of arc approximation by means of Bezier splines is +% controlled by a mesh width. +% +% The mesh width is provided in (full!) degrees. The smaller the mesh +% width, the more precise the arc approximation. +% +% Use an empty value to disable spline approximation (uses a single +% cubic polynomial for the complete arc). +% +% The value must be an integer! +\def\pgfpatharctomaxstepsize{45} + +% A specialized arc operation for an arc on an (axis--parallel) ellipse. +% +% In contrast to \pgfpatharc, it explicitly interpolates start- and end points. +% +% In contrast to \pgfpatharcto, this routine is numerically stable and +% quite fast since it relies on a lot of precomputed information. +% +% #1 center of ellipse +% #2 angle of last path position inside of the ellipse +% #3 end angle +% #4 end point (a \pgfpoint) +% #5 xradius +% #6 yradius +% #7 the ratio xradius/yradius of the ellipse +% #8 the ratio yradius/xradius of the ellipse +% Example: +% \def\cx{1cm}% center x +% \def\cy{1cm}% center y +% \def\startangle{0}% +% \def\endangle{45}% +% \def\a{5cm}% xradius +% \def\b{10cm}% yradius +% \pgfmathparse{\a/\b}\let\abratio=\pgfmathresult +% \pgfmathparse{\b/\a}\let\baratio=\pgfmathresult +% +% \pgfpathmoveto{\pgfpoint{\cx+\a*cos(\startangle)}{\cy+\b*sin(\startangle)}}% +% \pgfpatharctoprecomputed +% {\pgfpoint{\cx}{\cy}} +% {\startangle} +% {\endangle} +% {\pgfpoint{\cx+\a*cos(\endangle)}{\cy+\b*sin(\endangle)}}% +% {\a} +% {\b} +% {\abratio} +% {\baratio} +% +\def\pgfpatharctoprecomputed#1#2#3#4#5#6#7#8{% + \begingroup + % Implementation idea: + % + % let + % m = center (#1) + % \gamma_0 = start angle + % \gamma_1 = end angle + % a = x radius + % b = y radius + % + % an axis parallel ellipse is parameterized by + % C(\gamma) = m + ( a cos(\gamma), b sin(\gamma) ), \gamma in [0,360]. + % + % Now, consider the segment \gamma(t), + % \gamma:[0,1] -> [\gamma_0,\gamma_1], + % t -> \gamma_0 + t(\gamma_1 - \gamma_0) + % and + % C(\gamma(t)) which is defined on [0,1]. + % + % I'd like to approximate the arc by one or more cubic bezier + % splines which interpolate through the last and first provided + % points. + % + % In general, a Bezier spline C:[0,1] -> \R of order n fulfills + % C'(0) = n ( P_1 - P_0 ), + % C'(1) = n ( P_n - P_{n-1} ). + % For n=3 and given P_0 and P_3, I can directly compute P_1 and P_2 once I know + % the derivatives at t=0 and t=1. + % + % The derivatives in our case are + % ( C \circ \gamma )'(t) = C'[\gamma(t)] * \gamma'(t) + % = ( -a pi/180 sin(\gamma(t)), b pi/180 cos(\gamma(t)) ) * (\gamma_1 - \gamma_0). + % The pi/180 comes into play since we are working with degrees. + % + % Expression (C\circ\gamma)'(0) using P_0 and (C \circ \gamma)'(1) + % using P_3 yields the expressions + % (C \circ \gamma)'(0) = + % pi/180 * (\gamma_1 - \gamma_0)* [ - a/b(P_0^y - my), b/a (P_0^x - mx) ] + % (C \circ \gamma)'(1) = + % pi/180 * (\gamma_1 - \gamma_0)* [ - a/b(P_3^y - my), b/a (P_3^x - mx) ] + % + % defining + % scaleA = a/b * pi / (3*180) * (\gamma_1 - \gamma_0) + % and + % scaleB = b/a * pi / (3*180) * (\gamma_1 - \gamma_0) + % yields the direct expressions for the intermediate bezier + % control points + % + % P_1 = [ + % P_0^x - scaleA* ( P_0^y -my), + % P_0^y + scaleB* ( P_0^x -mx) ] + % and + % P_2 = [ + % P_3^x + scaleA* ( P_3^y -my), + % P_3^y - scaleB* ( P_3^x -mx) ]. + % + % This works fast, with few operations, if + % - a/b and b/a are known in advance + % - P_0 and P_3 are known in advance + % - \gamma_0 and \gamma_1 are known. + % + % It is also reliable if (\gamma_1 - \gamma_0) is small + % + \pgf@process{#1}% + \edef\pgfpath@center@x{\the\pgf@x}% + \edef\pgfpath@center@y{\the\pgf@y}% + \def\pgfpath@completearcend{#4}% + % compute scale (#3-#2) * pi/(3*180) = (#3 - #2) * pi/27 * 1/20 + % splitting pi/(3*180) into two scales has higher TeX accuracy + \pgf@xa=#2pt + \pgf@xb=#3pt + \edef\pgfpath@startangle{#2pt}% + \edef\pgfpath@endangle{\pgf@sys@tonumber\pgf@xb}% + % + \pgf@ya=\pgf@xb + \advance\pgf@ya by-\pgf@xa + % + \ifx\pgfpatharctomaxstepsize\pgfutil@empty + \def\pgfpath@N{1}% + \pgf@xc=\pgf@ya + \else + \pgf@xc=\pgf@ya% compute N = floor((gamma_1 - gamma_0) / max) +1 + \ifdim\pgf@xc<0pt + \multiply\pgf@xc by-1 + \fi + \divide\pgf@xc by\pgfpatharctomaxstepsize\relax + \afterassignment\pgfutil@gobble@until@relax + \c@pgf@counta=\the\pgf@xc\relax + \advance\c@pgf@counta by1 + \edef\pgfpath@N{\the\c@pgf@counta}% + % + \pgf@xc=\pgf@ya + \divide\pgf@xc by\c@pgf@counta + \fi + % + \edef\pgfpath@h{\pgf@sys@tonumber\pgf@xc}% + % +%\message{pgfpathellipse: using N =\pgfpath@N\space spline points y0 = \pgfpath@startangle, y0+i*h, yN=\pgfpath@endangle, i=1,...,(\pgfpath@N-1), with h=\pgfpath@h\space mesh width (total arc angle \pgf@sys@tonumber\pgf@ya).}% + % + % + \pgf@xc=0.116355283466289\pgf@xc % pi/27 + \divide\pgf@xc by20 + \pgf@xa=#7\pgf@xc + \edef\pgfpath@scale@A{\pgf@sys@tonumber\pgf@xa}% + \pgf@xa=#8\pgf@xc + \edef\pgfpath@scale@B{\pgf@sys@tonumber\pgf@xa}% + % + % compute intermediate spline segments for + % i = 1,...,N-1 + % this is a no-op for N=1. + \c@pgf@countd=1 + \pgfutil@loop + \ifnum\c@pgf@countd<\pgfpath@N\relax + % + \pgf@xa=\pgfpath@startangle % compute \pgf@xa = y_0 + i*h + \pgf@xb=\pgfpath@h pt + \multiply\pgf@xb by\c@pgf@countd + \advance\pgf@xa by\pgf@xb + \edef\pgfpath@angle@i{\pgf@sys@tonumber\pgf@xa}% +%\message{angle \the\c@pgf@countd: \pgfpath@angle@i...}% + % + \pgfpatharcofellipse@{% + \pgfpoint + {\pgfpath@center@x + #5*cos(\pgfpath@angle@i)} + {\pgfpath@center@y + #6*sin(\pgfpath@angle@i)}% + }% + % + \advance\c@pgf@countd by1 + \pgfutil@repeat + % + % compute final spline segment. It only differs insofar as the + % final point is already known explicitly and should be + % interpolated without additional math error. +%\message{angle \pgfpath@N: \pgfpath@endangle...}% + \pgfpatharcofellipse@{\pgfpath@completearcend}% + \endgroup +}% +\def\pgfpatharcofellipse@#1{% + \begingroup + \pgf@process{#1}% + \edef\pgfpath@endpt{\global\pgf@x=\the\pgf@x\space\global\pgf@y=\the\pgf@y\space}% + % + \pgfpathcurveto{ + \begingroup + \global\pgf@x=\pgf@path@lastx + \global\pgf@y=\pgf@path@lasty + \pgf@xa=\pgf@x \advance\pgf@xa by-\pgfpath@center@x + \pgf@ya=\pgf@y \advance\pgf@ya by-\pgfpath@center@y + \global\advance\pgf@x by-\pgfpath@scale@A\pgf@ya + \global\advance\pgf@y by \pgfpath@scale@B\pgf@xa + \endgroup + }{% + \begingroup + \pgfpath@endpt + \pgf@xa=\pgf@x \advance\pgf@xa by-\pgfpath@center@x + \pgf@ya=\pgf@y \advance\pgf@ya by-\pgfpath@center@y + \global\advance\pgf@x by \pgfpath@scale@A\pgf@ya + \global\advance\pgf@y by-\pgfpath@scale@B\pgf@xa + \endgroup + }{% + \pgfpath@endpt + }% + \endgroup +} + + + + + + + + + +% Append an ellipse to the current path. +% +% #1 = center +% #2 = first axis +% #3 = second axis +% +% Example: +% +% % Add a circle of radius 3cm around the origin +% \pgfpathellipse{\pgforigin}{\pgfxy(2,0)}{\pgfxy(0,1)} +% +% % Draw a non-filled circle of radius 1cm around the point (1,1) +% \pgfpathellipse{\pgfxy(1,1)}{\pgfxy(1,1)}{\pgfxy(-2,2)} +% \pgfstroke + +\def\pgfpathellipse#1#2#3{% + \pgfpointtransformed{#1}% store center in xc/yc + \pgf@xc=\pgf@x% + \pgf@yc=\pgf@y% + \pgfpointtransformed{#2}% + \pgf@xa=\pgf@x% store first axis in xa/ya + \pgf@ya=\pgf@y% + \advance\pgf@xa by-\pgf@pt@x% + \advance\pgf@ya by-\pgf@pt@y% + \pgfpointtransformed{#3}% + \pgf@xb=\pgf@x% store second axis in xb/yb + \pgf@yb=\pgf@y% + \advance\pgf@xb by-\pgf@pt@x% + \advance\pgf@yb by-\pgf@pt@y% + {% + \advance\pgf@xa by\pgf@xc% + \advance\pgf@ya by\pgf@yc% + \pgf@nlt@moveto{\pgf@xa}{\pgf@ya}% + }% + \pgf@x=0.55228475\pgf@xb% first arc + \pgf@y=0.55228475\pgf@yb% + \advance\pgf@x by\pgf@xa% + \advance\pgf@y by\pgf@ya% + \advance\pgf@x by\pgf@xc% + \advance\pgf@y by\pgf@yc% + \edef\pgf@temp{\pgf@xc\the\pgf@x\pgf@yc\the\pgf@y}% + \pgf@x=0.55228475\pgf@xa% + \pgf@y=0.55228475\pgf@ya% + \advance\pgf@x by\pgf@xb% + \advance\pgf@y by\pgf@yb% + {% + \advance\pgf@x by\pgf@xc% + \advance\pgf@y by\pgf@yc% + \advance\pgf@xb by\pgf@xc% + \advance\pgf@yb by\pgf@yc% + \pgf@temp% + \pgf@nlt@curveto{\pgf@xc}{\pgf@yc}{\pgf@x}{\pgf@y}{\pgf@xb}{\pgf@yb}% + }% + \pgf@xa=-\pgf@xa% flip first axis + \pgf@ya=-\pgf@ya% + \pgf@x=0.55228475\pgf@xa% second arc + \pgf@y=0.55228475\pgf@ya% + \advance\pgf@x by\pgf@xb% + \advance\pgf@y by\pgf@yb% + \advance\pgf@x by\pgf@xc% + \advance\pgf@y by\pgf@yc% + \edef\pgf@temp{\pgf@xc\the\pgf@x\pgf@yc\the\pgf@y}% + \pgf@x=0.55228475\pgf@xb% + \pgf@y=0.55228475\pgf@yb% + \advance\pgf@x by\pgf@xa% + \advance\pgf@y by\pgf@ya% + {% + \advance\pgf@x by\pgf@xc% + \advance\pgf@y by\pgf@yc% + \advance\pgf@xa by\pgf@xc% + \advance\pgf@ya by\pgf@yc% + \pgf@temp% + \pgf@nlt@curveto{\pgf@xc}{\pgf@yc}{\pgf@x}{\pgf@y}{\pgf@xa}{\pgf@ya}% + }% + \pgf@xb=-\pgf@xb% flip second axis + \pgf@yb=-\pgf@yb% + \pgf@x=0.55228475\pgf@xb% third arc + \pgf@y=0.55228475\pgf@yb% + \advance\pgf@x by\pgf@xa% + \advance\pgf@y by\pgf@ya% + \advance\pgf@x by\pgf@xc% + \advance\pgf@y by\pgf@yc% + \edef\pgf@temp{\pgf@xc\the\pgf@x\pgf@yc\the\pgf@y}% + \pgf@x=0.55228475\pgf@xa% + \pgf@y=0.55228475\pgf@ya% + \advance\pgf@x by\pgf@xb% + \advance\pgf@y by\pgf@yb% + {% + \advance\pgf@x by\pgf@xc% + \advance\pgf@y by\pgf@yc% + \advance\pgf@xb by\pgf@xc% + \advance\pgf@yb by\pgf@yc% + \pgf@temp% + \pgf@nlt@curveto{\pgf@xc}{\pgf@yc}{\pgf@x}{\pgf@y}{\pgf@xb}{\pgf@yb}% + }% + \pgf@xa=-\pgf@xa% flip first axis once more + \pgf@ya=-\pgf@ya% + \pgf@x=0.55228475\pgf@xa% fourth arc + \pgf@y=0.55228475\pgf@ya% + \advance\pgf@x by\pgf@xb% + \advance\pgf@y by\pgf@yb% + \advance\pgf@x by\pgf@xc% + \advance\pgf@y by\pgf@yc% + \edef\pgf@temp{\pgf@xc\the\pgf@x\pgf@yc\the\pgf@y}% + \pgf@x=0.55228475\pgf@xb% + \pgf@y=0.55228475\pgf@yb% + \advance\pgf@x by\pgf@xa% + \advance\pgf@y by\pgf@ya% + {% + \advance\pgf@x by\pgf@xc% + \advance\pgf@y by\pgf@yc% + \advance\pgf@xa by\pgf@xc% + \advance\pgf@ya by\pgf@yc% + \pgf@temp% + \pgf@nlt@curveto{\pgf@xc}{\pgf@yc}{\pgf@x}{\pgf@y}{\pgf@xa}{\pgf@ya}% + }% + \pgf@nlt@closepath% + \pgf@nlt@moveto{\pgf@xc}{\pgf@yc}% +} + + + +% Append a circle to the current path +% +% #1 = center +% #2 = radius +% +% Example: +% +% % Append a circle of radius 3cm around the point (1,1) +% \pgfpathcircle{\pgxy(1,1)}{3cm} + +\def\pgfpathcircle#1#2{\pgfpathellipse{#1}{\pgfpoint{#2}{0pt}}{\pgfpoint{0pt}{#2}}} + + + + +% Append a rectangle to the current path +% +% #1 = lower left corner point of rectangle +% #2 = width and height vector +% +% Example: +% +% % A rectangle with corners (2,2) and (3,3) +% \pgfpathrectangle{\pgfpointxy{2}{2}}{\pgfpointxy{1}{1}} + +\def\pgfpathrectangle{% + \let\pgfrect@next=\pgf@specialrect% + \ifpgf@pt@identity% + \ifpgf@arccorners% + \else% + \ifx\pgf@nlt@list\pgfutil@empty% + \let\pgfrect@next=\pgf@normalrect% + \fi% + \fi% + \fi% + \pgfrect@next% +} + +\def\pgf@normalrect#1#2{% + \pgf@process{#2}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgfpointtransformed{#1}% + \pgfsyssoftpath@rect{\the\pgf@x}{\the\pgf@y}{\the\pgf@xa}{\the\pgf@ya}% + \pgf@protocolsizes{\pgf@x}{\pgf@y}% + \advance\pgf@x by\pgf@xa\relax% + \advance\pgf@y by\pgf@ya\relax% + \pgf@protocolsizes{\pgf@x}{\pgf@y}% +} + +\def\pgf@specialrect#1#2{% + \pgf@process{#2}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgf@process{#1}% + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + \advance\pgf@xa by\pgf@xb% + \advance\pgf@ya by\pgf@yb% + \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}% + \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}% + \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yb}}% + \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}% + \pgfpathclose% + \pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@yb}}% +} + +% Append a rectangle to the current path +% +% #1 = one corner of the rectangle +% #2 = opposite corner of the rectangle +% +% Example: +% +% % A rectangle with corners (2,2) and (3,3) +% \pgfpathrectanglecorners{\pgfpointxy{2}{2}}{\pgfpointxy{3}{3}} + +\def\pgfpathrectanglecorners#1#2{% + \pgf@process{#2}% + \pgf@xc=\pgf@x% + \pgf@yc=\pgf@y% + \pgf@process{#1}% + \advance\pgf@xc by-\pgf@x% + \advance\pgf@yc by-\pgf@y% + \pgfpathrectangle{#1}{\pgfqpoint{\pgf@xc}{\pgf@yc}}% +} + + +% Append a grid to the current path. +% +% #1 = first corner point of grid +% #2 = second corner point of grid +% +% Options: +% +% stepx = x-step dimension (default 1cm) +% stepy = y-step dimension (default 1cm) +% step = dimension vector +% +% Example: +% +% \pgfsetlinewidth{0.8pt} +% \pgfgrid{\pgfxy(0,0)}{\pgfxy(3,2)} +% \pgfsetlinewidth{0.4pt} +% \pgfgrid[stepx=1cm,stepy=1cm]{\pgfxy(0,0)}{\pgfxy(3,2)} + +\pgfkeys{ + /pgf/stepx/.initial=1cm, + /pgf/stepy/.initial=1cm, + /pgf/step/.code={\pgf@process{#1}\pgfkeysalso{/pgf/stepx/.expanded=\the\pgf@x,/pgf/stepy/.expanded=\the\pgf@y}}, + /pgf/step/.value required +} + +\def\pgfpathgrid{\pgfutil@ifnextchar[{\pgf@pathgrid}{\pgf@pathgrid[]}} +\def\pgf@pathgrid[#1]#2#3{% + \pgfset{#1}% + \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/stepx}}% + \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/stepy}}% + \pgf@process{#3}% + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + \pgf@process{#2}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + % Swap coordinates if one of them is smaller than the other: + \ifdim\pgf@xa>\pgf@xb% + \pgf@x=\pgf@xb% + \pgf@xb=\pgf@xa% + \pgf@xa=\pgf@x% + \fi% + \ifdim\pgf@ya>\pgf@yb% + \pgf@y=\pgf@yb% + \pgf@yb=\pgf@ya% + \pgf@ya=\pgf@y% + \fi% + \ifdim \pgf@yc > .01pt\relax% if to draw horizontal lines + \c@pgf@counta=\pgf@ya\relax% + \c@pgf@countb=\pgf@yc\relax% + \divide\c@pgf@counta by\c@pgf@countb\relax% + \pgfutil@tempdima=\c@pgf@counta\pgf@yc\relax% + \ifdim\pgfutil@tempdima<\pgf@ya% + \advance\pgfutil@tempdima by\pgf@yc% + \fi% + \pgfutil@tempdimb\pgf@x + \pgfutil@loop% horizontal lines + {% + \pgf@xa=\pgfutil@tempdimb% + \pgf@ya=\pgfutil@tempdima% + \pgf@pos@transform{\pgf@xa}{\pgf@ya} + \pgf@nlt@moveto{\pgf@xa}{\pgf@ya}% + \pgf@xa=\pgf@xb% + \pgf@ya=\pgfutil@tempdima% + \pgf@pos@transform{\pgf@xa}{\pgf@ya} + \pgf@nlt@lineto{\pgf@xa}{\pgf@ya}% + }% + \advance\pgfutil@tempdima by\pgf@yc% + \ifdim\pgfutil@tempdima<\pgf@yb% + \pgfutil@repeat% + \advance\pgfutil@tempdima by-0.01pt\relax% + \ifdim\pgfutil@tempdima<\pgf@yb% + {% + \pgf@xa=\pgfutil@tempdimb% + \pgf@ya=\pgfutil@tempdima% + \pgf@pos@transform{\pgf@xa}{\pgf@ya} + \pgf@nlt@moveto{\pgf@xa}{\pgf@ya}% + \pgf@xa=\pgf@xb% + \pgf@ya=\pgfutil@tempdima% + \pgf@pos@transform{\pgf@xa}{\pgf@ya} + \pgf@nlt@lineto{\pgf@xa}{\pgf@ya}% + }% + \fi% + \fi% + \ifdim \pgf@xc > .01pt\relax% if to draw vertical lines + \c@pgf@counta=\pgf@xa\relax% + \c@pgf@countb=\pgf@xc\relax% + \divide\c@pgf@counta by\c@pgf@countb\relax% + \pgfutil@tempdimb=\c@pgf@counta\pgf@xc\relax% + \ifdim\pgfutil@tempdimb<\pgf@xa% + \advance\pgfutil@tempdimb by\pgf@xc% + \fi% + \pgfutil@loop% vertical lines + {% + \pgf@xc=\pgfutil@tempdimb% + \pgf@yc=\pgf@ya% + \pgf@pos@transform{\pgf@xc}{\pgf@yc} + \pgf@nlt@moveto{\pgf@xc}{\pgf@yc}% + \pgf@xc=\pgfutil@tempdimb% + \pgf@yc=\pgf@yb% + \pgf@pos@transform{\pgf@xc}{\pgf@yc} + \pgf@nlt@lineto{\pgf@xc}{\pgf@yc}% + }% + \advance\pgfutil@tempdimb by\pgf@xc% + \ifdim\pgfutil@tempdimb<\pgf@xb% + \pgfutil@repeat% + \advance\pgfutil@tempdimb by-0.01pt\relax% + \ifdim\pgfutil@tempdimb<\pgf@xb% + {% + \pgf@xc=\pgfutil@tempdimb% + \pgf@yc=\pgf@ya% + \pgf@pos@transform{\pgf@xc}{\pgf@yc} + \pgf@nlt@moveto{\pgf@xc}{\pgf@yc}% + \pgf@xc=\pgfutil@tempdimb% + \pgf@yc=\pgf@yb% + \pgf@pos@transform{\pgf@xc}{\pgf@yc} + \pgf@nlt@lineto{\pgf@xc}{\pgf@yc}% + }% + \fi% + \fi% + \pgf@process{#3}% + \pgf@pos@transform{\pgf@x}{\pgf@y}% + \pgf@nlt@moveto{\pgf@x}{\pgf@y}% +} + + + +% Append two half-parabolas to the path +% +% #1 = bend (relative to current point) +% #2 = end point (relative to bend point) +% +% Description: +% +% This command appends a half-parabola that starts at the current point +% and has its bend at #1+current point. Then, a second parabola is +% appended that starts at #1+current point, where it also has its +% minimum/maximum, and ends at #1+current point+#2, which becomes the +% new current point. +% +% By setting #2 = (0,0) you draw only a half parabola that goes from the +% current point to the bend; by setting #1 = (0,0) +% you draw a half parabola that going to current point + #2 and has its +% bend at the current point. +% +% Examples: +% +% % Half-parabola going ``up and right'' +% \pgfpathmoveto{\pgfpointorigin} +% \pgfpathparabola{\pgfpointorigin}{\pgfpoint{2cm}{4cm}} +% +% % Half-parabola going ``down and right'' +% \pgfpathmoveto{\pgfpointorigin} +% \pgfpathparabola{\pgfpoint{-2cm}{4cm}}}{\pgfpointorigin} +% +% % Full parabola +% \pgfpathmoveto{\pgfpointorigin} +% \pgfpathparabola{\pgfpoint{-2cm}{4cm}}{\pgfpoint{2cm}{4cm}} + +\def\pgfpathparabola#1#2{% + {% + \pgf@process{#2}% untransformed + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + \pgf@process{#1}% untransformed + \pgf@xc=\pgf@x% + \pgf@yc=\pgf@y% + \pgfutil@tempswatrue% + \ifdim\pgf@xb=0pt\relax% + \ifdim\pgf@yb=0pt\relax% + \pgfutil@tempswafalse% + \fi% + \fi% + {% + \ifpgfutil@tempswa% + \pgf@arccornersfalse + \else% + \fi% + \pgfutil@tempswatrue% + \ifdim\pgf@xc=0pt\relax% + \ifdim\pgf@yc=0pt\relax% + \pgfutil@tempswafalse% + \fi% + \fi% + \ifpgfutil@tempswa + {% + \pgf@pt@x=\pgf@path@lastx% + \pgf@pt@y=\pgf@path@lasty% + \pgfpathcurveto% + {\pgfqpoint{.1125\pgf@xc}{.225\pgf@yc}}% found by trial and error + {\pgfqpoint{.5\pgf@xc}{\pgf@yc}}% found by trial and error + {\pgfqpoint{\pgf@xc}{\pgf@yc}}% + }% + \fi% + }% + \ifpgfutil@tempswa% + \pgf@xc=\pgf@xb% + \pgf@yc=\pgf@yb% + {% + \pgf@pt@x=\pgf@path@lastx% + \pgf@pt@y=\pgf@path@lasty% + \pgfpathcurveto% + {\pgfqpoint{.5\pgf@xc}{0\pgf@yc}}% found by trial and error + {\pgfqpoint{.8875\pgf@xc}{.775\pgf@yc}}% found by trial and error + {\pgfqpoint{\pgf@xc}{\pgf@yc}}% + }% + \fi% + }% +} + + + + +% Append a sine curve between 0 and \pi/2 to the path. +% +% #1 = vector, describing the width and height of the curve +% +% Description: +% +% This command appends a sine curve in the interval 0 and \pi/2 to the +% current path. The sine curve ends at currentpoint+#1. +% +% Examples: +% +% % One complete sine in the interval [0,\pi] +% \pgfpathmoveto{\pgfpointorigin} +% \pgfpathsine{\pgfpoint{1.57cm}{1cm}} +% \pgfpathcosine{\pgfpoint{3.141cm}{0cm}} + +\def\pgfpathsine#1{% + {% + \pgf@process{#1}% untransformed + \pgf@xc=\pgf@x% + \pgf@yc=\pgf@y% + \pgf@pt@x=\pgf@path@lastx% evil trickery to transform to the last point + \pgf@pt@y=\pgf@path@lasty% + \pgfpathcurveto% + {\pgfqpoint{.3260\pgf@xc}{.5120\pgf@yc}}% + {\pgfqpoint{.6380\pgf@xc}{\pgf@yc}}% + {\pgfqpoint{\pgf@xc}{\pgf@yc}}% + }% +} + +% Append a cosine curve between 0 and \pi/2 to the path. +% +% #1 = vector, describing the width and height of the curve +% +% Examples: +% +% % One complete sine in the interval [0,\pi] +% \pgfpathmoveto{\pgfpointorigin} +% \pgfpathsine{\pgfpoint{1.57cm}{1cm}} +% \pgfpathcosine{\pgfpoint{3.141cm}{0cm}} + +\def\pgfpathcosine#1{% + {% + \pgf@process{#1}% untransformed + \pgf@xc=\pgf@x% + \pgf@yc=\pgf@y% + \pgf@pt@x=\pgf@path@lastx% evil trickery to transform to the last point + \pgf@pt@y=\pgf@path@lasty% + \pgfpathcurveto% + {\pgfqpoint{.3620\pgf@xc}{0pt}}% + {\pgfqpoint{.6740\pgf@xc}{.4880\pgf@yc}}% + {\pgfqpoint{\pgf@xc}{\pgf@yc}}% + }% +} + + + +% Draw part of a curve between two specified times s and t. +% +% #1 - a start time s. +% #2 - an end time t. +% #3 - start point of the curve +% #4 - first control +% #5 - second control +% #6 - end point of the curve +% +% There are two versions, \pgfpathcurvebetweentime and +% \pgfpathcurvebetweentimecontinue. The latter does not insert a +% moveto to the first point. +% +\def\pgfpathcurvebetweentime{\pgf@ignoremovetofalse\pgf@@pathcurvebetweentime} +\def\pgfpathcurvebetweentimecontinue{\pgf@ignoremovetotrue\pgf@@pathcurvebetweentime} +\newif\ifpgf@ignoremoveto + +\def\pgf@@pathcurvebetweentime#1#2#3#4#5#6{% + \pgfmathparse{#1}% + \let\pgf@time@s=\pgfmathresult% + \pgfmathparse{#2}% + \let\pgf@time@t=\pgfmathresult% + \ifdim\pgf@time@s pt>\pgf@time@t pt\relax% + \pgfmathsetmacro\pgf@time@s{1-#1}% + \pgfmathsetmacro\pgf@time@t{1-#2}% + \pgf@@@pathcurvebetweentime{\pgf@time@t}{#6}{#5}{#4}{#3}% + \else% + \pgf@@@pathcurvebetweentime{\pgf@time@t}{#3}{#4}{#5}{#6}% + \fi% +} + +\def\pgf@@@pathcurvebetweentime#1#2#3#4#5{% + % Q1 = P1. + \pgf@process{#2}% + \pgf@xc=\pgf@x% + \pgf@yc=\pgf@y% + % Q2 = P1 + t*(P2-P1). + \pgf@process{% + \pgf@process{#3}% + \pgf@xa=#1\pgf@x% + \pgf@ya=#1\pgf@y% + \pgf@process{#2}% + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + \advance\pgf@x by-#1\pgf@xb% + \advance\pgf@y by-#1\pgf@yb% + \advance\pgf@x by\pgf@xa% + \advance\pgf@y by\pgf@ya% + }% + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + % Q3 = Q2 + t*((P2 + t*(P3-P2)) - Q2). + \pgf@process{% + \pgf@process{#4}% + \pgf@xa=#1\pgf@x% + \pgf@ya=#1\pgf@y% + % + \pgf@process{#3}% + \pgf@xc=\pgf@x% + \pgf@yc=\pgf@y% + \advance\pgf@xc by-#1\pgf@x% + \advance\pgf@yc by-#1\pgf@y% + % + \pgf@x=\pgf@xb% + \pgf@y=\pgf@yb% + \advance\pgf@x by#1\pgf@xa% + \advance\pgf@y by#1\pgf@ya% + \advance\pgf@x by-#1\pgf@xb% + \advance\pgf@y by-#1\pgf@yb% + \advance\pgf@x by#1\pgf@xc% + \advance\pgf@y by#1\pgf@yc% + }% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + % Q4 = (1-t)^3*P1 + 3*t(1-t)^2*P2 + 3*t^2(1-t)*P3 + t^3*P4. + \pgf@process{\pgfpointcurveattime{#1}{#2}{#3}{#4}{#5}}% + \ifx#1\pgf@time@t% + % First time round... + \pgfmathdivide@{\pgf@time@s}{\pgf@time@t}% + \pgfmathadd@{-\pgfmathresult}{1}% + \let\pgf@time@s=\pgfmathresult% + \edef\pgf@marshal{% + \noexpand\pgf@@@pathcurvebetweentime{\noexpand\pgf@time@s}% + {\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}% + {\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}{\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}% + }% + \else% + % ...second time round. + \ifpgf@ignoremoveto% + \edef\pgf@marshal{% + \noexpand\pgfpathcurveto{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}% + {\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}{\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}% + }% + \else% + \edef\pgf@marshal{% + \noexpand\pgfpathmoveto{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}% + \noexpand\pgfpathcurveto{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}% + {\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}{\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}% + }% + \fi% + \fi% + \pgf@marshal% +} + + +\endinput diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcorepathprocessing.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcorepathprocessing.code.tex new file mode 100644 index 0000000000..e33f0653ce --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcorepathprocessing.code.tex @@ -0,0 +1,563 @@ +% Copyright 2018 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{pgfcorepathprocessing.code.tex} + + +% Split a path at the last subpath of a path +% +% #1 = a macro that stores a path +% +% Description: +% +% This command will split the path into two parts: +% +% \pgfprocessresultpathprefix +% The part of the path before the last subpath. +% +% \pgfprocessresultpathsuffix +% The last subpath on the path. +% +% #1 will always be equal to the contents of the two above macros +% concatenated. Normally, your objective will be to modify the +% \pgfprocessresultpathsuffix and then concatenate the result. + +\def\pgfprocesssplitpath#1{% + \let\pgfprocessresultpathprefix\pgfutil@empty% + \let\pgfprocessresultpathsuffix\pgfutil@empty% + \let\pgf@next\pgf@process@split% + \expandafter\pgf@process@split#1\pgfsyssoftpath@movetotoken{}{}\pgf@stop% +} + +\def\pgf@process@split#1\pgfsyssoftpath@movetotoken#2#3#4{% + \ifx#4\pgf@stop% ok, end reached! + \expandafter\def\expandafter\pgfprocessresultpathsuffix\expandafter{\pgfprocessresultpathsuffix#1}% + \let\pgf@next\pgfutil@gobble% + \else% + \expandafter\expandafter\expandafter\def% + \expandafter\expandafter\expandafter\pgfprocessresultpathprefix% + \expandafter\expandafter\expandafter{\expandafter\pgfprocessresultpathprefix\pgfprocessresultpathsuffix#1}% + \def\pgfprocessresultpathsuffix{\pgfsyssoftpath@movetotoken{#2}{#3}}% + \fi% + \pgf@next#4% +} + + + +% Split a subpath at the end +% +% #1 = a macro that stores an open subpath that contains at least two +% path commands (so, not just a moveto); +% +% Description: +% +% Splits the subpath into two parts: +% +% \pgfprocessresultsubpathsuffix +% This macro contains the last two "relevant" path commands: The end +% of the path command that led to the last path command and this +% last path command. In essence, this macro contains everything you +% "need to modify" if you wish to modify the end of the path. +% +% \pgfprocessresultsubpathprefix +% Everything before the previous macro on the subpath. + +\def\pgfprocesssplitsubpath#1{% + % First, we need to find the end: + \let\pgf@tempa\pgfutil@emtpy% + \let\pgf@tempb\pgfutil@emtpy% + \let\pgf@tempc\pgfutil@emtpy% + \let\pgf@tempd\pgfutil@emtpy% + \let\pgfprocessresultsubpathprefix\pgfutil@empty% + \let\pgfprocessresultsubpathsuffix\pgfutil@empty% + \let\pgf@next\pgf@split@subpath% + \expandafter\pgf@split@subpath#1\pgf@stop% +} + +\newif\ifpgf@split@move + +\def\pgf@split@subpath#1#2#3#4{% + \ifx#4\pgf@stop% + \expandafter\def\expandafter\pgfprocessresultsubpathsuffix\expandafter{\pgfprocessresultsubpathsuffix#1{#2}{#3}}% + \let\pgf@next\pgfutil@gobble% + \else% + \pgf@split@movetrue% + \ifx#1\pgfsyssoftpath@curvetosupportatoken% + \pgf@split@movefalse% + \else + \ifx#1\pgfsyssoftpath@curvetosupportbtoken% + \pgf@split@movefalse% + \fi% + \fi% + \ifpgf@split@move% + \expandafter\expandafter\expandafter\def% + \expandafter\expandafter\expandafter\pgfprocessresultsubpathprefix% + \expandafter\expandafter\expandafter{% + \expandafter\pgfprocessresultsubpathprefix\pgfprocessresultsubpathsuffix}% + \def\pgfprocessresultsubpathsuffix{#1{#2}{#3}}% + \else% + \expandafter\def\expandafter\pgfprocessresultsubpathsuffix\expandafter{\pgfprocessresultsubpathsuffix#1{#2}{#3}}% + \fi% + \fi% + \pgf@next#4% +} + + + + +% Extract start and end vectors of a path +% +% #1 = a macro that stores a path +% +% Description: +% +% This command will extract the first and second coordinate on the +% path as well as the last and second-last. These coordinates will be +% put in the pgfpoint-macros \pgfpointfirstonpath, +% \pgfpointsecondonpath, \pgfpointsecondlastonpath, and +% \pgfpointlastonpath. If the path is empty, these macros are set to +% \pgfpointorigin. +% +% Example: +% +% \pgfsyssoftpath@moveto{0}{0} +% \pgfsyssoftpath@lineto{10}{10} +% \pgfsyssoftpath@curveto{20}{20}{30}{30}{40}{40} +% \pgfsyssoftpath@getcurrentpath\mypath +% \pgfprocesspathextractpoints\mypath +% +% % \pgfpointfirstonpath is now \pgfpoint{0}{0} +% % \pgfpointsecondonpath is now \pgfpoint{10bp}{10bp} +% % \pgfpointsecondlastonpath is now \pgfpoint{30bp}{30bp} +% % \pgfpointlastonpath is now \pgfpoint{40bp}{40bp} + +\def\pgfprocesspathextractpoints#1{% + \ifx#1\pgfutil@empty% + \let\pgfpointfirstonpath=\pgfpointorigin% + \let\pgfpointsecondonpath=\pgfpointorigin% + \let\pgfpointsecondlastonpath=\pgfpointorigin% + \let\pgfpointlastonpath=\pgfpointorigin% + \else% + \expandafter\pgf@extractprocessorfirst#1\pgf@stop% + \fi% +} + +\def\pgf@extractprocessorfirst#1#2#3#4{% + \def\pgfpointfirstonpath{\pgfqpoint{#2}{#3}}% + \ifx#4\pgf@stop% + % pretty short path... + \let\pgfpointsecondonpath=\pgfpointfirstonpath% + \let\pgfpointsecondlastonpath=\pgfpointfirstonpath% + \let\pgfpointlastonpath=\pgfpointfirstonpath% + \let\next=\pgfutil@gobble% + \else + \let\next=\pgf@extractprocessorsecond% + \fi% + \next#4% +} + +\def\pgf@extractprocessorsecond#1{% + \ifx#1\pgfsyssoftpath@movetotoken% + % Reset things... + \let\pgf@next=\pgf@extractprocessorfirst% + \else% + \let\pgf@next=\pgf@@extractprocessorsecond% + \fi% + \pgf@next#1% +} +\def\pgf@@extractprocessorsecond#1#2#3#4{% + \def\pgfpointsecondonpath{\pgfqpoint{#2}{#3}}% + \let\pgfpointsecondlastonpath=\pgfpointfirstonpath% + \let\pgfpointlastonpath=\pgfpointsecondonpath% + \ifx#4\pgf@stop% + % short path... + \let\next=\pgfutil@gobble% + \else + \let\next=\pgf@extractprocessorother% + \fi% + \next#4% +} + +\def\pgf@extractprocessorother#1{% + \ifx#1\pgfsyssoftpath@movetotoken% + % Reset things... + \let\pgf@next=\pgf@extractprocessorfirst% + \else% + \let\pgf@next=\pgf@@extractprocessorother% + \fi% + \pgf@next#1% +} +\def\pgf@@extractprocessorother#1#2#3#4{% + \let\pgfpointsecondlastonpath=\pgfpointlastonpath% + \def\pgfpointlastonpath{\pgfqpoint{#2}{#3}}% + \ifx#4\pgf@stop% + % end! + \let\next=\pgfutil@gobble% + \fi% + \next#4% +} + + + +% Check for closepath and rectangles +% +% #1 = a macro that stores a path +% #2 = command to be executed when a closepath or a rectangle is encountered +% +% Example: +% +% \pgfsyssoftpath@moveto{0}{0} +% \pgfsyssoftpath@lineto{10}{10} +% \pgfsyssoftpath@curveto{20}{20}{30}{30}{40}{40} +% \pgfsyssoftpath@getcurrentpath\mypath +% \pgfprocesscheckclosed{\mypath}{\pgf@drawarrowsfalse} + +\def\pgfprocesscheckclosed#1#2{% + {% + \global\let\pgf@proc@todo=\relax% + \let\pgfsyssoftpath@movetotoken=\pgfutil@gobbletwo% + \let\pgfsyssoftpath@linetotoken=\pgfutil@gobbletwo% + \let\pgfsyssoftpath@curvetosupportatoken=\pgfutil@gobbletwo% + \let\pgfsyssoftpath@curvetosupportbtoken=\pgfutil@gobbletwo% + \let\pgfsyssoftpath@curvetotoken=\pgfutil@gobbletwo% + \def\pgfsyssoftpath@rectcornertoken{\gdef\pgf@proc@todo{#2}\pgfutil@gobbletwo}% + \def\pgfsyssoftpath@rectsizetoken{\gdef\pgf@proc@todo{#2}\pgfutil@gobbletwo}% + \def\pgfsyssoftpath@closepathtoken{\gdef\pgf@proc@todo{#2}\pgfutil@gobbletwo}% + #1% + }% + \pgf@proc@todo% +} + + +% Resolve specialround +% +% #1 = a macro that stores a path +% #2 = a macro that stores the new path +% +% Description: +% +% Resolves all specialround tokens. When such a token is encountered, +% the objective is to replace the next corner by a rounded corner. +% + +\def\pgfprocessround#1#2{% + % first, check whether #1 contains \pgfsyssoftpath@specialroundtoken. + % if not, do quick assignment! + \expandafter\pgf@processroundcheck\expandafter#1\expandafter#2#1\pgfsyssoftpath@specialroundtoken\pgf@stop% +} + +\def\pgf@processroundcheck#1#2#3\pgfsyssoftpath@specialroundtoken#4\pgf@stop{% + \def\pgf@test{#4}% + \ifx\pgf@test\pgfutil@empty% + % ok, nothing to be done! + \let#2=#1% + \else% + % very well... + \pgf@@processround#1#2% + \fi% +} + + +\def\pgf@@processround#1#2{% + \let\pgfprocess@newpath\pgfutil@empty% + \let\pgfprocess@moveto\pgfutil@empty% + \let\pgfprocess@firstto\pgfutil@empty% + \let\pgfprocess@segment\pgfutil@empty% + \pgf@xa=0pt% + \pgf@ya=0pt% + \expandafter\pgfprocess@round#1\pgf@stop{0pt}{0pt}% + \expandafter\pgfutil@g@addto@macro\expandafter\pgfprocess@newpath\expandafter{\pgfprocess@moveto}% + \expandafter\pgfutil@g@addto@macro\expandafter\pgfprocess@newpath\expandafter{\pgfprocess@segment}% + \let#2=\pgfprocess@newpath% +} + +\def\pgfprocess@round#1#2#3{% + \ifx#1\pgf@stop% + \let\next=\relax% + \else% + \ifx#1\pgfsyssoftpath@specialroundtoken% + \def\pgfprocess@savex{#2}% + \def\pgfprocess@savey{#3}% + \let\next=\pgfprocess@specialround% + \ifdim#2=0pt% + \ifdim#3=0pt% + \let\next=\pgfprocess@round% skip! + \fi% + \fi% + \else% + \ifx\pgfprocess@firstto\pgfutil@empty% + \def\pgfprocess@firstto{{#2}{#3}}% + \fi% + \pgf@xa=#2% + \pgf@ya=#3% + \ifx#1\pgfsyssoftpath@movetotoken% + % ok, move old segment to newpath + \expandafter\pgfutil@g@addto@macro\expandafter\pgfprocess@newpath\expandafter{\pgfprocess@moveto}% + \expandafter\pgfutil@g@addto@macro\expandafter\pgfprocess@newpath\expandafter{\pgfprocess@segment}% + \def\pgfprocess@moveto{#1{#2}{#3}}% + \let\pgfprocess@firstto=\pgfutil@empty% + \let\pgfprocess@segment=\pgfutil@empty% + \else% + \pgfutil@g@addto@macro\pgfprocess@segment{#1{#2}{#3}}% + \fi% + \let\next=\pgfprocess@round% + \fi% + \fi% + \next% +} + +\def\pgfprocess@specialround#1#2#3{% + \ifx\pgfprocess@firstto\pgfutil@empty% + \def\pgfprocess@firstto{{#2}{#3}}% + \fi% + \let\next=\pgfprocess@round% default: do nothing + \ifx#1\pgfsyssoftpath@linetotoken% + % Ok, round a lineto + \let\next=\pgfprocess@specialroundcope% + \else% + \ifx#1\pgfsyssoftpath@curvetosupportatoken% + % Ok, round a curveto. + \let\next=\pgfprocess@specialroundcurveto% + \else% + \ifx#1\pgfsyssoftpath@closepathtoken% + % Ok, round a closepath (this is tricky...) + \let\next=\pgfprocess@specialroundclose% + \fi% + \fi% + \fi% + \next#1{#2}{#3}% +}% + +\def\pgfprocess@specialroundcope#1#2#3#4#5#6{% + \let\next=\pgfprocess@round% do nothing by default + \let\pgfprocess@continueafterrounding=\pgfprocess@round% + \ifx#4\pgfsyssoftpath@linetotoken% + % ok, let's get kicking... + \pgf@xc=#5% + \pgf@yc=#6% + \let\next=\pgfprocess@@specialround% + \else% + \ifx#4\pgfsyssoftpath@curvetosupportatoken% + \pgf@xc=#5% + \pgf@yc=#6% + \let\next=\pgfprocess@@specialround% + \else% + \ifx#4\pgfsyssoftpath@closepathtoken% + \pgf@xc=#5% + \pgf@yc=#6% + \let\next=\pgfprocess@@specialround% + \else + \ifx#4\pgfsyssoftpath@specialroundtoken% + \let\next=\pgfprocess@@findrightcoordinates% + \fi% + \fi% + \fi% + \fi% + \next#1{#2}{#3}#4{#5}{#6}% +} + +\def\pgfprocess@@findrightcoordinates#1#2#3#4#5#6#7#8#9{% + \pgf@xc=#8% + \pgf@yc=#9% + \pgfprocess@@specialround#1{#2}{#3}#4{#5}{#6}#7{#8}{#9}% +} + +\def\pgfprocess@@specialround#1#2#3{% + \pgfutil@g@addto@macro\pgfprocess@segment{#1}% + % calculate start coordinate of the curve + \pgf@xb=#2% + \pgf@yb=#3% + % + \edef\pgf@marshal% + {\noexpand\pgfpointlineatdistance{\pgfprocess@savex}% + {\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}% + {\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}}% + \pgf@process{\pgf@marshal}% + \pgf@xa=\pgf@x% save start point of added curve + \pgf@ya=\pgf@y% + \edef\pgfprocess@addition{{\the\pgf@x}{\the\pgf@y}}% + \expandafter\pgfutil@g@addto@macro\expandafter\pgfprocess@segment\expandafter{\pgfprocess@addition}% + % + % now add curve + % + \edef\pgf@marshal% + {\noexpand\pgfpointlineatdistance{\pgfprocess@savey}% + {\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}% + {\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}}% + \pgf@process{\pgf@marshal}% + \pgf@xc=\pgf@x% save end point of added curve + \pgf@yc=\pgf@y% + % calculate first support: + {% + \pgf@x=\pgf@xb% + \pgf@y=\pgf@yb% + \advance\pgf@x by-\pgf@xa% + \advance\pgf@y by-\pgf@ya% + \advance\pgf@xa by 0.5522847\pgf@x% + \advance\pgf@ya by 0.5522847\pgf@y% + \edef\pgfprocess@addition{\noexpand\pgfsyssoftpath@curvetosupportatoken{\the\pgf@xa}{\the\pgf@ya}}% + \expandafter\pgfutil@g@addto@macro\expandafter\pgfprocess@segment\expandafter{\pgfprocess@addition}% + }% + % calculate second support: + {% + \pgf@x=\pgf@xb% + \pgf@y=\pgf@yb% + \advance\pgf@x by-\pgf@xc% + \advance\pgf@y by-\pgf@yc% + \advance\pgf@xc by 0.5522847\pgf@x% + \advance\pgf@yc by 0.5522847\pgf@y% + \edef\pgfprocess@addition{\noexpand\pgfsyssoftpath@curvetosupportbtoken{\the\pgf@xc}{\the\pgf@yc}}% + \expandafter\pgfutil@g@addto@macro\expandafter\pgfprocess@segment\expandafter{\pgfprocess@addition}% + }% + % add end: + \edef\pgfprocess@addition{\noexpand\pgfsyssoftpath@curvetotoken{\the\pgf@xc}{\the\pgf@yc}}% + \expandafter\pgfutil@g@addto@macro\expandafter\pgfprocess@segment\expandafter{\pgfprocess@addition}% + % + % continue! + % + \pgf@xa=#2% + \pgf@ya=#3% + \pgfprocess@continueafterrounding% +} + +\def\pgfprocess@specialroundcurveto#1#2#3#4#5#6{% + \pgfutil@g@addto@macro\pgfprocess@segment{#1{#2}{#3}#4{#5}{#6}}% supports + \pgf@xa=#5% + \pgf@ya=#6% + \pgfprocess@specialroundcope} + +\def\pgfprocess@specialroundclose{% + \let\next=\pgfprocess@round% + \ifx\pgfprocess@moveto\pgfutil@empty% + \else% + \ifx\pgfprocess@firstto\pgfutil@empty% + \else% + \expandafter\pgfprocess@@specialclosetarget\pgfprocess@firstto% + \let\pgfprocess@continueafterrounding=\pgfprocess@cleanupafterclose% + \edef\next{% + \noexpand\pgfprocess@@specialround% + \expandafter\expandafter\expandafter\noexpand\expandafter\pgfprocess@@specialclosemoveto\pgfprocess@moveto% + }% + \fi% + \fi% + \next% +} + +\def\pgfprocess@@specialclosetarget#1#2{% + \pgf@xc=#1% + \pgf@yc=#2% +} + +\def\pgfprocess@@specialclosemoveto#1#2#3{% + \pgfsyssoftpath@linetotoken{#2}{#3}% +} + + +\def\pgfprocess@cleanupafterclose#1#2#3{% + \edef\pgfprocess@moveto{\noexpand\pgfsyssoftpath@movetotoken{\the\pgf@xc}{\the\pgf@yc}}% + \edef\pgf@marshal{\noexpand\pgfprocess@round\noexpand\pgfsyssoftpath@closepathtoken{\the\pgf@xc}{\the\pgf@yc}}% + \pgf@marshal% +} + + +% Replace start and end coordinates of a path +% +% #1 = new start coordinate +% #2 = new end coordinate +% +% Description: +% +% This command will replace the first and last coordinates on a path +% by the given coordinates. +% +% Example: +% +% \pgfsyssoftpath@moveto{0}{0} +% \pgfsyssoftpath@lineto{10}{10} +% \pgfsyssoftpath@curveto{20}{20}{30}{10}{40}{0} +% \pgfsyssoftpath@getcurrentpath\mypath +% \pgfsetlinewidth{2pt} +% \pgfusepath{stroke} +% \pgfprocesspathextractpoints{\mypath} +% \pgfprocesspathreplacestartandend{\mypath} +% {\pgfpointlineatdistance{2pt}{\pgfpointfirstonpath}{\pgfpointsecondonpath}}% +% {\pgfpointlineatdistance{2pt}{\pgfpointlastonpath}{\pgfpointsecondlastonpath}}% +% \pgfsyssoftpath@setcurrentpath\mypath +% \pgfsetlinewidth{1pt} +% \color{red} +% \pgfusepath{stroke} + +\def\pgfprocesspathreplacestartandend#1#2#3{% + \ifx#1\pgfutil@empty% + \else% + {% + % We (mis)use the current path to store (in a buffered manner) the + % rest path. + \pgfsyssoftpath@getcurrentpath\pgf@replace@origpath% + \let\pgf@prepath=\pgfutil@empty% + \pgf@process{#3}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgf@process{#2}% + \expandafter\pgf@replaceprocessfirst#1\pgf@stop% + \pgfsyssoftpath@getcurrentpath\pgf@restpath% + \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\gdef% + \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter#1% + \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter\pgf@prepath% + \expandafter\pgf@newstart\pgf@restpath}% + % Restore current path + \pgfsyssoftpath@setcurrentpath\pgf@replace@origpath% + }% + \fi% +} + +\def\pgf@replaceprocessfirst#1#2#3#4{% + \def\pgf@origstart{#1{#2}{#3}}% + \edef\pgf@newstart{\noexpand#1{\the\pgf@x}{\the\pgf@y}}% + \pgfsyssoftpath@setcurrentpath\pgfutil@empty% + \ifx#4\pgf@stop% + \let\pgf@next=\pgfutil@gobble% + \else% + \let\pgf@next=\pgf@replaceprocessother% + \let\pgf@@next=\pgf@@replaceprocessother% + \fi% + \pgf@next#4% +} + +\def\pgf@replaceprocessother#1{% + \ifx#1\pgfsyssoftpath@movetotoken% + \pgf@replace@handle@move% + \fi% + \pgf@@next#1% +} +\def\pgf@@replaceprocessother#1#2#3#4{% + \ifx#4\pgf@stop% + \edef\pgf@restpathaddition{{\noexpand#1{\the\pgf@xa}{\the\pgf@ya}}}% + \expandafter\pgfsyssoftpath@addtocurrentpath\pgf@restpathaddition% + \let\pgf@next=\pgfutil@gobble% + \else% + \pgfsyssoftpath@addtocurrentpath{#1{#2}{#3}}% + \fi% + \pgf@next#4% +} + +\def\pgf@replace@handle@move{% + \pgfsyssoftpath@getcurrentpath\pgf@restpath% + % Arggghh! Must reset everything! + \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\gdef% + \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\pgf@prepath% + \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter\pgf@prepath% + \expandafter\pgf@origstart\pgf@restpath}% + % Redo first. + \let\pgf@@next=\pgf@replaceprocessfirst% +} + +\endinput diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcorepathusage.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcorepathusage.code.tex new file mode 100644 index 0000000000..5a9c5fc22b --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcorepathusage.code.tex @@ -0,0 +1,661 @@ +% Copyright 2018 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{pgfcorepathusage.code.tex} + + +% Stroke/fill/clip/etc. the current path. Depending on the options, +% the current path will be stroked/filled/clipped/etc. If no options +% are given, the path is stroked. If multiple options are given, all +% of them are performed (in a sensible order). +% +% #1 = action(s) to be applied to the current path. Valid actions are: +% stroke - strokes the path. +% draw - strokes the path and adds arrow tips. +% tips - adds arrow tips. +% fill - fills the path. +% clip - clip the path. +% discard - Discards the path. Same effect as having an empty +% options list. +% +% Example: +% +% % Draws an edge. +% \pgfpathmoveto{\pgfxy(0,0)} +% \pgfpathlineto{\pgfxy(0,1)} +% \pgfpathlineto{\pgfxy(1,0)} +% \pgfusepath{stroke} + +\pgfkeys{ + /pgf/stroke/.code=\let\pgf@up@stroke\pgf@up@stroke@text\pgf@up@path@neededtrue, + /pgf/draw/.code=\let\pgf@up@stroke\pgf@up@stroke@text\pgf@up@path@neededtrue, + /pgf/fill/.code=\let\pgf@up@fill\pgf@up@fill@text\pgf@up@path@neededtrue, + /pgf/clip/.code=\let\pgf@up@clip\pgf@up@clip@text\pgf@up@path@neededtrue, + /pgf/discard/.code=, + /pgf/use as bounding box/.code=\let\pgf@up@bb\pgf@do@up@bb, + /pgf/arrow keys/flex/.code=\pgferror{You need to say \string\usetikzlibrary{bending} for flexing and bending arrows}, + /pgf/arrow keys/flex'/.code=\pgferror{You need to say \string\usetikzlibrary{bending} for flexing and bending arrows}, + /pgf/arrow keys/bend/.code=\pgferror{You need to say \string\usetikzlibrary{bending} for flexing and bending arrows}, + /pgf/arrow keys/quick/.code=\pgfarrowsaddtooptions{\let\pgf@arrow@flex@mode\pgf@arrow@mode@is@quick}, +} + +\pgfkeys{ + /pgf/.cd, + tips/.is choice, + tips/.default=true, + tips/proper/.code=\let\pgf@tips@mode\pgf@tips@mode@onproper, + tips/on proper draw/.code=\let\pgf@tips@mode\pgf@tips@mode@onproperdraw, + tips/true/.code=\let\pgf@tips@mode\pgf@tips@mode@true, + tips/on draw/.code=\let\pgf@tips@mode\pgf@tips@mode@ondraw, + tips/never/.code=\let\pgf@tips@mode\pgf@tips@mode@false, + tips/false/.code=\let\pgf@tips@mode\pgf@tips@mode@false, +} +\def\pgf@tips@mode@onproper{4} +\def\pgf@tips@mode@onproperdraw{3} +\def\pgf@tips@mode@true{2} +\def\pgf@tips@mode@ondraw{1} +\def\pgf@tips@mode@false{0} +\let\pgf@tips@mode\pgf@tips@mode@ondraw + + +% The following can only be set to "true" using the options in the +% module "bending" +\newif\ifpgf@precise@shortening +\def\pgf@arrow@mode@is@quick{0} +\let\pgf@arrow@flex@mode\pgf@arrow@mode@is@quick + +\newif\ifpgf@up@path@needed +\newif\ifpgf@up@draw@arrows +\def\pgf@up@stroke@text{stroke} +\def\pgf@up@fill@text{fill} +\def\pgf@up@clip@text{clip} +\def\pgf@do@up@bb{\pgf@relevantforpicturesizefalse} + +\def\pgfusepath#1{% + \pgf@up@path@neededfalse% + \pgf@up@draw@arrowsfalse% + \let\pgf@up@stroke\pgfutil@empty% + \let\pgf@up@fill\pgfutil@empty% + \let\pgf@up@clip\pgfutil@empty% + \let\pgf@up@bb\pgfutil@empty% + \pgfset{#1}% + \expandafter\def\expandafter\pgf@up@action\expandafter{\csname pgfsys@\pgf@up@fill\pgf@up@stroke\endcsname}% + \ifnum\pgf@tips@mode=2\relax% + \pgf@up@path@neededtrue% + \fi% + \ifnum\pgf@tips@mode=4\relax% + \pgf@up@path@neededtrue% + \fi% + \ifpgf@up@path@needed% + \else% + \pgfsyssoftpath@setcurrentpath\pgfutil@empty% + \fi% + \ifx\pgf@up@stroke\pgfutil@empty% + \ifx\pgf@up@fill\pgfutil@empty% + \let\pgf@up@action=\pgfutil@empty% + \ifx\pgf@up@clip\pgfutil@empty% + \else% + % only clipping + \let\pgf@up@action=\pgfsys@discardpath% + \fi% + \fi% + \fi% + \pgfsyssoftpath@getcurrentpath\pgf@last@processed@path + \pgfprocessround{\pgf@last@processed@path}{\pgf@last@processed@path}% change the path + \pgfsyssoftpath@setcurrentpath\pgf@last@processed@path% + % + % Check whether the path is stroked. If so, add half the line width + % to the bounding box. + % + \ifpgf@relevantforpicturesize% + \ifx\pgf@up@stroke\pgfutil@empty% + \else% + \ifdim\pgf@picmaxx=-16000pt\relax% + \else% + \pgf@x=\pgf@pathminx\advance\pgf@x by-.5\pgflinewidth% + \ifdim\pgf@x<\pgf@picminx\global\pgf@picminx\pgf@x\fi% + \pgf@y=\pgf@pathminy\advance\pgf@y by-.5\pgflinewidth% + \ifdim\pgf@y<\pgf@picminy\global\pgf@picminy\pgf@y\fi% + \pgf@x=\pgf@pathmaxx\advance\pgf@x by.5\pgflinewidth% + \ifdim\pgf@x>\pgf@picmaxx\global\pgf@picmaxx\pgf@x\fi% + \pgf@y=\pgf@pathmaxy\advance\pgf@y by.5\pgflinewidth% + \ifdim\pgf@y>\pgf@picmaxy\global\pgf@picmaxy\pgf@y\fi% + \fi% + \fi% + \fi% + % + \ifx\pgf@up@clip\pgfutil@empty% + \ifx\pgf@up@stroke\pgfutil@empty% + \ifx\pgf@up@action\pgfutil@empty% + \ifnum\pgf@tips@mode=2\relax% + \pgf@up@draw@arrows@only% + \fi% + \ifnum\pgf@tips@mode=4\relax% + \pgf@up@draw@arrows@only% + \fi% + \else% + \pgfsyssoftpath@invokecurrentpath% + \pgf@up@action% + \fi% + \else% + \pgfgetpath\pgf@arrowpath% + \pgf@path@setup@tempswa% + \pgfprocesscheckclosed{\pgf@arrowpath}{\pgfutil@tempswafalse}% + \pgf@path@check@proper% + \ifpgfutil@tempswa% + \pgf@check@for@arrow@and@animation% + \pgf@prepare@end@of@path% + \begingroup% + \pgf@prepare@start@of@path% + \fi% + \pgfsyssoftpath@invokecurrentpath% + \pgf@up@action% + \ifdim\pgfinnerlinewidth>0pt\relax% + \pgf@stroke@inner@line% + \fi% + \ifpgfutil@tempswa% + \pgf@add@arrow@at@start% + \endgroup% + \pgf@add@arrow@at@end% + \fi% + \fi% + \else% + \pgfsyssoftpath@invokecurrentpath% + \pgfsys@clipnext% + \pgf@up@action% + \pgf@relevantforpicturesizefalse% + \fi% + \pgf@up@bb% + \pgfsyssoftpath@setcurrentpath\pgfutil@empty% + \pgf@resetpathsizes% + \ignorespaces% +} +\def\pgf@path@setup@tempswa{% + \ifnum\pgf@tips@mode>0\relax + \pgfutil@tempswatrue% + \else + \pgfutil@tempswafalse% + \fi% +} +\def\pgf@up@draw@arrows@only{% + \pgfgetpath\pgf@arrowpath% + \pgfutil@tempswatrue% + \pgfprocesscheckclosed{\pgf@arrowpath}{\pgfutil@tempswafalse}% + \pgf@path@check@proper% + \ifpgfutil@tempswa% + \pgf@check@for@arrow@and@animation% + \pgf@prepare@end@of@path% + \begingroup% + \pgf@prepare@start@of@path% + \pgf@add@arrow@at@start% + \endgroup% + \pgf@add@arrow@at@end% + \fi% +} + +\def\pgf@check@for@arrow@and@animation{\pgfsys@if@fresh@currentid{\pgf@check@for@arrow@and@animation@}{}}% +\def\pgf@check@for@arrow@and@animation@{% + \expandafter\ifx\csname pgfsysanim@path@is@animated@\pgf@sys@id@current@id @\pgfsys@current@type\endcsname\pgfutil@empty% + % Ok, an animation is here! + \ifx\pgf@end@tip@sequence\pgfutil@empty% + \ifx\pgf@start@tip@sequence\pgfutil@empty% + \else% + \pgf@check@for@arrow@and@animation@error% + \fi% + \else% + \pgf@check@for@arrow@and@animation@error% + \fi% + \fi% +} +\def\pgf@check@for@arrow@and@animation@error{\pgferror{Animated path may not have normal arrow tips. Use a base path with arrow tips}} + +\def\pgf@path@check@proper{% + \ifpgfutil@tempswa% + \ifnum\pgf@tips@mode>2\relax% + \pgf@path@check@proper@% + \fi% + \fi% +} + +\def\pgf@path@check@proper@{% + {% + \pgf@x0pt\pgf@y\pgf@x% + \pgfutil@tempswatrue% + \let\pgfsyssoftpath@movetotoken\pgf@path@proper@init% + \let\pgfsyssoftpath@linetotoken\pgf@path@proper@test%% + \let\pgfsyssoftpath@curvetosupportatoken\pgf@path@proper@test% + \let\pgfsyssoftpath@curvetosupportbtoken=\pgf@path@proper@test% + \let\pgfsyssoftpath@curvetotoken\pgf@path@proper@test% + \let\pgfsyssoftpath@rectcornertoken\pgf@path@proper@test% + \let\pgfsyssoftpath@rectsizetoken\pgf@path@proper@zero@test% + \let\pgfsyssoftpath@closepathtoken\pgf@path@proper@test% + % Execute the path: + \pgf@arrowpath% + \expandafter + }% + \ifpgfutil@tempswa\pgfutil@tempswafalse\else\pgfutil@tempswatrue\fi% +} + +\def\pgf@path@proper@init#1#2{\pgfutil@tempswatrue\pgf@x#1\pgf@y#2}% +\def\pgf@path@proper@test#1#2{% + \ifdim\pgf@x=#1\relax\else\pgfutil@tempswafalse\fi% + \ifdim\pgf@y=#2\relax\else\pgfutil@tempswafalse\fi} +\def\pgf@path@proper@zero@test#1#2{% + \ifdim\pgf@x=0pt\relax\else\pgfutil@tempswafalse\fi% + \ifdim\pgf@y=0pt\relax\else\pgfutil@tempswafalse\fi} + + + + +\def\pgf@stroke@inner@line{% + \let\pgf@temp@save=\pgf@strokecolor@global + \pgfsys@beginscope% + {% + \pgfsys@setlinewidth{\pgfinnerlinewidth}% + \pgfsetstrokecolor{\pgfinnerstrokecolor}% + \pgfsyssoftpath@invokecurrentpath% + \pgfsys@stroke% + }% + \pgfsys@endscope% + \global\let\pgf@strokecolor@global=\pgf@temp@save +} + +\let\pgf@prepare@start@of@path\relax% + + + + +% Shorten start/end of paths by a certain amount. +% +% #1 = amount by which paths should be shortened. +% +% Example: +% +% \pgfpathmoveto{\pgfpointorigin} +% \pgfpathlineto{\pgfpoint{10pt}{0pt} +% +% % The following has the same effect: +% \pgfsetshortenstart{1pt} +% \pgfpathmoveto{\pgfpointorigin} +% \pgfpathlineto{\pgfpoint{11pt}{0pt} + +\def\pgfsetshortenstart#1{\pgfmathsetlength\pgf@shorten@start@additional{#1}} +\def\pgfsetshortenend#1{\pgfmathsetlength\pgf@shorten@end@additional{#1}} + +\newdimen\pgf@shorten@end@additional +\newdimen\pgf@shorten@start@additional + + + +% +% +% Handling the end of a path +% +% +% The "handling" consists of first testing whether we need to do +% anything at all, namely because either an arrow tip should be drawn +% at the end or because the path should be shortened at the end. If +% so, we shorten the path if needed and, later on, add the arrow tip. +% + +\newif\ifpgf@worry + + +% Prepare the end of the path: Test whether anything must be done +% (step 0) and, if so, split the path (step 1), extract the interesting points from +% the path (step 2), prepare further computations (step 3), shorten +% the path (step 4) if necessary, and add the arrow tip (step 4 in +% macro \pgf@add@arrow@at@end, which is called later). + +\def\pgf@prepare@end@of@path{% + \let\pgfprocessresultpathsuffix\relax% flag that nothing has happened... + \let\pgfprocessresultsubpathsuffix\relax% + \pgfsyssoftpath@getcurrentpath\pgf@arrowpath% + % + % Step 0 start: + % + % Do we need to worry about the end? + % + \ifx\pgf@arrowpath\pgfutil@empty\else% + \pgf@worryfalse% + \ifx\pgf@end@tip@sequence\pgfutil@empty% + \else% + \pgf@worrytrue% Yes, worry if we have to draw an arrow + \fi% + \pgf@precise@shorteningfalse% + \pgf@arrow@compute@shortening\pgf@end@tip@sequence% + \advance\pgf@xa by\pgf@shorten@end@additional% + \advance\pgf@xb by\pgf@shorten@end@additional% + \ifdim\pgf@xa=0pt\relax\else\pgf@worrytrue\fi% Also, worry if shortening is requested + \edef\pgf@path@shortening@distance{\the\pgf@xa}% + \edef\pgf@arrow@tip@total@length{\the\pgf@xb}% + % + % Step 0 done. + % + \ifpgf@worry% + % Ok, need to "worry" about the end, either because we need to + % shorten it or to draw an arrow head. + % + % Step 1: Split + % + \pgfprocesssplitpath{\pgf@arrowpath}% + \pgfprocesssplitsubpath{\pgfprocessresultpathsuffix}% + % + % Step 2: extract + % + \expandafter\pgf@parse@end\pgfprocessresultsubpathsuffix\pgf@stop\pgf@stop\pgf@stop% + % + % Step 3: prep + % + \pgf@prep@end% + % + % Step 4: shorten + % + \ifdim\pgf@path@shortening@distance=0pt\else\pgf@do@shorten@end\fi% + \expandafter\expandafter\expandafter\def% + \expandafter\expandafter\expandafter\pgf@arrowpath% + \expandafter\expandafter\expandafter{\expandafter\pgfprocessresultpathprefix\pgfprocessresultpathsuffix}% + \pgfsyssoftpath@setcurrentpath\pgf@arrowpath% + \fi% + \fi% +} + +\def\pgf@parse@end#1#2#3#4#5#6{% + \ifx#4\pgf@stop% Only a moveto! -> do nothing! + \def\pgfpointlastonpath{\pgfqpoint{#2}{#3}}% + \let\pgf@next\relax% + \let\pgf@do@shorten@end\relax% + \let\pgf@do@draw@end\pgf@do@draw@straightend% + \let\pgf@prep@end\pgf@prep@movetoend% + \else\ifx#4\pgfsyssoftpath@curvetosupportatoken% A curve -> this will get complicated... + \def\pgfsubpathfourthlasttoken{#1}% + \def\pgfpointfourthlastonpath{\pgfqpoint{#2}{#3}}% + \def\pgfpointthirdlastonpath{\pgfqpoint{#5}{#6}}% + \ifpgf@precise@shortening% + \let\pgf@do@shorten@end\pgf@do@shorten@curvedend% + \let\pgf@do@draw@end\pgf@do@draw@curvedend% + \let\pgf@prep@end\pgf@prep@curveend% + \else% + \def\pgfsubpathstart{\noexpand#1{#2}{#3}\noexpand#4{#5}{#6}}% + \let\pgf@do@shorten@end\pgf@do@shorten@straightend% + \let\pgf@do@draw@end\pgf@do@draw@straightend% + \let\pgf@prep@end\pgf@prep@straightend% + \fi% + \let\pgf@next\pgf@parse@end@curve@cont% + \else% A straight line -> great! + \def\pgfsubpathstart{\noexpand#1{#2}{#3}\noexpand#4}% + \def\pgfpointsecondlastonpath{\pgfqpoint{#2}{#3}}% + \def\pgfpointlastonpath{\pgfqpoint{#5}{#6}}% + \let\pgfpointfourthlastonpath\relax% + \let\pgfpointthirdlastonpath\relax% + \let\pgf@next\pgf@parse@end@gobble@three% + \let\pgf@do@shorten@end\pgf@do@shorten@straightend% + \let\pgf@do@draw@end\pgf@do@draw@straightend% + \let\pgf@prep@end\pgf@prep@straightend% + \fi\fi% + \pgf@next% Needed for reading rest of path... +} + +\def\pgf@parse@end@gobble@three#1#2#3{}% +\def\pgf@parse@end@curve@cont#1#2#3#4#5#6#7#8#9{% + \def\pgfpointsecondlastonpath{\pgfqpoint{#2}{#3}}% + \def\pgfpointlastonpath{\pgfqpoint{#5}{#6}}% + \ifpgf@precise@shortening% + \else% + \expandafter\def\expandafter\pgfsubpathstart\expandafter{\pgfsubpathstart\noexpand#1{#2}{#3}\noexpand#4}% + \fi% +} + +% +% Preps +% +\def\pgf@prep@movetoend{% + \pgf@process{\pgfpointlastonpath}% + \pgf@xb\pgf@x + \pgf@yb\pgf@y + \pgf@xc\pgf@x + \pgf@yc\pgf@y +} +\def\pgf@prep@straightend{% + \let\pgf@ref\pgfpointsecondlastonpath + \ifx\pgfpointlastonpath\pgfpointsecondlastonpath% degenerate! + \ifx\pgfpointthirdlastonpath\relax% cannot help it: really a zero-length path + \else% + \ifx\pgfpointlastonpath\pgfpointthirdlastonpath% double degenerate! + \let\pgf@ref\pgfpointfourthlastonpath% Use third point for reference. + \else + \let\pgf@ref\pgfpointthirdlastonpath% Use third point for reference. + \fi% + \fi% + \fi% + \pgfpointlineatdistance{\pgf@path@shortening@distance}{\pgfpointlastonpath}{\pgf@ref}% + \pgf@xa\pgf@x% + \pgf@ya\pgf@y% +} + + +% +% Line shortening for straight lines: +% +\def\pgf@do@shorten@straightend{% + \edef\pgfprocessresultsubpathsuffix{\pgfsubpathstart{\the\pgf@xa}{\the\pgf@ya}}% + \expandafter\expandafter\expandafter\def% + \expandafter\expandafter\expandafter\pgfprocessresultpathsuffix% + \expandafter\expandafter\expandafter{\expandafter\pgfprocessresultsubpathprefix\pgfprocessresultsubpathsuffix}% +} + + +% +% Draw an end arrow by calling an appropriate subfunction, if necessary +% + +\def\pgf@add@arrow@at@end{% + \ifx\pgf@arrowpath\pgfutil@empty\else% + \ifx\pgf@end@tip@sequence\pgfutil@empty\else% + \pgf@do@draw@end% + \fi% + \fi% +} + +% +% Draw an end arrow at the end of a straight line +% +\def\pgf@do@draw@straightend{% + {% + \pgftransformreset% + \pgftransformarrow{\pgfqpoint{\pgf@xc}{\pgf@yc}}{\pgfqpoint{\pgf@xb}{\pgf@yb}}% + \pgf@arrow@draw@arrow\pgf@end@tip@sequence\pgf@arrow@tip@total@length% + }% +} + + + + + +% +% +% Handling the start of a path +% +% +% The "handling" is similar to the case for the start of the path. We +% may be able to skip the splitting if that was done already for the +% end. Otherwise, things are basically the same. +% + +% Prepare the start of the path: Test whether anything must be done +% (step 0) and, if so, split the path (step 1) if necessary, extract +% the interesting points from the path (step 2), prepare computations +% (step 3) needed for both shortening and tip adding, shorten the path +% (step 4), and add the arrow tip (step 5 in macro +% \pgf@add@arrow@at@start, which is called later). + +\def\pgf@prepare@start@of@path{% + % + % Step 0 start: + % + % Do we need to worry about the start? + % + \ifx\pgf@arrowpath\pgfutil@empty\else% + \pgf@worryfalse% + \ifx\pgf@start@tip@sequence\pgfutil@empty\else\pgf@worrytrue\fi% Yes, worry if we have to draw an arrow + \pgf@precise@shorteningfalse% + \pgf@arrow@compute@shortening\pgf@start@tip@sequence% + \advance\pgf@xa by\pgf@shorten@start@additional% + \advance\pgf@xb by\pgf@shorten@start@additional% + \ifdim\pgf@xa=0pt\relax\else\pgf@worrytrue\fi% Also, worry if shortening is requested + \edef\pgf@path@shortening@distance{\the\pgf@xa}% + \edef\pgf@arrow@tip@total@length{\the\pgf@xb}% + % + % Step 0 done. + % + \ifpgf@worry% + % Ok, need to "worry" about the start, either because we need to + % shorten it or to draw an arrow head. + % + % Step 1: Split + % + \ifx\pgfprocessresultpathsuffix\relax% + % Ok, still need to compute the split: + \pgfprocesssplitpath{\pgf@arrowpath}% + \fi% + % + % Step 2: extract + % + \expandafter\pgf@parse@start\pgfprocessresultpathsuffix\pgf@stop\pgf@stop\pgf@stop% + % + % Step 3: prep + % + \pgf@prep@start% + % + % Step 4: shorten + % + \ifdim\pgf@path@shortening@distance=0pt\else\pgf@do@shorten@start\fi% + \expandafter\expandafter\expandafter\def% + \expandafter\expandafter\expandafter\pgf@arrowpath% + \expandafter\expandafter\expandafter{\expandafter\pgfprocessresultpathprefix\pgfprocessresultpathsuffix}% + \pgfsyssoftpath@setcurrentpath\pgf@arrowpath% + \fi% + \fi% +} + +\def\pgf@parse@start#1#2#3#4#5#6{% + \def\pgfpointfirstonpath{\pgfqpoint{#2}{#3}}% + \def\pgfpointsecondonpath{\pgfqpoint{#5}{#6}}% + \let\pgfpointthirdonpath\relax% + \let\pgfpointfourthonpath\relax% + \def\pgfsubpathfirsttoken{\noexpand#1}% + \def\pgfsubpathsecondtoken{\noexpand#4}% + \ifx#4\pgf@stop% Only a moveto! -> do nothing! + \let\pgf@next\relax% + \let\pgf@do@shorten@start\relax% + \let\pgf@prep@start\pgf@prep@movetostart% + \let\pgf@do@draw@start\pgf@do@draw@straightstart% + \else\ifx#4\pgfsyssoftpath@curvetosupportatoken% A curve -> this will get complicated... + \ifpgf@precise@shortening% + \let\pgf@next\pgf@parse@start@curve@cont% + \let\pgf@do@shorten@start\pgf@do@shorten@curvedstart% + \let\pgf@do@draw@start\pgf@do@draw@curvedstart% + \let\pgf@prep@start\pgf@prep@curvedstart% + \else% can treat the end like a straight line... + \let\pgf@next\pgf@parse@start@curve@cont@straight% + \let\pgf@do@shorten@start\pgf@do@shorten@straightstart% + \let\pgf@do@draw@start\pgf@do@draw@straightstart% + \let\pgf@prep@start\pgf@prep@straightstart% + \fi% + \else% A straight line -> great! + \let\pgf@next\pgf@parse@start@till@stop% + \let\pgf@do@shorten@start\pgf@do@shorten@straightstart% + \let\pgf@do@draw@start\pgf@do@draw@straightstart% + \let\pgf@prep@start\pgf@prep@straightstart% + \fi\fi% + \pgf@next% Needed for reading rest of path... +} + +\def\pgf@parse@start@till@stop#1\pgf@stop\pgf@stop\pgf@stop{\def\pgfsubpathend{#1}}% + +\def\pgf@parse@start@curve@cont#1#2#3#4#5#6#7\pgf@stop\pgf@stop\pgf@stop{% + \def\pgfpointthirdonpath{\pgfqpoint{#2}{#3}}% + \def\pgfpointfourthonpath{\pgfqpoint{#5}{#6}}% + \def\pgfsubpathend{#7}% +} + +\def\pgf@parse@start@curve@cont@straight#1#2#3#4#5#6#7\pgf@stop\pgf@stop\pgf@stop{% + \def\pgfpointthirdonpath{\pgfqpoint{#2}{#3}}% + \def\pgfpointfourthonpath{\pgfqpoint{#5}{#6}}% + \def\pgfsubpathend{#1{#2}{#3}#4{#5}{#6}#7}% +} + +% +% Preps +% +\def\pgf@prep@movetostart{% + \pgf@process{\pgfpointfirstonpath}% + \pgf@xb\pgf@x + \pgf@yb\pgf@y + \pgf@xc\pgf@x + \pgf@yc\pgf@y +} +\def\pgf@prep@straightstart{% + \let\pgf@ref\pgfpointsecondonpath + \ifx\pgfpointfirstonpath\pgfpointsecondonpath% degenerate! + \ifx\pgfpointthirdonpath\relax% cannot help it: really a zero-length path + \else% + \ifx\pgfpointfirstonpath\pgfpointthirdonpath% double degenerate! + \let\pgf@ref\pgfpointfourthonpath% Use third point for reference. + \else + \let\pgf@ref\pgfpointthirdonpath% Use third point for reference. + \fi% + \fi% + \fi% + \pgfpointlineatdistance{\pgf@path@shortening@distance}{\pgfpointfirstonpath}{\pgf@ref}% + \pgf@xa\pgf@x% + \pgf@ya\pgf@y% +} + +% +% Line shortening for straight lines: +% +\def\pgf@do@shorten@straightstart{% + \edef\pgfprocessresultpathsuffix{\pgfsubpathfirsttoken{\the\pgf@xa}{\the\pgf@ya}\pgfsubpathsecondtoken{\the\pgf@xc}{\the\pgf@yc}}% + \expandafter\expandafter\expandafter\def% + \expandafter\expandafter\expandafter\pgfprocessresultpathsuffix% + \expandafter\expandafter\expandafter{\expandafter\pgfprocessresultpathsuffix\pgfsubpathend}% +} + + +% +% Draw a start arrow by calling an appropriate subfunction, if necessary +% + +\def\pgf@add@arrow@at@start{% + \ifx\pgf@arrowpath\pgfutil@empty\else% + \ifx\pgf@start@tip@sequence\pgfutil@empty\else% + \pgf@do@draw@start% + \fi% + \fi% +} + +% +% Draw an start arrow at the start of a straight line +% +\def\pgf@do@draw@straightstart{% + {% + \pgftransformreset% + \pgftransformarrow{\pgfqpoint{\pgf@xc}{\pgf@yc}}{\pgfqpoint{\pgf@xb}{\pgf@yb}}% + \pgf@arrow@draw@arrow\pgf@start@tip@sequence\pgf@arrow@tip@total@length% + }% +} + + + +\let\pgf@shorten@end=\pgfutil@empty +\let\pgf@shorten@start=\pgfutil@empty + + +\endinput% diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcorepatterns.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcorepatterns.code.tex new file mode 100644 index 0000000000..c2e438dfc4 --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcorepatterns.code.tex @@ -0,0 +1,301 @@ +% Copyright 2019 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{pgfcorepatterns.code.tex} + +% Creates a new uncolored pattern +% +% [#1] = optional list of variables. +% #2 = pattern name +% #3 = lower left of bounding box +% #4 = upper right of bounding box +% #5 = step vector +% #6 = pattern code +% +% Description: +% +% Declares a new uncolored pattern. An uncolored pattern is a pattern +% that has no inherent color. When the pattern is used, a color for +% the pattern must be supplied. +% +% See the pdf-manual for more details on uncolored patterns. +% +% Specifying a variable list makes the pattern ``mutable''. +% +% The bounding box must be a bounding box of the pattern cell. +% +% The step vector must provide the x- and y-step by which the cells +% are spaced. +% +% The pattern code should be pgf code that can be protocolled. +% +% The transformation matrix will be reset prior to invoking the +% pattern code. +% +% Example: +% +% \pgfdeclarepatternformonly{stars}{\pgfpointorigin}{\pgfpoint{1cm}{1cm}} +% {\pgfpoint{1cm}{1cm}}{ +% \pgftransformshift{\pgfpoint{.5cm}{.5cm}} +% \pgfpathmoveto{\pgfpointpolar{0}{4mm}} +% \pgfpathlineto{\pgfpointpolar{144}{4mm}} +% \pgfpathlineto{\pgfpointpolar{288}{4mm}} +% \pgfpathlineto{\pgfpointpolar{72}{4mm}} +% \pgfpathlineto{\pgfpointpolar{216}{4mm}} +% \pgfpathclose% +% \pgfusepath{stroke} +% } +% +\def\pgfdeclarepatternformonly{% + \def\pgf@pattern@type{formonly}% + \pgfutil@ifnextchar[{\pgf@declarepattern@checkarg}{\pgf@declarepattern@checkarg[]}% +} + + +% Creates a new colored pattern +% +% [#1] = optional list of variables. +% #2 = pattern name +% #3 = lower left of bounding box +% #4 = upper right of bounding box +% #5 = step vector +% #6 = pattern code +% +% Description: +% +% Declares a new colored pattern. Such patterns have a one or more +% fixed inherent colors. See the pdf-manual for more details on +% uncolored patterns. +% +% The parameters have the same effect as for uncolored patterns. +% +% Example: +% +% \pgfdeclarepatterninherentlycolored{red stars}{\pgfpointorigin}{\pgfpoint{1cm}{1cm}} +% {\pgfpoint{1cm}{1cm}}{ +% \pgfsetfillcolor{red} +% \pgfsetstrokecolor{black} +% \pgftransformshift{\pgfpoint{.5cm}{.5cm}} +% \pgfpathmoveto{\pgfpointpolar{0}{4mm}} +% \pgfpathlineto{\pgfpointpolar{144}{4mm}} +% \pgfpathlineto{\pgfpointpolar{288}{4mm}} +% \pgfpathlineto{\pgfpointpolar{72}{4mm}} +% \pgfpathlineto{\pgfpointpolar{216}{4mm}} +% \pgfpathclose% +% \pgfusepath{stroke,fill} +% } +% +\def\pgfdeclarepatterninherentlycolored{% + \def\pgf@pattern@type{inherentlycolored}% + \pgfutil@ifnextchar[{\pgf@declarepattern@checkarg}{\pgf@declarepattern@checkarg[]}% +} + + + + + +\def\pgf@declarepattern@checkarg[#1]{% + \def\pgf@pattern@tempvars{#1}% + \ifx\pgf@pattern@tempvars\pgfutil@empty% + \expandafter\let\expandafter\pgf@next\csname pgf@declarepattern\pgf@pattern@type\endcsname% + \else% + \expandafter\let\expandafter\pgf@next\csname pgf@declarepattern\pgf@pattern@type @mutable\endcsname% + \fi% + \pgf@next} + +\long\def\pgf@declarepatternformonly#1#2#3#4#5{\pgf@declarepattern{#1}{#2}{#3}{#4}{#5}{0}} + +\long\def\pgf@declarepatterninherentlycolored#1#2#3#4#5{\pgf@declarepattern{#1}{#2}{#3}{#4}{#5}{1}} + +\long\def\pgf@declarepatternformonly@mutable#1#2#3#4#5{% + \def\pgf@marshal{\pgf@declarepatternmutable{#1}}% + \expandafter\pgf@marshal\expandafter{\pgf@pattern@tempvars}{#2}{#3}{#4}{#5}{2}% +} + +\long\def\pgf@declarepatterninherentlycolored@mutable#1#2#3#4#5#6{% + \def\pgf@marshal{\pgf@declarepatternmutable{#1}}% + \expandafter\pgf@marshal\expandafter{\pgf@pattern@tempvars}{#2}{#3}{#4}{#5}{3}% +} + +\def\pgfsys@patternmatrix{{1.0}{0.0}{0.0}{1.0}{0.0pt}{0.0pt}} +\def\pgf@declarepattern#1#2#3#4#5#6{% + \pgfutil@ifundefined{pgf@pattern@name@#1}{% + \pgfsysprotocol@getcurrentprotocol\pgf@pattern@temp% + {% + \pgfinterruptpath% + \pgfpicturetrue% + \pgf@relevantforpicturesizefalse% + \pgftransformreset% + \pgfsysprotocol@setcurrentprotocol\pgfutil@empty% + \pgfsysprotocol@bufferedtrue% + \pgfsys@beginscope% + \pgfsetarrows{-}% + #5% + \pgfsys@endscope% + \pgfsysprotocol@getcurrentprotocol\pgf@pattern@code% + \global\let\pgf@pattern@code=\pgf@pattern@code% + \endpgfinterruptpath% + \pgf@process{#2}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgf@process{#3}% + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + \pgf@process{#4}% + \pgf@xc=\pgf@x% + \pgf@yc=\pgf@y% + % Now, build a name for the pattern + \pgfutil@tempcnta=\pgf@pattern@number% + \advance\pgfutil@tempcnta by1\relax% + \xdef\pgf@pattern@number{\the\pgfutil@tempcnta}% + \expandafter\xdef\csname pgf@pattern@name@#1\endcsname{\the\pgfutil@tempcnta}% + \expandafter\gdef\csname pgf@pattern@type@#1\endcsname{#6}% + \xdef\pgf@marshal{\noexpand\pgfsys@declarepattern + {\csname pgf@pattern@name@#1\endcsname}% name + {\the\pgf@xa}{\the\pgf@ya}{\the\pgf@xb}{\the\pgf@yb}% bbox + {\the\pgf@xc}{\the\pgf@yc}% x/y step + \pgfsys@patternmatrix% transformation matrix + {\pgf@pattern@code}{#6}}% + }% + \pgfsysprotocol@setcurrentprotocol\pgf@pattern@temp% + \expandafter\global\expandafter\let\csname pgf@pattern@instantiate@#1\endcsname=\pgf@marshal% + } + {% + \pgferror{Pattern `#1' already defined}% + }% +} + +\def\pgf@pattern@number{0}% + +\def\pgf@declarepatternmutable#1#2#3#4#5#6#7{% + \pgfutil@ifundefined{pgf@pattern@name@#1}{% + \expandafter\gdef\csname pgf@pattern@name@#1\endcsname{#1}% + \expandafter\gdef\csname pgf@pattern@variables@#1\endcsname{#2}% + \expandafter\gdef\csname pgf@pattern@lowerleft@#1\endcsname{#3}% + \expandafter\gdef\csname pgf@pattern@upperright@#1\endcsname{#4}% + \expandafter\gdef\csname pgf@pattern@tilesize@#1\endcsname{#5}% + \expandafter\long\expandafter\gdef\csname pgf@pattern@code@#1\endcsname{#6}% + \expandafter\gdef\csname pgf@pattern@type@#1\endcsname{#7}% + }{\pgferror{The pattern `#1' is already defined}}% +} + +\def\pgf@ifpatternisinherentlycolored#1#2#3{% + \expandafter\ifodd\csname pgf@pattern@type@#1\endcsname\relax#2\else#3\fi% +} + +\def\pgf@ifpatternismutable#1#2#3{% + \expandafter\ifnum\csname pgf@pattern@type@#1\endcsname>1\relax#2\else#3\fi% +} + +\def\pgfpatternreleasename#1{\expandafter\let\csname pgf@pattern@name@#1\endcsname\relax} + + + + + + +% Set an pattern as fill color +% +% #1 = Name of the pattern +% #2 = Color to be used for the pattern. If the pattern is already +% colored, this parameter is ignored. +% +% Description: +% +% Sets the pattern for subsequent filling operations. +% +% Example: +% +% \pgfsetfillpattern{stars}{red} +% +\def\pgfsetfillpattern#1#2{% + \pgfutil@ifundefined{pgf@pattern@name@#1}% + {% + \pgferror{Undefined pattern `#1'}% + }% + {% + \pgf@ifpatternismutable{#1}% + {% + % So, a mutable pattern. Check to see if the pattern + % has been used with the current variable values... + \let\pgf@pattern@tempvars\pgfutil@empty% + \expandafter\expandafter\expandafter\pgf@pattern@check@vars% + \csname pgf@pattern@variables@#1\endcsname,\pgf@stop,% + \edef\pgf@pattern@nametemp{pgf@pattern@#1@\pgf@pattern@tempvars}% + \expandafter\pgfutil@ifundefined\expandafter{\pgf@pattern@nametemp}% + {% + % ...Nope. So declare a new instance of the mutable pattern. + \pgf@ifpatternisinherentlycolored{#1}% + {\let\pgf@set@fillpattern@declare\pgfdeclarepatterninherentlycolored}% + {\let\pgf@set@fillpattern@declare\pgfdeclarepatternformonly}% + \pgf@set@fillpattern@declare% + {\pgf@pattern@nametemp}% + {\csname pgf@pattern@lowerleft@#1\endcsname}% + {\csname pgf@pattern@upperright@#1\endcsname}% + {\csname pgf@pattern@tilesize@#1\endcsname}% + {\csname pgf@pattern@code@#1\endcsname}% + }% + {% + % ...Yep. So do nothing. + }% + \expandafter\pgf@set@fillpattern\expandafter{\pgf@pattern@nametemp}{#2}% + \expandafter\gdef\csname\pgf@pattern@nametemp\endcsname{#1}% + }% + {% + % A non-mutable pattern. + \pgf@set@fillpattern{#1}{#2}% + }% + }% +} + + +\def\pgf@set@fillpattern#1#2{% + \pgfutil@ifundefined{pgf@pattern@name@#1}{% + \pgferror{Undefined pattern `#1'}} + {% + \csname pgf@pattern@instantiate@#1\endcsname% + \expandafter\global\expandafter\let\csname pgf@pattern@instantiate@#1\endcsname=\relax% + \pgf@ifpatternisinherentlycolored{#1}{% + \pgfsys@setpatterncolored{\csname pgf@pattern@name@#1\endcsname}% + }{% + \pgfutil@colorlet{pgf@tempcolor}{#2}% + \pgfutil@ifundefined{applycolormixins}{}{\applycolormixins{pgf@tempcolor}}% + \pgfutil@extractcolorspec{pgf@tempcolor}{\pgf@tempcolor}% + \expandafter\pgfutil@convertcolorspec\pgf@tempcolor{rgb}{\pgf@rgbcolor}% + \expandafter\pgf@set@fill@patternuncolored\pgf@rgbcolor\relax{#1}% + }% + }% +} + +\def\pgf@set@fill@patternuncolored#1,#2,#3\relax#4{% + \pgfsys@setpatternuncolored{\csname pgf@pattern@name@#4\endcsname}{#1}{#2}{#3}% +} + +\def\pgf@pattern@check@vars#1,{% + \ifx#1\pgf@stop% + \let\pgf@next\relax% + \else% + \afterassignment\pgfmath@gobbletilpgfmath@% + \expandafter\let\expandafter\pgf@pattern@char#1#1\pgfmath@% + \ifx\pgf@pattern@char/% + \edef\pgf@pattern@tempvar{(\pgfkeysvalueof{#1})}% + \else% + \expandafter\ifcat\pgf@pattern@char\relax% + \edef\pgf@pattern@tempvar{(\the#1)}% + \else% + \edef\pgf@pattern@tempvar{(#1)}% + \fi% + \fi% + \edef\pgf@pattern@tempvars{\pgf@pattern@tempvars\pgf@pattern@tempvar}% + \let\pgf@next\pgf@pattern@check@vars% + \fi% + \pgf@next% +} + +\endinput diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcorepoints.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcorepoints.code.tex new file mode 100644 index 0000000000..6c28f20b73 --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcorepoints.code.tex @@ -0,0 +1,1212 @@ +% Copyright 2019 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{pgfcorepoints.code.tex} + +\newdimen\pgf@picminx +\newdimen\pgf@picmaxx +\newdimen\pgf@picminy +\newdimen\pgf@picmaxy + +\newdimen\pgf@pathminx +\newdimen\pgf@pathmaxx +\newdimen\pgf@pathminy +\newdimen\pgf@pathmaxy + +\newif\ifpgf@relevantforpicturesize + +\def\pgf@process#1{{#1\global\pgf@x=\pgf@x\global\pgf@y=\pgf@y}} + +% Save a point. +% +% #1 = macro for storing point. +% #2 = code for point (should define x and y) +% +% Example: +% +% \pgfextract@process\mypoint{\pgf@x=10pt \pgf@y10pt} +% \pgfextract@process\myarcpoint{\pgfpointpolar{30}{5cm and 2cm}} + +\def\pgfextract@process#1#2{% + \pgf@process{#2}% + \edef#1{\noexpand\global\pgf@x=\the\pgf@x\noexpand\relax\noexpand\global\pgf@y=\the\pgf@y\noexpand\relax}% +} +% This needed until old shapes code changed. +\let\pgfsavepgf@process\pgfextract@process% + + +% Return a point +% +% #1 = x-coordinate of the point +% #2 = y-coordinate of the point +% +% x = #1 +% y = #2 +% +% Example: +% +% \pgfpathmoveto{\pgfpoint{2pt+3cm}{3cm}} + +\def\pgfpoint#1#2{% + \pgfmathsetlength\pgf@x{#1}% + \pgfmathsetlength\pgf@y{#2}\ignorespaces} + + +% Quickly a point +% +% #1 = x-coordinate of the point (no calculations done) +% #2 = y-coordinate of the point (no calculations done) +% +% x = #1 +% y = #2 +% +% Example: +% +% \pgfpathmoveto{\pgfqpoint{2pt}{3cm}} + +\def\pgfqpoint#1#2{\global\pgf@x=#1\relax\global\pgf@y=#2\relax} + + + +% Return the origin. +% +% x = 0 +% y = 0 +% +% Example: +% +% \pgfpathmoveto{\pgfpointorigin} + +\def\pgfpointorigin{\global\pgf@x=0pt \global\pgf@y=\pgf@x\ignorespaces} + + + +% Return a transformed point +% +% #1 = a point +% +% Description: +% +% This command applies pgf's current transformation matrix to the +% given point. Normally, this is done automatically by commands like +% lineto or moveto, but sometimes you may wish to access a transformed +% point yourself. In the below example, this command is used for a low level +% coordinate system shift. +% +% Example: +% +% \begin{pgflowleveltransformshiftscope}{\pgfpointtransformed{\pgfpointorigin}} +% \pgfbox[center,center]{Hi!} +% \end{pgflowleveltransformshiftscope} + +\def\pgfpointtransformed#1{% + \pgf@process{% + #1% + \pgf@pos@transform@glob% + }% +} + + +% Return the difference vector of two points. +% +% #1 = start of vector +% #2 = end of vector +% +% x = x-component of difference +% y = y-component of difference +% +% Example: +% +% \pgfpathmoveto{\pgfpointdiff{\pgfpointxy{1}{1}}{\pgfpointxy{2}{3}}} + +\def\pgfpointdiff#1#2{% + \pgf@process{#1}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgf@process{#2}% + \global\advance\pgf@x by-\pgf@xa\relax% + \global\advance\pgf@y by-\pgf@ya\relax\ignorespaces} + +% Add two vectors. +% +% #1 = first vector +% #2 = second vector +% +% x = x-component of addition +% y = y-component of addition +% +% Example: +% +% \pgfpathmoveto{\pgfpointadd{\pgfpointxy{0}{1}}{\pgfpointxy{2}{3}}} + +\def\pgfpointadd#1#2{% + \pgf@process{#1}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgf@process{#2}% + \global\advance\pgf@x by\pgf@xa% + \global\advance\pgf@y by\pgf@ya} + + + +% Multiply a vector by a factor. +% +% #1 = factor +% #2 = vector +% +% Example: +% +% \pgfpointscale{2}{\pgfpointxy{0}{1}} + +\def\pgfpointscale#1#2{% + \pgf@process{#2}% + \pgfmathparse{#1}% + \global\pgf@x=\pgfmathresult\pgf@x% + \global\pgf@y=\pgfmathresult\pgf@y% +} +% A "quick" variant of \pgfpointscale which doesn't invoke the math parser for '#1'. +% #1 must be a number without units, no registers are accepted. +\def\pgfqpointscale#1#2{% + \pgf@process{#2}% + \global\pgf@x=#1\pgf@x% + \global\pgf@y=#1\pgf@y% +} + + +% The intersection of two lines +% +% #1 = point on first line +% #2 = another point on first line +% #3 = point on second line +% #4 = another point on second line +% +% Returns the intersection of the two lines. If there is no +% intersection or if the points #1 and #2 or the points #3 and #4 are +% identical, the behaviour is not specified. +% +% Example: +% +% \pgfpointintersectionoflines{\pgfpointxy{0}{1}}{\pgfpointxy{1}{0}}{\pgfpointxy{2}{2}}{\pgfpointxy{3}{4}} + +\def\pgfpointintersectionoflines#1#2#3#4{% + {% + % + % Compute orthogonal vector to #1--#2 + % + \pgf@process{#2}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgf@process{#1}% + \advance\pgf@xa by-\pgf@x% + \advance\pgf@ya by-\pgf@y% + \pgf@ya=-\pgf@ya% + % Normalise a bit + \c@pgf@counta=\pgf@xa% + \ifnum\c@pgf@counta<0\relax% + \c@pgf@counta=-\c@pgf@counta\relax% + \fi% + \c@pgf@countb=\pgf@ya% + \ifnum\c@pgf@countb<0\relax% + \c@pgf@countb=-\c@pgf@countb\relax% + \fi% + \advance\c@pgf@counta by\c@pgf@countb\relax% + \divide\c@pgf@counta by 65536\relax% + \ifnum\c@pgf@counta>0\relax% + \divide\pgf@xa by\c@pgf@counta\relax% + \divide\pgf@ya by\c@pgf@counta\relax% + \fi% + % + % Compute projection + % + \pgf@xc=\pgf@sys@tonumber{\pgf@ya}\pgf@x% + \advance\pgf@xc by\pgf@sys@tonumber{\pgf@xa}\pgf@y% + % + % The orthogonal vector is (\pgf@ya,\pgf@xa) + % + % + % Compute orthogonal vector to #3--#4 + % + \pgf@process{#4}% + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + \pgf@process{#3}% + \advance\pgf@xb by-\pgf@x% + \advance\pgf@yb by-\pgf@y% + \pgf@yb=-\pgf@yb% + % Normalise a bit + \c@pgf@counta=\pgf@xb% + \ifnum\c@pgf@counta<0\relax% + \c@pgf@counta=-\c@pgf@counta\relax% + \fi% + \c@pgf@countb=\pgf@yb% + \ifnum\c@pgf@countb<0\relax% + \c@pgf@countb=-\c@pgf@countb\relax% + \fi% + \advance\c@pgf@counta by\c@pgf@countb\relax% + \divide\c@pgf@counta by 65536\relax% + \ifnum\c@pgf@counta>0\relax% + \divide\pgf@xb by\c@pgf@counta\relax% + \divide\pgf@yb by\c@pgf@counta\relax% + \fi% + % + % Compute projection + % + \pgf@yc=\pgf@sys@tonumber{\pgf@yb}\pgf@x% + \advance\pgf@yc by\pgf@sys@tonumber{\pgf@xb}\pgf@y% + % + % The orthogonal vector is (\pgf@yb,\pgf@xb) + % + % Setup transformation matrix (this is just to use the matrix + % inversion) + % + \pgfsettransform{{\pgf@sys@tonumber\pgf@ya}{\pgf@sys@tonumber\pgf@yb}{\pgf@sys@tonumber\pgf@xa}{\pgf@sys@tonumber\pgf@xb}{0pt}{0pt}}% + \pgftransforminvert% + \pgf@process{\pgfpointtransformed{\pgfpoint{\pgf@xc}{\pgf@yc}}}% + }% +} + + +% The intersection of two circles +% +% #1 = center of first circle +% #2 = center of second circle +% #3 = radius of first circle +% #4 = radius of second circle +% #5 = solution number +% +% Returns the intersection of the two circles. If #5 is to "1", the +% first intersection is returned, otherwise the second. If the circles +% do not intersect, an error may occur. +% +% Example: +% +% \pgfpointintersectionofcircles{\pgfpointxy{0}{1}}{\pgfpointxy{1}{0}}{1cm}{1cm}{1} + +\def\pgfpointintersectionofcircles#1#2#3#4#5{% + {% + % Store first point in (xa,ya) and radius in xc. + \pgf@process{#1}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgfmathsetlength{\pgf@xc}{#3}% + % Store second point in (xb,yb) and radius in yc. + \pgf@process{#2}% + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + \pgfmathsetlength{\pgf@yc}{#4}% + % + % Ok, now make numbers smaller, in case they are too large + % + \c@pgf@counta=1\relax% + \loop% + \pgf@scale@downfalse% + \ifdim\pgf@xc>50pt\relax% + \pgf@scale@downtrue% + \fi% + \ifdim\pgf@yc>50pt\relax% + \pgf@scale@downtrue% + \fi% + \ifpgf@scale@down% + \multiply\c@pgf@counta by2\relax% + \divide\pgf@xa by2\relax% + \divide\pgf@ya by2\relax% + \divide\pgf@xb by2\relax% + \divide\pgf@yb by2\relax% + \divide\pgf@xc by2\relax% + \divide\pgf@yc by2\relax% + \repeat% + % The following code is taken from the Dr. Math internet forum: + % + % Let the centers be: (a,b), (c,d) + % Let the radii be: r, s + % + % e = c - a [difference in x coordinates] + % f = d - b [difference in y coordinates] + % p = sqrt(e^2 + f^2) [distance between centers] + % k = (p^2 + r^2 - s^2)/(2p) [distance from center 1 to line + % joining points of intersection] + % x = a + ek/p + (f/p)sqrt(r^2 - k^2) + % y = b + fk/p - (e/p)sqrt(r^2 - k^2) + % OR + % x = a + ek/p - (f/p)sqrt(r^2 - k^2) + % y = b + fk/p + (e/p)sqrt(r^2 - k^2) + % + % Since we are running low on registers, use + % \dimen0 for e + % \dimen1 for f + % \dimen2 for p + % \dimen3 for p^2 + % \dimen4 for k + % \dimen5 for 1/p + % \dimen6 for sqrt(r^2 - k^2) + % \dimen7 for k^2 + % \dimen8 for k/p + % \dimen9 for sqrt(r^2 - k^2)/p + % Also note that: + % \pgf@xa for a + % \pgf@ya for b + % \pgf@xb for c + % \pgf@yb for d + % \pgf@xc for r + % \pgf@yc for s + % + % Now: + % e = c - a + \dimen0=\pgf@xb% + \advance\dimen0 by-\pgf@xa% + % f = d - b + \dimen1=\pgf@yb% + \advance\dimen1 by-\pgf@ya% + % p^2 = e^2 + f^2 + \pgf@x=\dimen0\relax% + \pgf@x=\pgf@sys@tonumber{\pgf@x}\pgf@x% + \dimen3=\pgf@x% + \pgf@x=\dimen1\relax% + \advance\dimen3 by\pgf@sys@tonumber{\pgf@x}\pgf@x% + % p = sqrt(p^2) + \pgfmathparse{sqrt(\the\dimen3)}% + \dimen2=\pgfmathresult pt% + % 1/p = 1/p + \pgfmathreciprocal@{\pgfmathresult}% + \dimen5=\pgfmathresult pt% + % k = (p^2 + r^2 - s^2)/(2p) + \dimen4=\dimen3\relax% + \pgf@x=\pgf@xc% + \advance\dimen4 by\pgf@sys@tonumber{\pgf@x}\pgf@x\relax% + \pgf@x=\pgf@yc% + \advance\dimen4 by-\pgf@sys@tonumber{\pgf@x}\pgf@x\relax% + \dimen4=.5\dimen4% + \dimen4=\pgf@sys@tonumber{\dimen5}\dimen4% + % dimen7 is k^2 + \dimen7=\pgf@sys@tonumber{\dimen4}\dimen4\relax% + % dimen6 is sqrt(r^2 - k^2) + \pgfmathparse{sqrt(\pgf@sys@tonumber{\pgf@xc}\pgf@xc-\the\dimen7)}% + \dimen6=\pgfmathresult pt% + % dimen8 is k/p + \dimen8=\pgf@sys@tonumber{\dimen4}\dimen5\relax% + % dimen9 is sqrt(r^2 - k^2)/p + \dimen9=\pgf@sys@tonumber{\dimen6}\dimen5\relax% + \ifnum#5=1\relax% + % x = a + ek/p + (f/p)sqrt(r^2 - k^2) + \pgf@x=\pgf@xa% + \advance\pgf@x by\pgf@sys@tonumber{\dimen0}\dimen8\relax% + \advance\pgf@x by\pgf@sys@tonumber{\dimen1}\dimen9\relax% + % y = b + fk/p - (e/p)sqrt(r^2 - k^2) + \pgf@y=\pgf@ya% + \advance\pgf@y by\pgf@sys@tonumber{\dimen1}\dimen8\relax% + %temp + \pgf@xb=\pgf@sys@tonumber{\dimen0}\dimen9% + \pgf@xb=-\pgf@xb% + \advance\pgf@y by\pgf@xb\relax% + \else% + % x = a + ek/p - (f/p)sqrt(r^2 - k^2) + \pgf@x=\pgf@xa% + \advance\pgf@x by\pgf@sys@tonumber{\dimen0}\dimen8\relax% + %temp + \pgf@xb=\pgf@sys@tonumber{\dimen1}\dimen9% + \pgf@xb=-\pgf@xb% + \advance\pgf@x by\pgf@xb\relax% + % y = b + fk/p + (e/p)sqrt(r^2 - k^2) + \pgf@y=\pgf@ya% + \advance\pgf@y by\pgf@sys@tonumber{\dimen1}\dimen8\relax% + \advance\pgf@y by\pgf@sys@tonumber{\dimen0}\dimen9\relax% + \fi% + \pgf@x=\c@pgf@counta\pgf@x% + \pgf@y=\c@pgf@counta\pgf@y% + \pgf@process{}% get results outside + }% +} +\newif\ifpgf@scale@down + + +% Returns point on a line from #2 to #3 at time #1. +% +% #1 = a time, where 0 is the start and 1 is the end +% #2 = start point +% #3 = end point +% +% x = x-component of #1*start + (1-#1)*end +% y = y-component of #1*start + (1-#1)*end +% xa/ya = #1*start + (1-#1)*end +% xb/yb = start point +% xc/yc = end point +% +% Example: +% +% % Middle of (1,1) and (2,3) +% \pgfpathmoveto{\pgfpointlineattime{0.5}{\pgfpointxy{0}{1}}{\pgfpointxy{2}{3}}} + +\def\pgfpointlineattime#1#2#3{% + \pgf@process{#3}% + \pgf@xa\pgf@x% + \pgf@ya\pgf@y% + \pgf@xc\pgf@x% + \pgf@yc\pgf@y% + \pgf@process{#2}% + \pgf@xb\pgf@x% + \pgf@yb\pgf@y% + \pgfmathsetmacro\pgf@temp{#1}% + \advance\pgf@xa by-\pgf@x% + \advance\pgf@ya by-\pgf@y% + \global\advance\pgf@x by\pgf@temp\pgf@xa% + \global\advance\pgf@y by\pgf@temp\pgf@ya% +} + + +% Move point #2 #1 many units in the direction of #3. +% +% #1 = a distance +% #2 = start point +% #3 = end point +% +% Description: +% +% Computes +% +% x/y = start + #1*(normalise(end-start)) +% +% and additionally +% +% xa/ya = #1*(normalise(end-start)) +% xb/yb = start +% xc/yc = end +% +% Example: +% +% \pgfpathmoveto{\pgfpointlineatdistance{2pt}{\pgfpointxy{0}{1}}{\pgfpointxy{2}{3}}} +% \pgfpathlineto{\pgfpointlineatdistance{3pt}{\pgfpointxy{2}{3}}{\pgfpointxy{0}{1}}} + +\def\pgfpointlineatdistance#1#2#3{% + \pgfmathsetlength\pgf@xa{#1}% + \pgf@process{#2}% + \pgf@xb\pgf@x% xb/yb = start point + \pgf@yb\pgf@y% + \pgf@process{#3}% + \pgf@xc\pgf@x% + \pgf@yc\pgf@y% + \global\advance\pgf@x by-\pgf@xb\relax% + \global\advance\pgf@y by-\pgf@yb\relax% + \pgf@process{\pgfpointnormalised{}}% x/y = normalised vector + \pgf@ya=\pgf@xa\relax% + \pgf@xa=\pgf@sys@tonumber{\pgf@x}\pgf@xa% + \pgf@ya=\pgf@sys@tonumber{\pgf@y}\pgf@ya% + \global\pgf@x=\pgf@xb\relax% + \global\pgf@y=\pgf@yb\relax% + \global\advance\pgf@x by\pgf@xa\relax% + \global\advance\pgf@y by\pgf@ya\relax% +} + + +% Returns point on a curve from #2 to #5 with controls #3 and #4 at time #1. +% +% #1 = a time +% #2 = start point +% #3 = first control point +% #4 = second control point +% #5 = end point +% +% x = x-component of place on the curve at time t +% y = y-component of place on the curve at time t +% +% Additionally, (\pgf@xa,\pgf@ya) and (\pgf@xb,\pgf@yb) will be on a +% tangent to the point on the curve (this can be useful for computing +% a label rotation). (\pgf@xc,\pgf@yc) will be equal to the end +% point. \pgf@time@s will equal the value of #1 and \pgf@time@t will +% equal 1-#1. +% +% Example: +% +% % Middle of (1,1) and (2,3) +% \pgfpathmoveto{\pgfpointcurveattime{0.5}{\pgfpointxy{0}{1}}{\pgfpointxy{1}{1}}{\pgfpointxy{1}{1}}{\pgfpointxy{2}{3}}} + +\def\pgfpointcurveattime#1#2#3#4#5{% + \pgfmathparse{#1}% + \let\pgf@time@s=\pgfmathresult% + \global\pgf@x=\pgfmathresult pt% + \global\pgf@x=-\pgf@x% + \advance\pgf@x by 1pt% + \edef\pgf@time@t{\pgf@sys@tonumber{\pgf@x}}% + \pgf@process{#5}% + \pgf@xc=\pgf@x% + \pgf@yc=\pgf@y% + \pgf@process{#4}% + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + \pgf@process{#3}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgf@process{#2}% + % First iteration: + \global\pgf@x=\pgf@time@t\pgf@x\global\advance\pgf@x by\pgf@time@s\pgf@xa% + \global\pgf@y=\pgf@time@t\pgf@y\global\advance\pgf@y by\pgf@time@s\pgf@ya% + \pgf@xa=\pgf@time@t\pgf@xa\advance\pgf@xa by\pgf@time@s\pgf@xb% + \pgf@ya=\pgf@time@t\pgf@ya\advance\pgf@ya by\pgf@time@s\pgf@yb% + \pgf@xb=\pgf@time@t\pgf@xb\advance\pgf@xb by\pgf@time@s\pgf@xc% + \pgf@yb=\pgf@time@t\pgf@yb\advance\pgf@yb by\pgf@time@s\pgf@yc% + % Second iteration: + \global\pgf@x=\pgf@time@t\pgf@x\global\advance\pgf@x by\pgf@time@s\pgf@xa% + \global\pgf@y=\pgf@time@t\pgf@y\global\advance\pgf@y by\pgf@time@s\pgf@ya% + \pgf@xa=\pgf@time@t\pgf@xa\advance\pgf@xa by\pgf@time@s\pgf@xb% + \pgf@ya=\pgf@time@t\pgf@ya\advance\pgf@ya by\pgf@time@s\pgf@yb% + % Save x/y + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + % Third iteration: + \global\pgf@x=\pgf@time@t\pgf@x\global\advance\pgf@x by\pgf@time@s\pgf@xa% + \global\pgf@y=\pgf@time@t\pgf@y\global\advance\pgf@y by\pgf@time@s\pgf@ya% +} + + + +% Returns point on an arc at a certain "time" +% +% #1 = a time +% #2 = center of a ellipse +% #3 = 0-degree axis of the ellipse +% #4 = 90-degree axis of the ellipse +% #5 = start angle of an arc on the ellipse +% #6 = end angle of an arc on the ellipse +% +% Result: +% +% \pgf@x = x-component of place on the arc at time t +% \pgf@y = y-component of place on the arc at time t +% +% Additionally, (\pgf@xa,\pgf@ya) will be a tangent to the +% point on the arc (this can be useful for computing a label rotation). +% +% Example: +% +% \pgfpointarcaxesattime{0.25}{\pgfpoint{1cm}{1cm}}{\pgfpoint{1cm}{0cm}}{\pgfpoint{0cm}{1cm}}{1cm}{30}{40} + +\def\pgfpointarcaxesattime#1#2#3#4#5#6{% + \pgfmathsetmacro\pgf@angle@start{#5}% + \pgfmathsetmacro\pgf@angle@end{#6}% + \pgfmathparse{#1}% + \global\pgf@x=\pgfmathresult pt% + \global\pgf@x=-\pgf@x% + \advance\pgf@x by 1pt% + \pgfmathsetmacro\pgf@angle@mid{\pgf@angle@end*\pgfmathresult+\pgf@angle@start*\pgf@sys@tonumber{\pgf@x}}% + \pgfmathcos@{\pgf@angle@mid}% + \let\pgf@angle@cos\pgfmathresult% + \pgfmathsin@{\pgf@angle@mid}% + \let\pgf@angle@sin\pgfmathresult% + \pgf@process{#3}% + \edef\pgf@angle@zero@axis{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}} + \pgf@process{#4}% + \edef\pgf@angle@ninety@axis{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}} + % Compute tangent + \pgf@process{\pgfpointadd{\pgfpointscale{\pgf@angle@sin}{\pgf@angle@zero@axis}}% + {\pgfpointscale{-\pgf@angle@cos}{\pgf@angle@ninety@axis}}}% + \ifdim\pgf@angle@start pt>\pgf@angle@end pt% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \else% + \pgf@xa=-\pgf@x% + \pgf@ya=-\pgf@y% + \fi% + % Compute position + \pgf@process{\pgfpointadd{#2}{% + \pgfpointadd{\pgfpointscale{\pgf@angle@cos}{\pgf@angle@zero@axis}}% + {\pgfpointscale{\pgf@angle@sin}{\pgf@angle@ninety@axis}}}}% +} + + + +% Internal registers +\newdimen\pgf@xx +\newdimen\pgf@xy +\newdimen\pgf@yx +\newdimen\pgf@yy +\newdimen\pgf@zx +\newdimen\pgf@zy + + + +% A polar coordinate +% +% #1 = a degree +% #2 = a radius -- either a dimension or two dimensions separated by +% " and ". +% +% x = (first dimension in #2) * cos(#1) +% y = (second dimension in #2) * sin(#2) +% +% Example: +% +% \pgfpathmoveto{\pgfpointpolar{30}{1cm}} +% \pgfpathlineto{\pgfpointpolar{30}{1cm and 2cm}} + +\def\pgfpointpolar#1#2{% + \pgfutil@in@{and }{#2}% + \ifpgfutil@in@% + \pgf@polar@#2\@@% + \else% + \pgf@polar@#2 and #2\@@% + \fi% + \pgfmathparse{#1}% + \let\pgfpoint@angle=\pgfmathresult% + \pgfmathcos@{\pgfpoint@angle}% + \global\pgf@x=\pgfmathresult\pgf@x% + \pgfmathsin@{\pgfpoint@angle}% + \global\pgf@y=\pgfmathresult\pgf@y% +} + +\def\pgf@polar@#1and #2\@@{% + \pgfmathsetlength{\pgf@y}{#2}% + \pgfmathsetlength{\pgf@x}{#1}% +} + +% Quick version of the polar coordinate method + +\def\pgfqpointpolar#1#2{% + \global\pgf@x=#2% + \global\pgf@y=\pgf@x% + \pgfmathcos@{#1}% + \global\pgf@x=\pgfmathresult\pgf@x% + \pgfmathsin@{#1}% + \global\pgf@y=\pgfmathresult\pgf@y\relax% +} + + + + +% A polar coordinate in the xy plane. +% +% #1 = a degree +% #2 = a radius given as a number or two radii +% +% result = (first dim in #2) * x-vector * cos(#1) + +% (second dim in #2) * y-vector * sin(#1) +% +% Example: +% +% \pgfpathmoveto{\pgfpointpolarxy{30}{2}} + +\def\pgfpointpolarxy#1#2{% + \pgfutil@in@{and }{#2}% + \ifpgfutil@in@% + \pgf@polarxy@#2\@@% + \else% + \pgf@polarxy@#2and #2\@@% + \fi% + \pgfmathparse{#1}% + \let\pgfpoint@angle=\pgfmathresult% + \pgfmathcos@{\pgfpoint@angle}% + \pgf@xa=\pgfmathresult\pgf@xa% + \pgfmathsin@{\pgfpoint@angle}% + \pgf@ya=\pgfmathresult\pgf@ya% + \global\pgf@x=\pgf@sys@tonumber{\pgf@xa}\pgf@xx% + \global\advance\pgf@x by \pgf@sys@tonumber{\pgf@ya}\pgf@yx% + \global\pgf@y=\pgf@sys@tonumber{\pgf@xa}\pgf@xy% + \global\advance\pgf@y by \pgf@sys@tonumber{\pgf@ya}\pgf@yy} + +\def\pgf@polarxy@#1and #2\@@{% + \pgfmathsetlength{\pgf@xa}{#1}% + \pgfmathsetlength{\pgf@ya}{#2}% +} + + + +% A cylindrical coordinate. +% +% #1 = a degree +% #2 = a radius given as a number +% #3 = a height given as a number +% +% result = #2*(x-vector * cos(#1) + y-vector * sin(#1)) + #3*z-vector +% +% Example: +% +% \pgfpathmoveto{\pgfpointcylindrical{30}{2}{1}} + +\def\pgfpointcylindrical#1#2#3{% + \pgfpointpolarxy{#1}{#2}% + \pgfmathparse{#3}% + \global\advance\pgf@x by \pgfmathresult\pgf@zx% + \global\advance\pgf@y by \pgfmathresult\pgf@zy} + + +% A spherical coordinate. +% +% #1 = a longitude +% #2 = a latitude +% #3 = a radius +% +% result = #3*(cos(#2)*(x-vector * cos(#1) + y-vector * sin(#1)) + sin(#2)*z-vector) +% +% Example: +% +% \pgfpathmoveto{\pgfpointspherical{30}{30}{2}} + +\def\pgfpointspherical#1#2#3{% + \pgfmathparse{#1}% + \let\pgfpoint@angle=\pgfmathresult% + \pgfmathsin@{\pgfpoint@angle}% + \pgf@xb=\pgfmathresult\pgf@xx% + \pgf@yb=\pgfmathresult\pgf@xy% + \pgfmathcos@{\pgfpoint@angle}% + \advance\pgf@xb by \pgfmathresult\pgf@yx% + \advance\pgf@yb by \pgfmathresult\pgf@yy% + % + \pgfmathparse{#2}% + \let\pgfpoint@angle=\pgfmathresult% + \pgfmathcos@{\pgfpoint@angle}% + \pgf@xc=\pgfmathresult\pgf@xb% + \pgf@yc=\pgfmathresult\pgf@yb% + \pgfmathsin@{\pgfpoint@angle}% + \advance\pgf@xc by \pgfmathresult\pgf@zx% + \advance\pgf@yc by \pgfmathresult\pgf@zy% + \pgfmathparse{#3}% + \global\pgf@x=\pgfmathresult\pgf@xc% + \global\pgf@y=\pgfmathresult\pgf@yc\relax% +} + + +% Store the vector #1 * x-vec + #2 * y-vec +% +% #1 = a factor for the x-vector +% #2 = a factor for the y-vector +% +% x = x-component of result vector +% y = y-component of result vector +% +% Description: +% +% This command can be used to create a new coordinate system +% without using the rotate/translate/scale commands. This +% may be useful, if you do not want arrows and line width to +% be scaled/transformed together with the coordinate system. +% +% Example: +% +% % Create a slanted rectangle +% +% \pgfsetxvec{\pgfpoint{1cm}{1cm}} +% \pgfsetyvec{\pgfpoint{0cm}{1cm}} +% +% \pgfpathmoveto{\pgfpointxy{0}{0}} +% \pgfpathlineto{\pgfpointxy{1}{0}} +% \pgfpathlineto{\pgfpointxy{1}{1}} +% \pgfpathlineto{\pgfpointxy{0}{1}} +% \pgfclosestroke + +\def\pgfpointxy#1#2{% + \pgfmathparse{#1}% + \let\pgftemp@x=\pgfmathresult% + \pgfmathparse{#2}% + \let\pgftemp@y=\pgfmathresult% + \global\pgf@x=\pgftemp@x\pgf@xx% + \global\advance\pgf@x by \pgftemp@y\pgf@yx% + \global\pgf@y=\pgftemp@x\pgf@xy% + \global\advance\pgf@y by \pgftemp@y\pgf@yy} + + +% "Quick" variant for \pgfpointxy. +% +% Only numbers without unit are allowed here. +\def\pgfqpointxy#1#2{% + \global\pgf@x=#1\pgf@xx% + \global\advance\pgf@x by #2\pgf@yx% + \global\pgf@y=#1\pgf@xy% + \global\advance\pgf@y by #2\pgf@yy} + +% Store the vector #1 * x-vec + #2 * y-vec + #3 * z-vec +% +% #1 = a factor for the x-vector +% #2 = a factor for the y-vector +% #3 = a factor for the z-vector +% +% x = x-component of result vector +% y = y-component of result vector +% +% +% Description: +% +% This command allows you to use a 3d coordinate system. +% +% +% Example: +% +% % Draw a cubus +% +% \pgfline{\pgfpointxyz{0}{0}{0}}{\pgfpointxyz{0}{0}{1}} +% \pgfline{\pgfpointxyz{0}{1}{0}}{\pgfpointxyz{0}{1}{1}} +% \pgfline{\pgfpointxyz{1}{0}{0}}{\pgfpointxyz{1}{0}{1}} +% \pgfline{\pgfpointxyz{1}{1}{0}}{\pgfpointxyz{1}{1}{1}} +% \pgfline{\pgfpointxyz{0}{0}{0}}{\pgfpointxyz{0}{1}{0}} +% \pgfline{\pgfpointxyz{0}{0}{1}}{\pgfpointxyz{0}{1}{1}} +% \pgfline{\pgfpointxyz{1}{0}{0}}{\pgfpointxyz{1}{1}{0}} +% \pgfline{\pgfpointxyz{1}{0}{1}}{\pgfpointxyz{1}{1}{1}} +% \pgfline{\pgfpointxyz{0}{0}{0}}{\pgfpointxyz{1}{0}{0}} +% \pgfline{\pgfpointxyz{0}{0}{1}}{\pgfpointxyz{1}{0}{1}} +% \pgfline{\pgfpointxyz{0}{1}{0}}{\pgfpointxyz{1}{1}{0}} +% \pgfline{\pgfpointxyz{0}{1}{1}}{\pgfpointxyz{1}{1}{1}} + +\def\pgfpointxyz#1#2#3{% + \pgfmathparse{#1}% + \let\pgftemp@x=\pgfmathresult% + \pgfmathparse{#2}% + \let\pgftemp@y=\pgfmathresult% + \pgfmathparse{#3}% + \let\pgftemp@z=\pgfmathresult% + \global\pgf@x=\pgftemp@x\pgf@xx% + \global\advance\pgf@x by \pgftemp@y\pgf@yx% + \global\advance\pgf@x by \pgftemp@z\pgf@zx% + \global\pgf@y=\pgftemp@x\pgf@xy% + \global\advance\pgf@y by \pgftemp@y\pgf@yy% + \global\advance\pgf@y by \pgftemp@z\pgf@zy} + +% "Quick" variant for \pgfpointxyz. +% +% Only numbers without unit are allowed. +\def\pgfqpointxyz#1#2#3{% + \global\pgf@x=#1\pgf@xx% + \global\advance\pgf@x by #2\pgf@yx% + \global\advance\pgf@x by #3\pgf@zx% + \global\pgf@y=#1\pgf@xy% + \global\advance\pgf@y by #2\pgf@yy% + \global\advance\pgf@y by #3\pgf@zy} + + + +% Set the x-vector +% +% #1 = a point the is the new x-vector +% +% Example: +% +% \pgfsetxvec{\pgfpoint{1cm}{0cm}} + +\def\pgfsetxvec#1{% + \pgf@process{#1}% + \pgf@xx=\pgf@x% + \pgf@xy=\pgf@y% + \ignorespaces} + + +% Set the y-vector +% +% #1 = a point the is the new y-vector +% +% Example: +% +% \pgfsetyvec{\pgfpoint{0cm}{1cm}} + +\def\pgfsetyvec#1{% + \pgf@process{#1}% + \pgf@yx=\pgf@x% + \pgf@yy=\pgf@y% + \ignorespaces} + + +% Set the z-vector +% +% #1 = a point the is the new z-vector +% +% Example: +% +% \pgfsetzvec{\pgfpoint{-0.385cm}{-0.385cm}} + +\def\pgfsetzvec#1{% + \pgf@process{#1}% + \pgf@zx=\pgf@x% + \pgf@zy=\pgf@y% + \ignorespaces} + + + +% Default values +\pgfsetxvec{\pgfpoint{1cm}{0cm}} +\pgfsetyvec{\pgfpoint{0cm}{1cm}} +\pgfsetzvec{\pgfpoint{-0.385cm}{-0.385cm}} + + + + +% Normalise a point. +% +% #1 = point with coordinates (a,b) +% +% x = a/\sqrt(a*a+b*b) +% y = b/\sqrt(a*a+b*b) +% +% Example: +% +% \pgfpointnormalised{\pgfpointxy{2}{1}} + +\def\pgfpointnormalised#1{% + \pgf@process{#1}% + \pgfmathatantwo{\the\pgf@y}{\the\pgf@x}% + \let\pgf@tmp=\pgfmathresult% + \pgfmathcos@{\pgf@tmp}% + \pgf@x=\pgfmathresult pt\relax% + \pgfmathsin@{\pgf@tmp}% + \pgf@y=\pgfmathresult pt\relax% +} + + + + + +% A point on a rectangle in a certain direction. +% +% #1 = a point pointing in some direction (length should be about 1pt, +% but need not be exact) +% #2 = upper right corner of a rectangle centered at the origin +% +% Returns the intersection of a line starting at the origin going in +% the given direction and the rectangle's border. +% +% Example: +% +% \pgfpointborderrectangle{\pgfpointnormalised{\pgfpointxy{2}{1}} +% {\pgfpoint{1cm}{2cm}} + +\def\pgfpointborderrectangle#1#2{% + \pgf@process{#2}% + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + \pgf@process{#1}% + % Ok, let's find out about the direction: + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \ifnum\pgf@xa<0\relax% move into first quadrant + \global\pgf@x=-\pgf@x% + \fi% + \ifnum\pgf@ya<0\relax% + \global\pgf@y=-\pgf@y% + \fi% + \pgf@xc=.125\pgf@x% + \pgf@yc=.125\pgf@y% + \c@pgf@counta=\pgf@xc% + \c@pgf@countb=\pgf@yc% + \ifnum\c@pgf@countb<\c@pgf@counta% + \ifnum\c@pgf@counta<255\relax% + \global\pgf@y=\pgf@yb\relax% + \global\pgf@x=0pt\relax% + \else% + \pgf@xc=8192pt% + \divide\pgf@xc by\c@pgf@counta% \pgf@xc = 1/\pgf@x + \global\pgf@y=\pgf@sys@tonumber{\pgf@xc}\pgf@y% + \global\pgf@y=\pgf@sys@tonumber{\pgf@xb}\pgf@y% + \ifnum\pgf@y<\pgf@yb% + \global\pgf@x=\pgf@xb% + \else% rats, calculate intersection on upper side + \ifnum\c@pgf@countb<255\relax% + \global\pgf@x=\pgf@xb\relax% + \global\pgf@y=0pt\relax% + \else% + \pgf@yc=8192pt% + \divide\pgf@yc by\c@pgf@countb% \pgf@xc = 1/\pgf@x + \global\pgf@x=\pgf@sys@tonumber{\pgf@yc}\pgf@x% + \global\pgf@x=\pgf@sys@tonumber{\pgf@yb}\pgf@x% + \global\pgf@y=\pgf@yb% + \fi% + \fi% + \fi% + \else% + \ifnum\c@pgf@countb<255\relax% + \global\pgf@x=\pgf@xb\relax% + \global\pgf@y=0pt\relax% + \else% + \pgf@yc=8192pt% + \divide\pgf@yc by\c@pgf@countb% \pgf@xc = 1/\pgf@x + \global\pgf@x=\pgf@sys@tonumber{\pgf@yc}\pgf@x% + \global\pgf@x=\pgf@sys@tonumber{\pgf@yb}\pgf@x% + \ifnum\pgf@x<\pgf@xb% + \global\pgf@y=\pgf@yb% + \else% + \ifnum\c@pgf@counta<255\relax% + \global\pgf@y=\pgf@yb\relax% + \global\pgf@x=0pt\relax% + \else% + \pgf@xc=8192pt% + \divide\pgf@xc by\c@pgf@counta% \pgf@xc = 1/\pgf@x + \global\pgf@y=\pgf@sys@tonumber{\pgf@xc}\pgf@y% + \global\pgf@y=\pgf@sys@tonumber{\pgf@xb}\pgf@y% + \global\pgf@x=\pgf@xb% + \fi% + \fi% + \fi% + \fi% + \ifnum\pgf@xa<0\relax\global\pgf@x=-\pgf@x\fi% + \ifnum\pgf@ya<0\relax\global\pgf@y=-\pgf@y\fi% +} + + + + +% An approximation to a point on an ellipse in a certain +% direction. Will be exact only if the ellipse is a circle. +% +% #1 = a point pointing in some direction +% #2 = upper right corner of a bounding box for the ellipse +% +% Returns the intersection of a line starting at the origin going in +% the given direction and the ellipses border. +% +% Example: +% +% \pgfpointborderellipse{\pgfpointnormalised{\pgfpointxy{2}{1}} +% {\pgfpoint{1cm}{2cm}} + +\def\pgfpointborderellipse#1#2{% + \pgf@process{#2}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \ifdim\pgf@xa=\pgf@ya% circle. that's easy! + \pgf@process{\pgfpointnormalised{#1}}% + \global\pgf@x=\pgf@sys@tonumber{\pgf@xa}\pgf@x% + \global\pgf@y=\pgf@sys@tonumber{\pgf@xa}\pgf@y% + \else% + \ifdim\pgf@xa<\pgf@ya% + % Ok, first, let's compute x/y: + \c@pgf@countb=\pgf@ya% + \divide\c@pgf@countb by65536\relax% + \global\divide\pgf@x by\c@pgf@countb% + \global\divide\pgf@y by\c@pgf@countb% + \pgf@xc=\pgf@x% + \pgf@yc=8192pt% + \global\pgf@y=.125\pgf@y% + \c@pgf@countb=\pgf@y% + \divide\pgf@yc by\c@pgf@countb% + \pgf@process{#1}% + \global\pgf@y=\pgf@sys@tonumber{\pgf@yc}\pgf@y% + \global\pgf@y=\pgf@sys@tonumber{\pgf@xc}\pgf@y% + \pgf@process{\pgfpointnormalised{}}% + \global\pgf@x=\pgf@sys@tonumber{\pgf@xa}\pgf@x% + \global\pgf@y=\pgf@sys@tonumber{\pgf@ya}\pgf@y% + \else% + % Ok, now let's compute y/x: + \c@pgf@countb=\pgf@xa% + \divide\c@pgf@countb by65536\relax% + \global\divide\pgf@x by\c@pgf@countb% + \global\divide\pgf@y by\c@pgf@countb% + \pgf@yc=\pgf@y% + \pgf@xc=8192pt% + \global\pgf@x=.125\pgf@x% + \c@pgf@countb=\pgf@x% + \divide\pgf@xc by\c@pgf@countb% + \pgf@process{#1}% + \global\pgf@x=\pgf@sys@tonumber{\pgf@yc}\pgf@x% + \global\pgf@x=\pgf@sys@tonumber{\pgf@xc}\pgf@x% + \pgf@process{\pgfpointnormalised{}}% + \global\pgf@x=\pgf@sys@tonumber{\pgf@xa}\pgf@x% + \global\pgf@y=\pgf@sys@tonumber{\pgf@ya}\pgf@y% + \fi% + \fi% +} + + + + + +% Extract the x-coordinate of a point to a dimensions +% +% #1 = a TeX dimension +% #2 = a point +% +% Example: +% +% \newdimen\mydim +% \pgfextractx{\mydim}{\pgfpoint{2cm}{4pt}} +% % \mydim is now 2cm + +\def\pgfextractx#1#2{% + \pgf@process{#2}% + #1=\pgf@x\relax} + + +% Extract the y-coordinate of a point to a dimensions +% +% #1 = a TeX dimension +% #2 = a point +% +% Example: +% +% \newdimen\mydim +% \pgfextracty{\mydim}{\pgfpoint{2cm}{4pt}} +% % \mydim is now 4pt + +\def\pgfextracty#1#2{% + \pgf@process{#2}% + #1=\pgf@y\relax} + + +% Stores the most recently used (x,y) coordinates into two macros, #1 and #2. +\def\pgfgetlastxy#1#2{% + \edef#1{\the\pgf@x}% + \edef#2{\the\pgf@y}% +}% + + +\def\pgf@def#1#2#3{\expandafter\def\csname pgf@#1#2\endcsname{#3}} +\pgf@def{cosfrac}{0}{1} +\pgf@def{cosfrac}{1}{0.99995} \pgf@def{cosfrac}{2}{0.9998} +\pgf@def{cosfrac}{3}{0.99955} \pgf@def{cosfrac}{4}{0.999201} +\pgf@def{cosfrac}{5}{0.998752} \pgf@def{cosfrac}{6}{0.998205} +\pgf@def{cosfrac}{7}{0.997559} \pgf@def{cosfrac}{8}{0.996815} +\pgf@def{cosfrac}{9}{0.995974} \pgf@def{cosfrac}{10}{0.995037} +\pgf@def{cosfrac}{11}{0.994004} \pgf@def{cosfrac}{12}{0.992877} +\pgf@def{cosfrac}{13}{0.991656} \pgf@def{cosfrac}{14}{0.990342} +\pgf@def{cosfrac}{15}{0.988936} \pgf@def{cosfrac}{16}{0.987441} +\pgf@def{cosfrac}{17}{0.985856} \pgf@def{cosfrac}{18}{0.984183} +\pgf@def{cosfrac}{19}{0.982424} \pgf@def{cosfrac}{20}{0.980581} +\pgf@def{cosfrac}{21}{0.978653} \pgf@def{cosfrac}{22}{0.976644} +\pgf@def{cosfrac}{23}{0.974555} \pgf@def{cosfrac}{24}{0.972387} +\pgf@def{cosfrac}{25}{0.970143} \pgf@def{cosfrac}{26}{0.967823} +\pgf@def{cosfrac}{27}{0.965429} \pgf@def{cosfrac}{28}{0.962964} +\pgf@def{cosfrac}{29}{0.960429} \pgf@def{cosfrac}{30}{0.957826} +\pgf@def{cosfrac}{31}{0.955157} \pgf@def{cosfrac}{32}{0.952424} +\pgf@def{cosfrac}{33}{0.949629} \pgf@def{cosfrac}{34}{0.946773} +\pgf@def{cosfrac}{35}{0.943858} \pgf@def{cosfrac}{36}{0.940887} +\pgf@def{cosfrac}{37}{0.937862} \pgf@def{cosfrac}{38}{0.934784} +\pgf@def{cosfrac}{39}{0.931655} \pgf@def{cosfrac}{40}{0.928477} +\pgf@def{cosfrac}{41}{0.925252} \pgf@def{cosfrac}{42}{0.921982} +\pgf@def{cosfrac}{43}{0.918669} \pgf@def{cosfrac}{44}{0.915315} +\pgf@def{cosfrac}{45}{0.911922} \pgf@def{cosfrac}{46}{0.90849} +\pgf@def{cosfrac}{47}{0.905024} \pgf@def{cosfrac}{48}{0.901523} +\pgf@def{cosfrac}{49}{0.89799} \pgf@def{cosfrac}{50}{0.894427} +\pgf@def{cosfrac}{51}{0.890835} \pgf@def{cosfrac}{52}{0.887217} +\pgf@def{cosfrac}{53}{0.883573} \pgf@def{cosfrac}{54}{0.879905} +\pgf@def{cosfrac}{55}{0.876216} \pgf@def{cosfrac}{56}{0.872506} +\pgf@def{cosfrac}{57}{0.868777} \pgf@def{cosfrac}{58}{0.865031} +\pgf@def{cosfrac}{59}{0.861269} \pgf@def{cosfrac}{60}{0.857493} +\pgf@def{cosfrac}{61}{0.853704} \pgf@def{cosfrac}{62}{0.849903} +\pgf@def{cosfrac}{63}{0.846092} \pgf@def{cosfrac}{64}{0.842271} +\pgf@def{cosfrac}{65}{0.838444} \pgf@def{cosfrac}{66}{0.834609} +\pgf@def{cosfrac}{67}{0.83077} \pgf@def{cosfrac}{68}{0.826927} +\pgf@def{cosfrac}{69}{0.82308} \pgf@def{cosfrac}{70}{0.819232} +\pgf@def{cosfrac}{71}{0.815383} \pgf@def{cosfrac}{72}{0.811534} +\pgf@def{cosfrac}{73}{0.807687} \pgf@def{cosfrac}{74}{0.803842} +\pgf@def{cosfrac}{75}{0.8} \pgf@def{cosfrac}{76}{0.796162} +\pgf@def{cosfrac}{77}{0.792329} \pgf@def{cosfrac}{78}{0.788502} +\pgf@def{cosfrac}{79}{0.784682} \pgf@def{cosfrac}{80}{0.780869} +\pgf@def{cosfrac}{81}{0.777064} \pgf@def{cosfrac}{82}{0.773268} +\pgf@def{cosfrac}{83}{0.769481} \pgf@def{cosfrac}{84}{0.765705} +\pgf@def{cosfrac}{85}{0.761939} \pgf@def{cosfrac}{86}{0.758185} +\pgf@def{cosfrac}{87}{0.754443} \pgf@def{cosfrac}{88}{0.750714} +\pgf@def{cosfrac}{89}{0.746997} \pgf@def{cosfrac}{90}{0.743294} +\pgf@def{cosfrac}{91}{0.739605} \pgf@def{cosfrac}{92}{0.735931} +\pgf@def{cosfrac}{93}{0.732272} \pgf@def{cosfrac}{94}{0.728628} +\pgf@def{cosfrac}{95}{0.724999} \pgf@def{cosfrac}{96}{0.721387} +\pgf@def{cosfrac}{97}{0.717792} \pgf@def{cosfrac}{98}{0.714213} +\pgf@def{cosfrac}{99}{0.710651} \pgf@def{cosfrac}{100}{0.707107} + + + + +% Forward declarations for nonlinear stuff (have no effect till module +% nonlineartransformations is loaded) + +\let\pgfpointtransformednonlinear\pgfpointtransformed + + +\endinput diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcorequick.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcorequick.code.tex new file mode 100644 index 0000000000..4180440b00 --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcorequick.code.tex @@ -0,0 +1,134 @@ +% Copyright 2018 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{pgfcorequick.code.tex} + +% Quick version of basic drawing commands. Most high-level commands +% are not available if these commands are used. + +% Move current point to (#1,#2). +% +% #1 = x dimension of new current point +% #2 = y dimension of new current point +% +% Example: +% +% \pgfpathqmoveto{0pt}{0pt} +% \pgfpathqlineto{1pt}{1pt} +% \pgfpathqcurveto{2pt}{1pt}{2pt}{2pt}{3pt}{2pt} +% \pgfqstroke + +\def\pgfpathqmoveto#1#2{\pgfsyssoftpath@moveto{#1}{#2}} + + +% Append a line to (#1,#2) to the current path. +% +% #1 = x dimension of target +% #2 = y dimension of target +% +% Example: +% +% \pgfpathqmoveto{0pt}{0pt} +% \pgfpathqlineto{1pt}{1pt} +% \pgfpathqcurveto{2pt}{1pt}{2pt}{2pt}{3pt}{2pt} +% \pgfqstroke + +\def\pgfpathqlineto#1#2{\pgfsyssoftpath@lineto{#1}{#2}} + + +% Append a bezier spline to the current path. +% +% #1 = x dimension of first support point +% #2 = y dimension of first support point +% #3 = x dimension of second support point +% #4 = y dimension of second support point +% #5 = x dimension of target point +% #6 = y dimension of target point +% +% Example: +% +% \pgfpathqmoveto{0pt}{0pt} +% \pgfpathqlineto{1pt}{1pt} +% \pgfpathqcurveto{2pt}{1pt}{2pt}{2pt}{3pt}{2pt} +% \pgfqstroke + +\def\pgfpathqcurveto#1#2#3#4#5#6{\pgfsyssoftpath@curveto{#1}{#2}{#3}{#4}{#5}{#6}} + + + + +% Append a circle of the given radius around the origin. +% +% #1 = radius +% +% Example: +% +% \pgfpathqcircle{10pt} +% is quicker than +% \pgfpathcircle{\pgforigin}{10pt} + +\def\pgfpathqcircle#1{% + {% + \pgf@x=#1% + \pgf@y=0.5522847\pgf@x% + \pgfsyssoftpath@moveto{\the\pgf@x}{0pt}% + \pgfsyssoftpath@curveto{\the\pgf@x}{\the\pgf@y}{\the\pgf@y}{\the\pgf@x}{0pt}{\the\pgf@x}% + \pgfsyssoftpath@curveto{-\the\pgf@y}{\the\pgf@x}{-\the\pgf@x}{\the\pgf@y}{-\the\pgf@x}{0pt}% + \pgfsyssoftpath@curveto{-\the\pgf@x}{-\the\pgf@y}{-\the\pgf@y}{-\the\pgf@x}{0pt}{-\the\pgf@x}% + \pgfsyssoftpath@curveto{\the\pgf@y}{-\the\pgf@x}{\the\pgf@x}{-\the\pgf@y}{\the\pgf@x}{0pt}% + \pgfsyssoftpath@closepath% + }% +} + + + +% Stroke current path. No hooks called. +% +% Example: +% +% \pgfpathqmoveto{0cm}{0cm} +% \pgfpathqlineto{1cm}{1cm} +% \pgfpathqcurveto{2cm}{1cm}{2cm}{2cm}{3cm}{2cm} +% \pgfqstroke + +\def\pgfusepathqstroke{% + \pgfsyssoftpath@flushcurrentpath% + \pgfsys@stroke% + \pgf@resetpathsizes% +} + + +% Quickly fill current path. + +\def\pgfusepathqfill{% + \pgfsyssoftpath@flushcurrentpath% + \pgfsys@fill% + \pgf@resetpathsizes% +} + + +% Quickly fill and stroke current path. + +\def\pgfusepathqfillstroke{% + \pgfsyssoftpath@flushcurrentpath% + \pgfsys@fillstroke% + \pgf@resetpathsizes% +} + +% Quickly clip current path. + +\def\pgfusepathqclip{% + \pgfsyssoftpath@flushcurrentpath% + \pgfsys@clipnext% + \pgfsys@discardpath% + \pgf@resetpathsizes% +} + + +\endinput diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcorerdf.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcorerdf.code.tex new file mode 100644 index 0000000000..1069318a4b --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcorerdf.code.tex @@ -0,0 +1,228 @@ +% Copyright 2018 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{pgfcorerdf.code.tex} + + + +% +% +% The Resource Description Framework (RDF) is a method of enriching +% output files with semantic information. In PGF, you can use the +% following commands to create RDF information that will be inserted +% into the output, provided the output format allows this (SVG +% does). You call any of these commands before an ID-scope and it will +% attach the attribute(s) to this id scope. +% +% +% Example: +% +% ... +% \pgfrdftypeof{http://purl.org/dc/dcmitype/Image} +% \pgfrdfresource{/paper/figures/1} +% \pgfidscope +% % This ID scope will be flagged as the resource "/paper/figures/1" +% % and typeof "Image" from the Dublin Core. +% ... +% \endidscope + + + + + +% Adds the rdf attribute "about" with value #1 to the next +% idscope. +% +% #1 = A URL +% +% Description: +% +% The RDF-spec says: "a SafeCURIEorCURIEorIRI, used for stating what +% the data is about (a 'subject' in RDF terminology);" + +\def\pgfrdfabout#1{\pgfsys@rdf@about{#1}} + + + +% Adds the rdf attribute content with value #1 to the next +% idscope. +% +% #1 = A URL +% +% Description: +% +% The RDF-spec says: "a CDATA string, for supplying machine-readable +% content for a literal (a 'literal object', in RDF terminology);" + +\def\pgfrdfcontent#1{\pgfsys@rdf@content{#1}} + + + +% Adds the rdf attribute datatype with value #1 to the next +% idscope. +% +% #1 = A URL +% +% Description: +% +% The RDF-spec says: "a TERMorCURIEorAbsIRI representing a datatype, +% to express the datatype of a literal;" + +\def\pgfrdfdatatype#1{\pgfsys@rdf@datatype{#1}} + + + +% Adds the rdf attribute href with value #1 to the next idscope +% The RDF-spec says: "a traditionally navigable IRI for +% expressing the partner resource of a relationship (a 'resource object', in RDF terminology);" + +\def\pgfrdfhref#1{\pgfsys@rdf@href{#1}} + + + +% Adds the rdf attribute inlist to the next idscope. +% +% Description: +% +% The RDF-spec says: "An attribute used to indicate that the object +% associated with a rel or property attribute on the same element is +% to be added to the list for that predicate. Presence of this +% attribute causes a list to be created if it does not already exist." + +\def\pgfrdfinlist{\pgfsys@rdf@inlist} + + + + +% Adds #1 to the list of the rdf prefix attribute to the next +% idscope. +% +% #1 = A URL +% +% Description: +% +% Can be called several times, in which case all values of #1 are +% concatenated with whitespaces. The RDF-spec says: "a white space +% separated list of prefix-name IRI pairs of the form NCName ':' ' '+ +% xsd:anyURI" + +\def\pgfrdfprefix#1{\pgfsys@rdf@prefix{#1}} + + + + +% Adds #1 to the list of the rdf property attribute to the next +% idscope. +% +% #1 = A URL +% +% Description: +% +% Can be called repeatedly. The RDF-spec says: "a white space +% separated list of TERMorCURIEorAbsIRIs, used for expressing +% relationships between a subject and either a resource object if +% given or some literal text (also a 'predicate');" + +\def\pgfrdfproperty#1{\pgfsys@rdf@property{#1}} + + + +% Adds #1 to the list of the rdf rel attribute to the next +% next idscope. +% +% #1 = A URL +% +% Description: +% +% Can be called repeatedly. The RDF-spec says: "a white space +% separated list of TERMorCURIEorAbsIRIs, used for expressing +% relationships between two resources ('predicates' in RDF +% terminology);" + +\def\pgfrdfrel#1{\pgfsys@rdf@rel{#1}} + + +% Adds the rdf attribute resource with value #1 to the next idscope. +% +% #1 = A URL +% +% Description: +% +% The RDF-spec says: "a SafeCURIEorCURIEorIRI for expressing the +% partner resource of a relationship that is not intended to be +% navigable (e.g., a 'clickable' link) (also an 'object');" + +\def\pgfrdfresource#1{\pgfsys@rdf@resource{#1}} + + + + +% Adds #1 to the list of the rdf rev attribute to the next +% idscope. +% +% #1 = A URL +% +% Description: +% +% Can be called repeatedly. The RDF-spec says: "a white space +% separated list of TERMorCURIEorAbsIRIs, used for expressing reverse +% relationships between two resources (also 'predicates'); + +\def\pgfrdfrev#1{\pgfsys@rdf@rev{#1}} + + + + +% Adds an rdf attribute src with value #1 to the next idscope. +% +% #1 = A URL +% +% Description: +% +% The RDF-spec says: "an IRI for expressing the partner resource of a +% relationship when the resource is embedded (also a 'resource object');" + +\def\pgfrdfsrc#1{\pgfsys@rdf@src{#1}} + + + + +% Adds #1 to the list of the rdf typeof attribute to the next +% idscope. +% +% #1 = A URL +% +% Description: +% +% Can be called repeatedly. The RDF-spec says: "a white space +% separated list of TERMorCURIEorAbsIRIs that indicate the RDF type(s) +% to associate with a subject;" + +\def\pgfrdftypeof#1{\pgfsys@rdf@typeof{#1}} + + + + +% Adds an rdf attribute vocab with value #1 to the next idscope. +% +% #1 = A URL +% +% Description: +% +% The RDF-spec says: "an IRI that defines the mapping to use when a +% TERM is referenced in an attribute value. See General Use of Terms +% in Attributes and the section on Vocabulary Expansion." + +\def\pgfrdfvocab#1{\pgfsys@rdf@vocab{#1}} + + + + + +\endinput diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcorescopes.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcorescopes.code.tex new file mode 100644 index 0000000000..75cb1b587d --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcorescopes.code.tex @@ -0,0 +1,771 @@ +% Copyright 2019 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{pgfcorescopes.code.tex} + +% Globals + +\newbox\pgfpic +\newbox\pgf@hbox + +\newbox\pgf@layerbox@main + +\newcount\pgf@picture@serial@count + + + +% This if decides whether the position of pictures on the page is +% protocolled or not. Normally, +% this is switched off as it works only with certain drivers and it +% causes external files to be written. When switched on, the position +% of pgfpictures are protocolled and can be referenced using +% \pgfsys@getposition{XXX} where XXX is the value of \pgfpictureid +% inside the picture. +\newif\ifpgfrememberpicturepositiononpage + + + + +% Scopes + + +% Pgf scope environment. All changes of the graphic state are local to +% the scope. +% +% Example: +% +% \begin{pgfscope} +% \pgfsetlinewidth{3pt} +% \pgfline{\pgfxy(0,0)}{\pgfxy(3,3)} +% \end{pgfscope} + +\def\pgfscope{% + \pgfsyssoftpath@setcurrentpath\pgfutil@empty% + \pgfsys@beginscope% + \pgf@resetpathsizes% + \edef\pgfscope@linewidth{\the\pgflinewidth}% + \let\pgfscope@stroke@color=\pgf@strokecolor@global% + \let\pgfscope@fill@color=\pgf@fillcolor@global% + \begingroup} +\def\endpgfscope{% + \endgroup% + \global\pgflinewidth=\pgfscope@linewidth% + \global\let\pgf@strokecolor@global=\pgfscope@stroke@color% + \global\let\pgf@fillcolor@global=\pgfscope@fill@color% + \pgfsys@endscope} + + + + +% Quickly insert a box can contain normal TeX text at the origin. +% +% #1 = box of width/height and depth 0pt +% +% Example: +% +% \pgfqbox{\mybox} + +\def\pgfqbox#1{% + \pgfsys@hbox#1% +} + + +% Insert a box that can contain normal TeX text at the origin, but +% with the current coordinate transformation matrix synced with the +% low-level transformation matrix. +% +% #1 = box of width/height and depth 0pt +% +% In essence, this command does the same as if you first said +% \pgflowlevelsynccm and then \pgfqbox. However, pgf will use a +% ``TeX-translation'' for the translation part of the transformation +% cm. This will ensure that hyperlinks ``survive'' at least +% translations. +% +% Example: +% +% \pgfqboxsynced{\mybox} + +\def\pgfqboxsynced#1{% + \pgfsys@hboxsynced#1% +} + + +% Puts some text in a box and inserts it with the current +% transformations applied. +% +% #1 = List of optional positioning. Possible values are ``left'', ``right'', +% ``top'', ``bottom'' and ``base''. +% #2 = TeX text. May contain verbatims. +% +% Example: +% +% \pgftransformshift{\pgfpoint{1cm}{0cm}} +% \pgftext{Hello World!} + +\def\pgftext{\pgfutil@ifnextchar[\pgf@text{\pgf@text[]}}% +\def\pgf@text[#1]{% + \def\pgf@text@options{#1}% + \pgf@maketext\pgf@after@text} +\def\pgf@after@text{% + {% + \def\pgf@text@hshift{center}% + \def\pgf@text@vshift{center}% + \expandafter\pgf@text@setkeys\expandafter{\pgf@text@options}% + \csname pgf@halign\pgf@text@hshift\endcsname% + \csname pgf@valign\pgf@text@vshift\endcsname% + % + \pgfapproximatenonlineartransformation% + % Protocol sizes: + \pgf@process{\pgfpointtransformed{\pgfqpoint{0pt}{\dp\pgf@hbox}}}% + \pgf@protocolsizes{\pgf@x}{\pgf@y}% + \pgf@process{\pgfpointtransformed{\pgfqpoint{\wd\pgf@hbox}{\dp\pgf@hbox}}}% + \pgf@protocolsizes{\pgf@x}{\pgf@y}% + \pgf@process{\pgfpointtransformed{\pgfqpoint{0pt}{\ht\pgf@hbox}}}% + \pgf@protocolsizes{\pgf@x}{\pgf@y}% + \pgf@process{\pgfpointtransformed{\pgfqpoint{\wd\pgf@hbox}{\ht\pgf@hbox}}}% + \pgf@protocolsizes{\pgf@x}{\pgf@y}% + \pgfqboxsynced{\pgf@hbox}% + }% +} +\def\pgf@text@setkeys{\pgfqkeys{/pgf/text}}% + +\pgfkeys{/pgf/text/left/.code=\def\pgf@text@hshift{left}} +\pgfkeys{/pgf/text/center/.code=} +\pgfkeys{/pgf/text/right/.code=\def\pgf@text@hshift{right}} +\pgfkeys{/pgf/text/top/.code=\def\pgf@text@vshift{top}} +\pgfkeys{/pgf/text/bottom/.code=\def\pgf@text@vshift{bottom}} +\pgfkeys{/pgf/text/base/.code=\def\pgf@text@vshift{base}} +\pgfkeys{/pgf/text/at/.cd,.code=\pgftransformshift{#1},.value required} +\pgfkeys{/pgf/text/x/.cd,.code=\pgftransformxshift{#1},.value required} +\pgfkeys{/pgf/text/y/.cd,.code=\pgftransformyshift{#1},.value required} +\pgfkeys{/pgf/text/rotate/.cd,.code=\pgftransformrotate{#1},.value required} + +\def\pgf@halignleft{}% do nothing +\def\pgf@haligncenter{\pgftransformxshift{+-.5\wd\pgf@hbox}} +\def\pgf@halignright{\pgftransformxshift{+-\wd\pgf@hbox}}% +\def\pgf@valignbase{}% do nothing +\def\pgf@valignbottom{\pgftransformyshift{+\dp\pgf@hbox}}% +\def\pgf@valigncenter{\pgftransformyshift{+.5\dp\pgf@hbox}\pgftransformyshift{+-.5\ht\pgf@hbox}}% +\def\pgf@valigntop{\pgftransformyshift{+-\ht\pgf@hbox}}% + + +% Internal function for creating a hbox. +\def\pgf@maketext#1{% + \def\pgf@@maketextafter{#1}% + \setbox\pgf@hbox=\hbox\bgroup% + \pgfinterruptpicture% + \bgroup% + \aftergroup\pgf@collectresetcolor% + \let\next=% +} +\def\pgf@collectresetcolor{% + \pgfutil@ifnextchar\reset@color% + {\reset@color\afterassignment\pgf@collectresetcolor\let\pgf@temp=}% + {\pgf@textdone}% +} +\def\pgf@textdone{% + \endpgfinterruptpicture% + \egroup% + \pgf@@maketextafter% +} + +\long\def\pgf@makehbox#1{% + \setbox\pgf@hbox=\hbox{{% + \pgfinterruptpicture% + #1% + \endpgfinterruptpicture% + }}} + + + +% Picture environment +% +% Example: +% +% \begin{pgfpicture} +% \pgfsetendarrow{\pgfarrowto} +% \pgfpathmoveto{\pgfpointxy{-0.9}{0.2}} +% \pgfpathlineto{\pgfpointxy{0.9}{0.4}} +% \pgfusepath{stroke} +% \end{pgfpicture} + +\def\pgfresetboundingbox{% + \global\pgf@picmaxx=-16000pt\relax% + \global\pgf@picminx=16000pt\relax% + \global\pgf@picmaxy=-16000pt\relax% + \global\pgf@picminy=16000pt\relax% +}% + +\def\pgfpicture{% + \begingroup% + \pgfpicturetrue% + \global\advance\pgf@picture@serial@count by1\relax% + \edef\pgfpictureid{pgfid\the\pgf@picture@serial@count}% + \let\pgf@nodecallback=\pgfutil@gobble% + \pgf@picmaxx=-16000pt\relax% + \pgf@picminx=16000pt\relax% + \pgf@picmaxy=-16000pt\relax% + \pgf@picminy=16000pt\relax% + \pgf@relevantforpicturesizetrue% + \pgf@resetpathsizes% + \pgfutil@ifnextchar\bgroup\pgf@oldpicture\pgf@picture} +\def\pgf@oldpicture#1#2#3#4{% + \pgfmathsetlength\pgf@picminx{#1}% + \pgfmathsetlength\pgf@picminy{#2}% + \pgfmathsetlength\pgf@picmaxx{#3}% + \pgfmathsetlength\pgf@picmaxy{#4}% + \pgf@relevantforpicturesizefalse% + \pgf@picture} + +\def\pgf@picture{% + \setbox\pgfpic\hbox to0pt\bgroup% + \begingroup% + \pgfsys@beginpicture% + \pgfsys@beginscope% + \begingroup% + \pgfsetcolor{.}% + \pgfsetlinewidth{0.4pt}% + \pgftransformreset% + \pgfsyssoftpath@setcurrentpath\pgfutil@empty% + \begingroup% + \let\pgf@setlengthorig=\setlength% + \let\pgf@addtolengthorig=\addtolength% + \let\pgf@selectfontorig=\selectfont% + \let\setlength=\pgf@setlength% + \let\addtolength=\pgf@addtolength% + \let\selectfont=\pgf@selectfont% + \nullfont\spaceskip0pt\xspaceskip0pt% + \tracinglostchars=% + \ifnum\tracinglostchars>2 2\else\tracinglostchars\fi + \setbox\pgf@layerbox@main\hbox to0pt\bgroup% + \begingroup% + } +\def\endpgfpicture{% + \ifpgfrememberpicturepositiononpage% + \hbox to0pt{\pgfsys@markposition{\pgfpictureid}}% + \fi% + % ok, now let's position the box + \ifdim\pgf@picmaxx=-16000pt\relax% + % empty picture. make size 0. + \global\pgf@picmaxx=0pt\relax% + \global\pgf@picminx=0pt\relax% + \global\pgf@picmaxy=0pt\relax% + \global\pgf@picminy=0pt\relax% + \fi% + % Shift baseline outside: + \pgf@relevantforpicturesizefalse% + \pgf@process{\pgf@baseline}% + \xdef\pgf@shift@baseline{\the\pgf@y}% + % + \pgf@process{\pgf@trimleft}% + \global\advance\pgf@x by-\pgf@picminx + % prepare \hskip\pgf@trimleft@final. + % note that \pgf@trimleft@final is also queried + % by the pgf image externalization. + \xdef\pgf@trimleft@final{-\the\pgf@x}% + % + \pgf@process{\pgf@trimright}% + \global\advance\pgf@x by-\pgf@picmaxx + % prepare \hskip\pgf@trimright@final. + % note that \pgf@trimright@final is also queried + % by the pgf image externalization. + \xdef\pgf@trimright@final{\the\pgf@x}% + % + \pgf@remember@layerlist@globally + \endgroup% + \hss% + \egroup% + \pgf@restore@layerlist@from@global + \pgf@insertlayers% + \endgroup% + \pgfsys@discardpath% + \endgroup% + \pgfsys@endscope% + \pgfsys@endpicture% + \endgroup% + \hss + \egroup% + \pgfsys@typesetpicturebox\pgfpic% + \endgroup% +} + +\def\pgf@remember@layerlist@globally{% + \global\let\pgf@layerlist@=\pgf@layerlist +}% +\def\pgf@restore@layerlist@from@global{% + \let\pgf@layerlist=\pgf@layerlist@ +}% +\def\pgf@insertlayers{% + \box\pgf@layerbox@main% +} + +\def\pgf@selectfont{\pgf@selectfontorig\nullfont} + +\def\pgf@setlength#1#2{% these will be used only when \nullfont is active + \begingroup% keep font setting local + \pgfutil@selectfont% restore font + \pgf@setlengthorig#1{#2}% calculate dimension (possibly using calc) + \expandafter% + \endgroup% + \expandafter#1\expandafter=\the#1\relax} +\def\pgf@addtolength#1#2{% + \begingroup% keep font setting local + \pgfutil@selectfont% restore font + \pgf@addtolengthorig#1{#2}% calculate dimension (possibly using calc) + \expandafter% + \endgroup% + \expandafter#1\expandafter=\the#1\relax} + + +% Sets the baseline at the y-coordinate of a given point +% +% #1 = point +% +% Sets the baseline of the picture to the y-coordinate of a given +% point. However, the point will be evaluated *at the end of the +% picture*. +% +% Example: +% +% \pgfsetbaselinepointlater{\pgfpointanchor{mynode}{base}} + +\def\pgfsetbaselinepointlater#1{\def\pgf@baseline{#1}} + + +% Sets the baseline at the y-coordinate of a given point, now +% +% #1 = point +% +% Sets the baseline of the picture to the y-coordinate of a given +% point. +% +% Example: +% +% \pgfsetbaselinepointnow{\pgfpoint{1cm}{2pt}} + +\def\pgfsetbaselinepointnow#1{% + \pgf@process{#1}% + \edef\pgf@setter@baseline{\noexpand\pgfpoint{\the\pgf@x}{\the\pgf@y}}% + \pgfsetbaselinepointlater{\pgf@setter@baseline}% +} + +\def\pgf@default@text{default}% + +% Sets the baseline +% +% #1 = baseline +% +% Sets the baseline of the picture. Default is the lower border, which +% is the same as \pgf@picminy +% +% Example: +% +% \pgfsetbaseline{1cm+2pt} +% \pgfsetbaseline{default}% resets to default value + +\def\pgfsetbaseline#1{% + \def\pgf@temp{#1}% + \ifx\pgf@temp\pgf@default@text + \pgfsetbaseline{\pgf@picminy}% + \else + \pgfsetbaselinepointlater{\pgfpoint{0pt}{#1}}% + \fi +} +\pgfsetbaseline{\pgf@picminy} + +% controls how the image externalization implements trim: +\newif\ifpgf@trim@lowlevel +\pgfkeys{ + /pgf/trim lowlevel/.is if=pgf@trim@lowlevel, + /pgf/trim lowlevel/.default=true, +} + +% Same as the y-baseline for horizontal alignment. +% The effect is different, though: it is some kind of trimming which +% leaves the bounding box intact. +\def\pgfsettrimleftpointlater#1{\def\pgf@trimleft{#1}} +\def\pgfsettrimleftpointnow#1{% + \pgf@process{#1}% + \edef\pgf@setter@baseline{\noexpand\pgfpoint{\the\pgf@x}{\the\pgf@y}}% + \pgfsettrimleftpointlater{\pgf@setter@baseline}% +} +% \pgfsettrimleft{<x coord>} +% or +% \pgfsettrimleft{default} +\def\pgfsettrimleft#1{% + \def\pgf@temp{#1}% + \ifx\pgf@temp\pgf@default@text + \pgfsettrimleft{\pgf@picminx} + \else + \pgfsettrimleftpointlater{\pgfpoint{#1}{0pt}}% + \fi +} +\pgfsettrimleft{\pgf@picminx} + +\def\pgfsettrimrightpointlater#1{\def\pgf@trimright{#1}} +\def\pgfsettrimrightpointnow#1{% + \pgf@process{#1}% + \edef\pgf@setter@baseline{\noexpand\pgfpoint{\the\pgf@x}{\the\pgf@y}}% + \pgfsettrimrightpointlater{\pgf@setter@baseline}% +} +% \pgfsettrimright{<x coord>} +% or +% \pgfsettrimright{default} +\def\pgfsettrimright#1{% + \def\pgf@temp{#1}% + \ifx\pgf@temp\pgf@default@text + \pgfsettrimright{\pgf@picmaxx}% + \else + \pgfsettrimrightpointlater{\pgfpoint{#1}{0pt}}% + \fi +} +\pgfsettrimright{\pgf@picmaxx} + + +% Interrupt path +% +% Description: +% +% The environment can be used to insert some drawing commands while +% constructing a path. The drawing commands inside the environment +% will not interfere with the path being constructed ``outside.'' +% However, you must ward against graphic state changes using a scope. +% +% Example: Draw two parallel lines +% +% \pgfmoveto{\pgfpoint{0cm}{0cm}} +% \begin{pgfinterruptpath} +% \pgfmoveto{\pgfpoint{1cm}{0cm}} +% \pgfmoveto{\pgfpoint{1cm}{1cm}} +% \pgfusepath{stroke} +% \end{pgfinterruptpath} +% \pgflineto{\pgfpoint{0cm}{1cm}} +% \pgfusepath{stroke} + +\def\pgfinterruptpath +{% + \begingroup% + % save all sorts of things... + \edef\pgf@interrupt@savex{\the\pgf@path@lastx}% + \edef\pgf@interrupt@savey{\the\pgf@path@lasty}% + \pgf@getpathsizes\pgf@interrupt@pathsizes% + \pgfsyssoftpath@getcurrentpath\pgf@interrupt@path% + \pgfsyssoftpath@setcurrentpath\pgfutil@empty% + \let\pgf@interrupt@lastmoveto=\pgfsyssoftpath@lastmoveto% + \begingroup% +} +\def\endpgfinterruptpath +{% + \endgroup% + \pgfsyssoftpath@setcurrentpath\pgf@interrupt@path% + \pgf@setpathsizes\pgf@interrupt@pathsizes% + \global\pgf@path@lastx\pgf@interrupt@savex% + \global\pgf@path@lasty\pgf@interrupt@savey% + \global\let\pgfsyssoftpath@lastmoveto\pgf@interrupt@lastmoveto% + \endgroup% +} + + + +% Interrupt bounding box +% +% Description: +% +% The environment can be used to temporarily setup a new bounding box +% computation. The bounding box will be made empty at the beginning of +% the environment and will be reset to its old value after the +% environment. +% +% Example: +% +% \begin{pgfinterruptboundinbox} +% \pgfmoveto{\pgfpoint{1cm}{0cm}} +% \pgfmoveto{\pgfpoint{1cm}{1cm}} +% \pgfusepath{stroke} +% \end{pgfinterruptboundinbox} + +\def\pgfinterruptboundingbox +{% + \begingroup% + \edef\pgf@interrupt@savemaxx{\the\pgf@picmaxx}% + \edef\pgf@interrupt@saveminx{\the\pgf@picminx}% + \edef\pgf@interrupt@savemaxy{\the\pgf@picmaxy}% + \edef\pgf@interrupt@saveminy{\the\pgf@picminy}% + \pgf@picmaxx=-16000pt\relax% + \pgf@picminx=16000pt\relax% + \pgf@picmaxy=-16000pt\relax% + \pgf@picminy=16000pt\relax% + \pgf@size@hookedfalse% + \let\pgf@path@size@hook=\pgfutil@empty% +} +\def\endpgfinterruptboundingbox +{% + \global\pgf@picmaxx=\pgf@interrupt@savemaxx% + \global\pgf@picmaxy=\pgf@interrupt@savemaxy% + \global\pgf@picminx=\pgf@interrupt@saveminx% + \global\pgf@picminy=\pgf@interrupt@saveminy% + \endgroup% +} + + + + +% Creates an id scope. +% +% Description: +% +% An id scope is not (conceptually) a graphic scope, but a scope that +% has a unique name or "id". This id can be used as a reference point +% for instance for a hyperlink or for an animation (currently, only +% SVG supports ids, all other drivers ignore id scopes). +% +% Prior to using \pgfidscope, call \pgfuseid to install an +% id (and possibly \pgfusetype). The scope will then get this id and, +% likely, a graphic scope is installed. If \pgfuseid has not been +% called or if you try to call \pgfidscope again for the same id, +% nothing happens (except for a \TeX\ group being established). + +\def\pgfidscope{\pgfsys@begin@idscope} +\def\endpgfidscope{\pgfsys@end@idscope} + +\let\startpgfidscope\pgfidscope +\let\stoppgfidscope\pgfendidscope + + + + +% Use an id on the next graphic object +% +% #1 = a name +% +% The next scope or path can be the target of an animation command or +% a hyperlink. + +\def\pgfuseid#1{% + \edef\pgf@temp{#1}% + \ifx\pgf@temp\pgfutil@empty% + \else% + \pgf@lookup@id{#1}% + \pgfsys@use@id{\pgf@next@id}% + \expandafter\xdef\csname pgf@id@names@#1\endcsname{{\pgf@next@id}{}}% + \fi% +} + +\def\pgf@lookup@id#1{% + \expandafter\let\expandafter\pgf@id@name\csname pgf@id@names@#1\endcsname% + \ifx\pgf@id@name\relax% + \let\pgf@prev@id\pgfutil@empty% + \let\pgf@next@id\pgfutil@empty% + \else% + \expandafter\pgf@id@parse\pgf@id@name% + \fi% + \ifx\pgf@next@id\pgfutil@empty% + \pgfsys@new@id\pgf@next@id% + \expandafter\xdef\csname pgf@id@names@#1\endcsname{{\pgf@prev@id}{\pgf@next@id}}% + \fi% +} +\def\pgf@id@parse#1#2{% + \def\pgf@prev@id{#1}% + \def\pgf@next@id{#2}% +} + + + +% Clear the current id +% +% Description: +% +% Sets the current id to be empty so that it cannot be referenced. + +\def\pgfclearid{% + \pgfsys@clear@id% +} + + +% Get the id that will be given to a name upon the next use +% +% #1 = a macro +% #2 = a name +% +% Description: +% +% #1 will get the id that will be used by \pgfuseid next time for the +% given name. + +\def\pgfidrefnextuse#1#2{% + \edef\pgf@temp{#2}\ifx\pgf@temp\pgfutil@empty\pgferror{Missing name reference for ``\string#1''}\fi% + \pgf@lookup@id{#2}% + \let#1\pgf@next@id% +} + + +% Get the id was last used +% +% #1 = a macro +% #2 = a name +% +% Description: +% +% #1 will get the id that was last used by \pgfuseid for #2. + +\def\pgfidrefprevuse#1#2{% + \edef\pgf@temp{#2}\ifx\pgf@temp\pgfutil@empty\pgferror{Missing name reference for ``\string#1''}\fi% + \pgf@lookup@id{#2}% + \let#1\pgf@prev@id% +} + + +% Use a type +% +% #1 = an id type; when starting with a dot, it is added to the +% current type. +% +% The next scope or path can be the target of an animation command or +% a hyperlink. + +\def\pgfusetype#1{% + \edef\pgf@temp{#1}% + \expandafter\pgfutil@ifnextchar\expandafter.\expandafter\pgf@id@use@type@add\expandafter\pgf@id@use@type@replace\pgf@temp\pgf@stop +} +\def\pgf@id@use@type@add.#1\pgf@stop{\pgfsys@append@type{#1}} +\def\pgf@id@use@type@replace#1\pgf@stop{\pgfsys@use@type{#1}} + +% Push the current type on a global stack +% +% Description: +% +% The current type is pushed onto a global type stack. It can be +% restored using \pgfpoptype. + +\def\pgfpushtype{\pgfsys@push@type} + + +% Pop a type from the type stack +% +% Description: +% +% Restores the most current value from the type stack. + +\def\pgfpoptype{\pgfsys@pop@type} + + + + +% Alias an id locally or globally +% +% #1 = the alias name +% #2 = a existing id name +% +% Description: +% +% Creates an alias of a name + +\def\pgfaliasid#1#2{% + \expandafter\let\expandafter\pgf@temp\csname pgf@id@names@#2\endcsname% + \expandafter\let\csname pgf@id@names@#1\endcsname\pgf@temp% +} +\def\pgfgaliasid#1#2{% + \expandafter\let\expandafter\pgf@temp\csname pgf@id@names@#2\endcsname% + \expandafter\global\expandafter\let\csname pgf@id@names@#1\endcsname\pgf@temp% +} + + +% Check whether a name has been forward-referenced +% +% #1 = a name +% #2 = what to do, when has been forward-referenced +% #3 = what to do otherwise +% +% Description: +% +% Depending on whether #1 has been forward-referenced, #2 or #3 will be executed. + +\def\pgfifidreferenced#1#2#3{% + \expandafter\let\expandafter\pgf@id@name\csname pgf@id@names@#1\endcsname% + \ifx\pgf@id@name\relax% + #3% + \else + \expandafter\pgf@id@parse\pgf@id@name% + \ifx\pgf@next@id\pgfutil@empty% + #3% + \else% + #2% + \fi% + \fi% +} + + +% Interrupts a picture +% +% Description: +% +% This environment interrupts a picture and temporarily returns to +% normal TeX mode. All sorts of things are saved and restored by this +% environment. +% +% WARNING: Using this environment in conjunction with low level +% transformations can *strongly* upset the typesetting. Typically, the +% contents of this environment should have size/height/depth 0pt in +% the end. +% +% WARNING: This environment should only be used inside typesetting a +% box and this box must in turn be inserted using \pgfqbox. +% +% Example: Draw two parallel lines +% +% \pgfmoveto{\pgfpoint{0cm}{0cm}} +% \setbox\mybox=\hbox{ +% \begin{pgfinterruptpicture} +% This is normal text. +% \begin{pgfpicture} % a subpicture +% \pgfmoveto{\pgfpoint{1cm}{0cm}} +% \pgfmoveto{\pgfpoint{1cm}{1cm}} +% \pgfusepath{stroke} +% \end{pgfpicture} +% More text. +% \end{pgfinterruptpicture} +% } +% \ht\mybox=0pt +% \wd\mybox=0pt +% \dp\mybox=0pt +% \pgfqbox{\mybox}% +% \pgfpathlineto{\pgfpoint{0cm}{1cm}} +% \pgfusepath{stroke} + +\def\pgfinterruptpicture +{% + \begingroup% + \csname tikz@inside@picturefalse\endcsname% + \pgfinterruptboundingbox% + \pgftransformreset% + \pgfinterruptpath% + \ifx\pgf@selectfontorig\@undefined% + \else% + \let\setlength\pgf@setlengthorig% + \let\addtolength\pgf@addtolengthorig% + \let\selectfont\pgf@selectfontorig% + \fi% + \pgfutil@selectfont% + \pgfpicturefalse% + \let\pgf@positionnodelater@macro\relax% + \pgf@savelayers% +} +\def\endpgfinterruptpicture +{% + \pgf@restorelayers% + \endpgfinterruptpath% + \endpgfinterruptboundingbox% + \endgroup% +} + +\let\pgf@savelayers=\relax +\let\pgf@restorelayers=\relax + +\endinput diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcoreshade.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcoreshade.code.tex new file mode 100644 index 0000000000..39a40c54ee --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcoreshade.code.tex @@ -0,0 +1,974 @@ +% Copyright 2019 by Till Tantau +% CMYK and grayscale shadings adaptation copyright 2019 by David Purton +% +% 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{pgfcoreshade.code.tex} + +% +% Parsing functions +% +\newdimen\pgf@max +\newcount\pgf@sys@shading@range@num +\def\pgf@parsefunc#1{% + \edef\temp{{#1}}% + \expandafter\pgf@convertstring\temp% + \edef\temp{{\pgf@conv}}% + \expandafter\pgf@@parsefunc\temp} +\def\pgf@@parsefunc#1{% + \let\pgf@bounds=\pgfutil@empty% + \let\pgf@funcs=\pgfutil@empty% + \let\pgf@psfuncs=\pgfutil@empty% + \let\pgf@encode=\pgfutil@empty% + \let\pgf@sys@shading@ranges=\pgfutil@empty% + \pgf@sys@shading@range@num=0\relax% + \csname pgf@parsefirst\pgf@shading@model\endcsname[#1; ]% + \csname pgf@parselastdom\pgf@shading@model\endcsname[#1; ]% + \csname pgf@parsemid\pgf@shading@model\endcsname[#1; ]% + \ifx\pgf@bounds\pgfutil@empty% + \edef\pgf@pdfparseddomain{0 1}% + \edef\pgf@pdfparsedfunction{\pgf@singlefunc\space}% + \else% + \edef\pgf@pdfparseddomain{\pgf@doma\space\pgf@domb}% + \edef\pgf@pdfparsedfunction{% + << /FunctionType 3 /Domain [\pgf@doma\space\pgf@domb] /Functions + [\pgf@funcs\space] /Bounds [\pgf@bounds] /Encode [0 1 \pgf@encode] + >> }% << + \fi% + \xdef\pgf@psfuncs{\pgf@psfuncs}% + } +\def\pgf@parsefirstrgb[rgb(#1)=(#2,#3,#4)#5]{% + \pgfmathsetlength\pgf@x{#1}% + \edef\pgf@sys@shading@start@pos{\the\pgf@x}% + \pgf@sys@bp@correct\pgf@x% + \edef\pgf@doma{\pgf@sys@tonumber{\pgf@x}}% + \edef\pgf@prevx{\pgf@sys@tonumber{\pgf@x}}% + \pgf@getrgbtuplewithmixin{#2}{#3}{#4}% + \edef\pgf@sys@shading@start@rgb{\pgf@sys@rgb}% + \let\pgf@sys@prevcolor=\pgf@sys@shading@start@rgb% + \let\pgf@sys@prevpos=\pgf@sys@shading@start@pos% + \edef\pgf@prevcolor{\pgf@rgb}% + \edef\pgf@firstcolor{\pgf@rgb}} +\def\pgf@parselastdomrgb[rgb(#1)=(#2,#3,#4); {% + \pgfutil@ifnextchar]{% + \pgfmathsetlength\pgf@x{#1}% + \edef\pgf@sys@shading@end@pos{\the\pgf@x}% + \pgf@max=\pgf@x\relax% + \pgf@sys@bp@correct\pgf@x% + \edef\pgf@domb{\pgf@sys@tonumber{\pgf@x}}% + \pgf@getrgbtuplewithmixin{#2}{#3}{#4}% + \edef\pgf@sys@shading@end@rgb{\pgf@sys@rgb}% + \pgfutil@gobble}{\pgf@parselastdomrgb[}} +\def\pgf@parsemidrgb[rgb(#1)=(#2,#3,#4); {\pgf@parserestrgb[} +\def\pgf@parserestrgb[rgb(#1)=(#2,#3,#4); {% + \advance\pgf@sys@shading@range@num by1\relax% + \pgfutil@ifnextchar]{% + \pgf@getrgbtuplewithmixin{#2}{#3}{#4}% + \edef\pgf@singlefunc{\space% + << /FunctionType 2 /Domain [0 1] /C0 + [\pgf@prevcolor] /C1 [\pgf@rgb] /N 1 >> }% << + \edef\pgf@funcs{\pgf@funcs\space% + << /FunctionType 2 /Domain [\pgf@doma\space\pgf@domb] /C0 + [\pgf@prevcolor] /C1 [\pgf@rgb] /N 1 >> }% << + \edef\pgf@psfuncs{\pgf@prevx\space \pgf@rgb\space \pgf@prevcolor\space pgfshade \pgf@psfuncs}% + \pgfmathsetlength\pgf@x{#1}% + \edef\pgf@sys@shading@ranges{\pgf@sys@shading@ranges{{\pgf@sys@prevpos}{\the\pgf@x}{\pgf@sys@prevcolor}{\pgf@sys@rgb}}}% + \edef\pgf@sys@prevpos{\the\pgf@x}% + \let\pgf@sys@prevcolor=\pgf@sys@rgb% + \pgfutil@gobble}{% + \pgfmathsetlength\pgf@x{#1}% + \pgf@getrgbtuplewithmixin{#2}{#3}{#4}% + \edef\pgf@sys@shading@ranges{\pgf@sys@shading@ranges{{\pgf@sys@prevpos}{\the\pgf@x}{\pgf@sys@prevcolor}{\pgf@sys@rgb}}}% + \edef\pgf@sys@prevpos{\the\pgf@x}% + \let\pgf@sys@prevcolor=\pgf@sys@rgb% + \edef\pgf@psfuncs{\pgf@prevx\space \pgf@rgb\space \pgf@prevcolor\space pgfshade \pgf@psfuncs}% + \pgf@sys@bp@correct\pgf@x% + \edef\pgf@prevx{\pgf@sys@tonumber{\pgf@x}}% + \edef\pgf@bounds{\pgf@bounds\space\pgf@sys@tonumber{\pgf@x}}% + \edef\pgf@encode{\pgf@encode\space0 1}% + \edef\pgf@singlefunc{\space% + << /FunctionType 2 /Domain [0 1] /C0 + [\pgf@prevcolor] /C1 [\pgf@rgb] /N 1 >> }% << + \edef\pgf@funcs{\pgf@funcs\space% + << /FunctionType 2 /Domain [\pgf@doma\space\pgf@domb] /C0 + [\pgf@prevcolor] /C1 [\pgf@rgb] /N 1 >> }% << + \edef\pgf@prevcolor{\pgf@rgb}% + \pgf@parserestrgb[}} + +\def\pgf@getrgbtuplewithmixin#1#2#3{% + \pgfutil@definecolor{pgfshadetemp}{rgb}{#1,#2,#3}% + \pgfutil@ifundefined{applycolormixins}{}{\applycolormixins{pgfshadetemp}}% + \pgfutil@extractcolorspec{pgfshadetemp}{\pgf@tempcolor}% + \expandafter\pgfutil@convertcolorspec\pgf@tempcolor{rgb}{\pgf@rgbcolor}% + \expandafter\pgf@getrgb@@\pgf@rgbcolor!} +\def\pgf@getrgb@@#1,#2,#3!{% + \def\pgf@rgb{#1 #2 #3}% + \def\pgf@sys@rgb{{#1}{#2}{#3}}% +} + +\def\pgf@parsefirstcmyk[cmyk(#1)=(#2,#3,#4,#5)#6]{% + \pgfmathsetlength\pgf@x{#1}% + \edef\pgf@sys@shading@start@pos{\the\pgf@x}% + \pgf@sys@bp@correct\pgf@x% + \edef\pgf@doma{\pgf@sys@tonumber{\pgf@x}}% + \edef\pgf@prevx{\pgf@sys@tonumber{\pgf@x}}% + \pgf@getcmyktuplewithmixin{#2}{#3}{#4}{#5}% + \edef\pgf@sys@shading@start@cmyk{\pgf@sys@cmyk}% + \let\pgf@sys@prevcolor=\pgf@sys@shading@start@cmyk% + \let\pgf@sys@prevpos=\pgf@sys@shading@start@pos% + \edef\pgf@prevcolor{\pgf@cmyk}% + \edef\pgf@firstcolor{\pgf@cmyk}} +\def\pgf@parselastdomcmyk[cmyk(#1)=(#2,#3,#4,#5); {% + \pgfutil@ifnextchar]{% + \pgfmathsetlength\pgf@x{#1}% + \edef\pgf@sys@shading@end@pos{\the\pgf@x}% + \pgf@max=\pgf@x\relax% + \pgf@sys@bp@correct\pgf@x% + \edef\pgf@domb{\pgf@sys@tonumber{\pgf@x}}% + \pgf@getcmyktuplewithmixin{#2}{#3}{#4}{#5}% + \edef\pgf@sys@shading@end@cmyk{\pgf@sys@cmyk}% + \pgfutil@gobble}{\pgf@parselastdomcmyk[}} +\def\pgf@parsemidcmyk[cmyk(#1)=(#2,#3,#4,#5); {\pgf@parserestcmyk[} +\def\pgf@parserestcmyk[cmyk(#1)=(#2,#3,#4,#5); {% + \advance\pgf@sys@shading@range@num by1\relax% + \pgfutil@ifnextchar]{% + \pgf@getcmyktuplewithmixin{#2}{#3}{#4}{#5}% + \edef\pgf@singlefunc{\space% + << /FunctionType 2 /Domain [0 1] /C0 + [\pgf@prevcolor] /C1 [\pgf@cmyk] /N 1 >> }% << + \edef\pgf@funcs{\pgf@funcs\space% + << /FunctionType 2 /Domain [\pgf@doma\space\pgf@domb] /C0 + [\pgf@prevcolor] /C1 [\pgf@cmyk] /N 1 >> }% << + \edef\pgf@psfuncs{\pgf@prevx\space + \pgf@cmyk\space \pgf@prevcolor\space pgfshade \pgf@psfuncs}% + \pgfmathsetlength\pgf@x{#1}% + \edef\pgf@sys@shading@ranges{\pgf@sys@shading@ranges{% + {\pgf@sys@prevpos}{\the\pgf@x}{\pgf@sys@prevcolor}{\pgf@sys@cmyk}}}% + \edef\pgf@sys@prevpos{\the\pgf@x}% + \let\pgf@sys@prevcolor=\pgf@sys@cmyk% + \pgfutil@gobble}{% + \pgfmathsetlength\pgf@x{#1}% + \pgf@getcmyktuplewithmixin{#2}{#3}{#4}{#5}% + \edef\pgf@sys@shading@ranges{\pgf@sys@shading@ranges{% + {\pgf@sys@prevpos}{\the\pgf@x}{\pgf@sys@prevcolor}{\pgf@sys@cmyk}}}% + \edef\pgf@sys@prevpos{\the\pgf@x}% + \let\pgf@sys@prevcolor=\pgf@sys@cmyk% + \edef\pgf@psfuncs{\pgf@prevx\space \pgf@cmyk\space + \pgf@prevcolor\space pgfshade \pgf@psfuncs}% + \pgf@sys@bp@correct\pgf@x% + \edef\pgf@prevx{\pgf@sys@tonumber{\pgf@x}}% + \edef\pgf@bounds{\pgf@bounds\space\pgf@sys@tonumber{\pgf@x}}% + \edef\pgf@encode{\pgf@encode\space0 1}% + \edef\pgf@singlefunc{\space% + << /FunctionType 2 /Domain [0 1] /C0 + [\pgf@prevcolor] /C1 [\pgf@cmyk] /N 1 >> }% << + \edef\pgf@funcs{\pgf@funcs\space% + << /FunctionType 2 /Domain [\pgf@doma\space\pgf@domb] /C0 + [\pgf@prevcolor] /C1 [\pgf@cmyk] /N 1 >> }% << + \edef\pgf@prevcolor{\pgf@cmyk}% + \pgf@parserestcmyk[}} + +\def\pgf@getcmyktuplewithmixin#1#2#3#4{% + \pgfutil@definecolor{pgfshadetemp}{cmyk}{#1,#2,#3,#4}% + \pgfutil@ifundefined{applycolormixins}{}{\applycolormixins{pgfshadetemp}}% + \pgfutil@extractcolorspec{pgfshadetemp}{\pgf@tempcolor}% + \expandafter\pgfutil@convertcolorspec\pgf@tempcolor{cmyk}{\pgf@cmykcolor}% + \expandafter\pgf@getcmyk@@\pgf@cmykcolor!} +\def\pgf@getcmyk@@#1,#2,#3,#4!{% + \def\pgf@cmyk{#1 #2 #3 #4}% + \def\pgf@sys@cmyk{{#1}{#2}{#3}{#4}}% +} + +\def\pgf@parsefirstgray[gray(#1)=(#2)#3]{% + \pgfmathsetlength\pgf@x{#1}% + \edef\pgf@sys@shading@start@pos{\the\pgf@x}% + \pgf@sys@bp@correct\pgf@x% + \edef\pgf@doma{\pgf@sys@tonumber{\pgf@x}}% + \edef\pgf@prevx{\pgf@sys@tonumber{\pgf@x}}% + \pgf@getgraytuplewithmixin{#2}% + \edef\pgf@sys@shading@start@gray{\pgf@sys@gray}% + \let\pgf@sys@prevcolor=\pgf@sys@shading@start@gray% + \let\pgf@sys@prevpos=\pgf@sys@shading@start@pos% + \edef\pgf@prevcolor{\pgf@gray}% + \edef\pgf@firstcolor{\pgf@gray}} +\def\pgf@parselastdomgray[gray(#1)=(#2); {% + \pgfutil@ifnextchar]{% + \pgfmathsetlength\pgf@x{#1}% + \edef\pgf@sys@shading@end@pos{\the\pgf@x}% + \pgf@max=\pgf@x\relax% + \pgf@sys@bp@correct\pgf@x% + \edef\pgf@domb{\pgf@sys@tonumber{\pgf@x}}% + \pgf@getgraytuplewithmixin{#2}% + \edef\pgf@sys@shading@end@gray{\pgf@sys@gray}% + \pgfutil@gobble}{\pgf@parselastdomgray[}} +\def\pgf@parsemidgray[gray(#1)=(#2); {\pgf@parserestgray[} +\def\pgf@parserestgray[gray(#1)=(#2); {% + \advance\pgf@sys@shading@range@num by1\relax% + \pgfutil@ifnextchar]{% + \pgf@getgraytuplewithmixin{#2}% + \edef\pgf@singlefunc{\space% + << /FunctionType 2 /Domain [0 1] /C0 + [\pgf@prevcolor] /C1 [\pgf@gray] /N 1 >> }% << + \edef\pgf@funcs{\pgf@funcs\space% + << /FunctionType 2 /Domain [\pgf@doma\space\pgf@domb] /C0 + [\pgf@prevcolor] /C1 [\pgf@gray] /N 1 >> }% << + \edef\pgf@psfuncs{\pgf@prevx\space \pgf@gray\space + \pgf@prevcolor\space pgfshade \pgf@psfuncs}% + \pgfmathsetlength\pgf@x{#1}% + \edef\pgf@sys@shading@ranges{\pgf@sys@shading@ranges{% + {\pgf@sys@prevpos}{\the\pgf@x}{\pgf@sys@prevcolor}{\pgf@sys@gray}}}% + \edef\pgf@sys@prevpos{\the\pgf@x}% + \let\pgf@sys@prevcolor=\pgf@sys@gray% + \pgfutil@gobble}{% + \pgfmathsetlength\pgf@x{#1}% + \pgf@getgraytuplewithmixin{#2}% + \edef\pgf@sys@shading@ranges{\pgf@sys@shading@ranges{% + {\pgf@sys@prevpos}{\the\pgf@x}{\pgf@sys@prevcolor}{\pgf@sys@gray}}}% + \edef\pgf@sys@prevpos{\the\pgf@x}% + \let\pgf@sys@prevcolor=\pgf@sys@gray% + \edef\pgf@psfuncs{\pgf@prevx\space \pgf@gray\space + \pgf@prevcolor\space pgfshade \pgf@psfuncs}% + \pgf@sys@bp@correct\pgf@x% + \edef\pgf@prevx{\pgf@sys@tonumber{\pgf@x}}% + \edef\pgf@bounds{\pgf@bounds\space\pgf@sys@tonumber{\pgf@x}}% + \edef\pgf@encode{\pgf@encode\space0 1}% + \edef\pgf@singlefunc{\space% + << /FunctionType 2 /Domain [0 1] /C0 + [\pgf@prevcolor] /C1 [\pgf@gray] /N 1 >> }% << + \edef\pgf@funcs{\pgf@funcs\space% + << /FunctionType 2 /Domain [\pgf@doma\space\pgf@domb] /C0 + [\pgf@prevcolor] /C1 [\pgf@gray] /N 1 >> }% << + \edef\pgf@prevcolor{\pgf@gray}% + \pgf@parserestgray[}} + +\def\pgf@getgraytuplewithmixin#1{% + \pgfutil@definecolor{pgfshadetemp}{gray}{#1}% + \pgfutil@ifundefined{applycolormixins}{}{\applycolormixins{pgfshadetemp}}% + \pgfutil@extractcolorspec{pgfshadetemp}{\pgf@tempcolor}% + \expandafter\pgfutil@convertcolorspec\pgf@tempcolor{gray}{\pgf@graycolor}% + \expandafter\pgf@getgray@@\pgf@graycolor!} +\def\pgf@getgray@@#1!{% + \def\pgf@gray{#1}% + \def\pgf@sys@gray{{#1}}% +} + +% Normalized a <color specification> argument for shadings into a +% series of color specifications in the current xcolor color model and write +% the result into \pgf@conv. +% +% Example: +% \pgf@convertstring{rgb(0cm)=(1,0,0); rgb(2cm)=(0,1,0); cmyk(4cm)=(1,0,0,0); gray(1cm)=(3); color(2cm)=(green); } +% -> +% \pgf@conv = macro:->'rgb(0cm)=(1,0,0); rgb(2cm)=(0,1,0); rgb(4cm)=(0,1,1); rgb(1cm)=(3,3,3); rgb(2cm)=(0,1,0); ' +\def\pgf@convertstring#1{% + \def\pgf@conv{}% + \pgf@convert#1]% + } +\def\pgf@convert{% + \pgfutil@ifnextchar]{\pgfutil@gobble}%done! + {% + \pgfutil@ifnextchar;{\pgf@grabsemicolor}% + {% + \pgfutil@ifnextchar c{\pgf@gobblec}% + {% + \pgfutil@ifnextchar g{\pgf@grabgray}% + {% + \pgfutil@ifnextchar o{\pgf@grabcolor}% + {% + \pgfutil@ifnextchar m{\pgf@grabcmyk}% + {% + \pgfutil@ifnextchar r{\pgf@grabrgb}% + {\pgferror{Illformed shading + specification}\pgf@convert}% + }% + }% + }% + }% + }% + }% +} +\def\pgf@savecolor#1{% + \pgfutil@extractcolorspec{pgf@tempcol}{\pgf@tempcolor}% + \expandafter\pgfutil@convertcolorspec\pgf@tempcolor + {\pgf@shading@model}{\pgf@color}% + \expandafter\pgf@convget@\expandafter{\pgf@color}{#1}% +} +\def\pgf@grabsemicolor;{% + \edef\pgf@conv{\pgf@conv; }\pgf@convert} +\def\pgf@gobblec c{\pgf@convert} +\def\pgf@grabrgb rgb(#1)=(#2,#3,#4){% + \pgfutil@definecolor{pgf@tempcol}{rgb}{#2,#3,#4}% + \pgf@savecolor{#1}% +} +\def\pgf@grabcmyk myk(#1)=(#2,#3,#4,#5){% + \pgfutil@definecolor{pgf@tempcol}{cmyk}{#2,#3,#4,#5}% + \pgf@savecolor{#1}% +} +\def\pgf@grabgray gray(#1)=(#2){% + \pgfutil@definecolor{pgf@tempcol}{gray}{#2}% + \pgf@savecolor{#1}% +} +\def\pgf@grabcolor olor(#1)=(#2){% + \pgfutil@colorlet{pgf@tempcol}{#2}% + \pgf@savecolor{#1}% +} +\def\pgf@convget@#1#2{% + \edef\pgf@conv{\pgf@conv \pgf@shading@model(#2)=(#1)}\pgf@convert} + + +\newcount\pgf@shadingcount +\pgf@shadingcount=0 +{ + \catcode`\/=0 + \catcode`\\=12 + /gdef/pgf@shadingnum{\/the/pgf@shadingcount\} +} + +% Set up shading properties based on the current xcolor color model. This is +% called when shadings are declared and used. \ifpgfshadingmodelrgb, +% \ifpgfshadingmodelcmyk, and \ifpgfshadingmodelgray are set so that the type +% 4 function in functional shadings can be converted to the current color +% model. See \pgffuncshading*to* macros. + +\newif\ifpgfshadingmodelrgb +\newif\ifpgfshadingmodelcmyk +\newif\ifpgfshadingmodelgray +\def\pgf@setup@shading@model{% + \pgfshadingmodelrgbtrue + \pgfshadingmodelcmykfalse + \pgfshadingmodelgrayfalse + \XC@sdef\pgf@mod@test{\XC@tgt@mod{natural}}% + \def\pgf@shading@device{/DeviceRGB}% + \def\pgf@shading@ps@device{setrgbcolor}% + \def\pgf@shading@functional@range{0 1 0 1 0 1}% + \def\pgf@shading@model{rgb}% + \ifx\pgf@mod@test\XC@mod@cmyk + \def\pgf@shading@device{/DeviceCMYK}% + \def\pgf@shading@ps@device{setcmykcolor}% + \def\pgf@shading@functional@range{0 1 0 1 0 1 0 1}% + \def\pgf@shading@model{cmyk}% + \pgfshadingmodelrgbfalse + \pgfshadingmodelcmyktrue + \fi + \ifx\pgf@mod@test\XC@mod@gray + \def\pgf@shading@device{/DeviceGray}% + \def\pgf@shading@ps@device{setgray}% + \def\pgf@shading@functional@range{0 1}% + \def\pgf@shading@model{gray}% + \pgfshadingmodelrgbfalse + \pgfshadingmodelgraytrue + \fi + \edef\pgf@sys@driver@dvisvgm{pgfsys-dvisvgm.def}% + \ifx\pgfsysdriver\pgf@sys@driver@dvisvgm + \def\pgf@shading@model{rgb}% + \fi + \edef\pgf@sys@driver@texforht{pgfsys-tex4ht.def}% + \ifx\pgfsysdriver\pgf@sys@driver@texforht + \def\pgf@shading@model{rgb}% + \fi +} + + +% Declares a horizontal shading for later use. The shading is a +% horizontal bar that changes its color. +% +% #1 = optional dependencies +% #2 = name of the shading for later use +% #3 = height of the shading +% #4 = color specification in the following format: A list of colors +% that the bar should have at certain points. If the bar should +% be red at 1cm, this is specified as +% "rgb(1cm)=(1,0,0)". Multiple specifications are separated by a +% semicolon and a space. At least two specifications must be +% given. The specified positions must be given in increasing +% order. +% +% Description: +% +% The optional dependencies have the following effect: If present, it +% should consist of a list of colors, separated by commas. Each time +% the shading is used, these colors will be reevaluated. It will be +% checked whether the colors still have their "original meaning". If +% the colors have changed, a new shading will be created internally to +% reflect the changed color's values. +% +% Example: +% +% \pgfdeclarehorizontalshading{redtogreentoblue}{1cm}{% +% rgb(0cm)=(1,0,0); % red +% rgb(1cm)=(0,1,0); % green +% rgb(2cm)=(0,0,1)} +% +% \begin{document} +% The following bar is 2cm long: \pgfuseshading{redtogreentoblue}. +% \end{document} + +\def\pgfdeclarehorizontalshading{% + \pgf@setup@shading@model + \pgfutil@ifnextchar[% + \pgf@declarehorizontalshading{\pgf@declarehorizontalshading[]}} +\def\pgf@declarehorizontalshading[#1]#2#3#4{% + \expandafter\def\csname pgf@deps@pgfshading#2!\endcsname{#1}% + \expandafter\ifx\csname pgf@deps@pgfshading#2!\endcsname\pgfutil@empty% + \global\expandafter\let\csname pgf@num@pgfshading#2!\endcsname\pgfutil@empty + \pgfsys@horishading{#2}{#3}{#4}% + \else% + \global\advance\pgf@shadingcount 1\relax + \global\expandafter\edef\csname pgf@num@pgfshading#2!\endcsname{\pgf@shadingnum}% + \expandafter\def\csname pgf@func@pgfshading#2!\endcsname{\pgfsys@horishading}% + \expandafter\def\csname pgf@args@pgfshading#2!\endcsname{{#3}{#4}}% + \expandafter\let\csname @pgfshading#2!\endcsname=\pgfutil@empty% + \fi} + + +% Declares a vertical shading for later use. +% +% #1 = optional dependencies +% #2 = name of the shading for later use +% #3 = height of the shading +% #4 = color specification +% +% Example: +% +% \pgfdeclareverticalshading{redtogreentoblue}{1cm}{% +% rgb(0cm)=(1,0,0); % red +% rgb(1cm)=(0,1,0); % green +% rgb(2cm)=(0,0,1)} +% +% \begin{document} +% The following bar is 2cm high: \pgfuseshading{redtogreentoblue}. +% \end{document} + +\def\pgfdeclareverticalshading{% + \pgf@setup@shading@model + \pgfutil@ifnextchar[% + \pgf@declareverticalshading{\pgf@declareverticalshading[]}} +\def\pgf@declareverticalshading[#1]#2#3#4{% + \expandafter\def\csname pgf@deps@pgfshading#2!\endcsname{#1}% + \expandafter\ifx\csname pgf@deps@pgfshading#2!\endcsname\pgfutil@empty% + \global\expandafter\let\csname pgf@num@pgfshading#2!\endcsname=\pgfutil@empty + \pgfsys@vertshading{#2}{#3}{#4}% + \else% + \global\advance\pgf@shadingcount 1\relax + \global\expandafter\edef\csname pgf@num@pgfshading#2!\endcsname{\pgf@shadingnum}% + \expandafter\def\csname pgf@func@pgfshading#2!\endcsname{\pgfsys@vertshading}% + \expandafter\def\csname pgf@args@pgfshading#2!\endcsname{{#3}{#4}}% + \expandafter\let\csname @pgfshading#2!\endcsname=\pgfutil@empty% + \fi} + + +% Declares a radial shading for later use. +% +% #1 = optional dependencies +% #2 = name of the shading for later use +% #3 = center of inner circle +% #4 = color specification +% +% Description: +% +% A radial shading creates a smooth color transition between two +% circles. The center of the inner circle is at the give position. Its +% radius is the start of the color specification. The +% center of the outer circle is at the center of the whole shading, +% whose radius is the end of the color specification. For example, +% suppose the color specification is "rgb(1cm)=(1,1,1); rgb(2cm)=(0,0,0)". +% Then the shading would be 4cm times 4cm large. The inner circle would +% have diameter 1cm and the outer circle would have diameter 2cm. The +% outer circle would be centered in the middle of the shading, whereas +% the outer circle would be centered at the given position. +% +% Example: +% +% \pgfdeclareradialshading{redtogreentoblue}{\pgfpoint{2cm}{2cm}}{% +% rgb(10pt)=(1,0,0); % red +% rgb(2cm)=(0,1,0); % green +% rgb(3cm)=(0,0,1)} +% +% \begin{document} +% The following ball has diameter 3cm: \pgfuseshading{redtogreentoblue}. +% \end{document} + +\def\pgfdeclareradialshading{% + \pgf@setup@shading@model + \pgfutil@ifnextchar[% + \pgf@declareradialshading{\pgf@declareradialshading[]}} +\def\pgf@declareradialshading[#1]#2#3#4{% + \expandafter\def\csname pgf@deps@pgfshading#2!\endcsname{#1}% + \expandafter\ifx\csname pgf@deps@pgfshading#2!\endcsname\pgfutil@empty% + \global\expandafter\let\csname pgf@num@pgfshading#2!\endcsname=\pgfutil@empty + \pgfsys@radialshading{#2}{#3}{#4}% + \else% + \global\advance\pgf@shadingcount 1\relax + \global\expandafter\edef\csname pgf@num@pgfshading#2!\endcsname{\pgf@shadingnum}% + \expandafter\def\csname pgf@func@pgfshading#2!\endcsname{\pgfsys@radialshading}% + \expandafter\def\csname pgf@args@pgfshading#2!\endcsname{{#3}{#4}}% + \expandafter\let\csname @pgfshading#2!\endcsname=\pgfutil@empty% + \fi} + + + + +% Declares a functional shading for later use. +% +% #1 = optional dependencies +% #2 = name of the shading for later use +% #3 = lower left corner of the shading as a pgfpoint. +% #4 = upper right corner of the shading as a pgfpoint. +% #5 = Preparation code +% #6 = a PDF type 4 function (restricted Postscript function), see the +% PDF-specification 1.7, section 3.9.4 +% +% Description: +% +% This command creates a so-called functional shading. For such a +% shading the color of each point is calculated by calling a function +% for each point that gets the coordinates as input and yields the +% color as an output. Note that the function is evaluated by the +% *renderer*, not by PGF or TeX or someone else at compile-time. This +% means that the evaluation of this function has to be done *extremely +% quickly* and the function should be *very simple*. For this reason, +% only a very restricted set of operations are possible in the +% function (see 3.9.4 of the PDF-spec 1.7). Also functions should be +% kept small. Any errors in the function will only be noticed by the +% renderer. +% +% The function gets the coordinates of a point as input (as bp). This +% input consists of the top two elements of an otherwise empty +% (virtual, PostScript) stack. The function should then replace these +% two values by one value representing the gray color of the point for a +% grayscale shading, three values, representing the red, green, and blue color +% of the point for an RGB shading, or four values, representing the cyan, +% magenta, yellow, and black color of the point for a CMYK shading. The +% numbers should be real values, not integers since Apple's PDF renderer is +% broken in this regard (use cvr at the end if necessary). +% +% Conceptually, the function will be evaluated once for each point of +% the rectangle (#3) to (#4). A renderer may choose to evaluate the +% function at less points, but, in principle, the function will be +% evaluated for each pixel independently. +% +% Because of the rather difficult PostScript syntax, use this macro +% only *if you know what you are doing* (or if you are adventurous, of +% course). +% +% As for other shadings, the optional dependencies argument is used to +% determine whether a shading needs to be recalculated when a color +% has changed. +% +% The code #5 is executed each time a shading is +% (re)calculated. Typically, it will contain code to extract +% coordinates from colors (see below). +% +% Inside the PostScript function #6 you cannot use colors +% directly. Rather, you must push the color components on the +% stack. For this, it is useful to call \pgfshadecolortorgb, +% \pgfshadecolortocmyk, or \pgfshadecolortogray in the startup +% code #4. The macro takes a color name as input and stores the color's +% component real numbers between 0.0 and 1.0 separated +% by spaces (which is exactly what you need if you want to push it on +% a stack) in a macro. +% +% Example: +% +%\pgfdeclarefunctionalshading{twospots}{\pgfpointorigin}{\pgfpoint{200bp}{200bp}}{}{ +% 2 copy +% 90 sub dup mul exch +% 80 sub dup mul add sqrt +% dup mul neg 1.0005 exch exp 1.0 exch sub +% 3 1 roll +% 120 sub dup mul exch +% 100 sub dup mul add sqrt +% dup mul neg 1.002 exch exp 1.0 exch sub +% 1.0 +%} +% +% \pgfdeclarefunctionalshading[mycol]{sweep}{\pgfpointorigin}{\pgfpoint{100bp}{100bp}} +% {\pgfshadecolortorgb{mycol}{\myrgb}}{ +% add 150 div % not very useful... +% dup +% \myrgb % push mycol +% 5 4 roll % multiply all components by calculated value +% mul +% 3 1 roll +% 3 index +% mul +% 3 1 roll +% 4 3 roll +% mul +% 3 1 roll +% } +% +% \begin{document} +% Have a look at this: \pgfuseshading{twospots}. +% Here is \colorlet{mycol}{green!50}\pgfuseshading{sweep} in green +% and in \colorlet{mycol}{red!50!blue}\pgfuseshading{sweep} in red/blue. +% \end{document} + +\def\pgfdeclarefunctionalshading{% + \pgf@setup@shading@model + \pgfutil@ifnextchar[% + \pgf@declarefunctionalshading{\pgf@declarefunctionalshading[]}} +\def\pgf@declarefunctionalshading[#1]#2#3#4#5#6{% + \expandafter\def\csname pgf@deps@pgfshading#2!\endcsname{#1}% + \expandafter\ifx\csname pgf@deps@pgfshading#2!\endcsname\pgfutil@empty% + \global\expandafter\let\csname pgf@num@pgfshading#2!\endcsname=\pgfutil@empty + \pgfshade@functionaldo{#2}{#3}{#4}{#5}{#6}% + \else% + \global\advance\pgf@shadingcount 1\relax + \global\expandafter\edef\csname pgf@num@pgfshading#2!\endcsname{\pgf@shadingnum}% + \expandafter\def\csname pgf@func@pgfshading#2!\endcsname{\pgfshade@functionaldo}% + \expandafter\def\csname pgf@args@pgfshading#2!\endcsname{{#3}{#4}{#5}{#6}}% + \expandafter\let\csname @pgfshading#2!\endcsname=\pgfutil@empty% + \fi} +\def\pgfshade@functionaldo#1#2#3#4#5{% + \begingroup + #4% + \pgfsys@functionalshading{#1}{#2}{#3}{#5}% + \expandafter\pgfmath@smuggleone\csname @pgfshading#1!\endcsname + \endgroup +} + +\def\pgfshadecolortorgb#1#2{% + \pgfutil@colorlet{pgf@tempcol}{#1}% + \pgfutil@extractcolorspec{pgf@tempcol}{\pgf@tempcolor}% + \expandafter\pgfutil@convertcolorspec\pgf@tempcolor{rgb}{\pgf@rgbcolor}% + \expandafter\pgfshading@rgb\pgf@rgbcolor\relax% + \edef#2{\pgf@sys@tonumber{\pgf@xa}\space\pgf@sys@tonumber{\pgf@xb}\space\pgf@sys@tonumber{\pgf@xc}\space}% + \c@pgf@counta\escapechar% + \escapechar-1\relax% + \expandafter\edef\csname\string#2red\endcsname{\pgf@sys@tonumber{\pgf@xa}\space}% + \expandafter\edef\csname\string#2green\endcsname{\pgf@sys@tonumber{\pgf@xb}\space}% + \expandafter\edef\csname\string#2blue\endcsname{\pgf@sys@tonumber{\pgf@xc}\space}% + \escapechar\c@pgf@counta% +} +\def\pgfshading@rgb#1,#2,#3\relax{% + \pgf@xa=#1pt% + \pgf@xb=#2pt% + \pgf@xc=#3pt% +} + +\def\pgfshadecolortocmyk#1#2{% + \pgfutil@colorlet{pgf@tempcol}{#1}% + \pgfutil@extractcolorspec{pgf@tempcol}{\pgf@tempcolor}% + \expandafter\pgfutil@convertcolorspec\pgf@tempcolor{cmyk}{\pgf@cmykcolor}% + \expandafter\pgfshading@cmyk\pgf@cmykcolor\relax% + \edef#2{\pgf@sys@tonumber{\pgf@xa}\space\pgf@sys@tonumber{\pgf@xb}\space + \pgf@sys@tonumber{\pgf@xc}\space\pgf@sys@tonumber{\pgf@xd}\space}% + \c@pgf@counta\escapechar% + \escapechar-1\relax% + \expandafter\edef\csname\string#2cyan\endcsname{% + \pgf@sys@tonumber{\pgf@xa}\space}% + \expandafter\edef\csname\string#2magenta\endcsname{% + \pgf@sys@tonumber{\pgf@xb}\space}% + \expandafter\edef\csname\string#2yellow\endcsname{% + \pgf@sys@tonumber{\pgf@xc}\space}% + \expandafter\edef\csname\string#2black\endcsname{% + \pgf@sys@tonumber{\pgf@xd}\space}% + \escapechar\c@pgf@counta +} +\def\pgfshading@cmyk#1,#2,#3,#4\relax{% + \pgf@xa=#1pt% + \pgf@xb=#2pt% + \pgf@xc=#3pt% + \pgf@xd=#4pt% +} + +\def\pgfshadecolortogray#1#2{% + \pgfutil@colorlet{pgf@tempcol}{#1}% + \pgfutil@extractcolorspec{pgf@tempcol}{\pgf@tempcolor}% + \expandafter\pgfutil@convertcolorspec\pgf@tempcolor{gray}{\pgf@graycolor}% + \expandafter\pgfshading@gray\pgf@graycolor\relax + \edef#2{\pgf@sys@tonumber{\pgf@xa}\space}% + \c@pgf@counta\escapechar + \escapechar-1\relax + \expandafter\edef\csname\string#2gray\endcsname{% + \pgf@sys@tonumber{\pgf@xa}\space}% + \escapechar\c@pgf@counta +} +\def\pgfshading@gray#1\relax{% + \pgf@xa=#1pt% +} + +% Functions to convert between color models in the type 4 PostScript data of +% functional shadings. + +\def\pgffuncshadingrgbtocmyk{% + 1.0 exch sub 3 1 roll + 1.0 exch sub 3 1 roll + 1.0 exch sub 3 1 roll + 3 copy + 2 copy gt { exch } if pop + 2 copy gt { exch } if pop + dup 3 1 roll sub + 0.0 2 copy lt { exch } if pop + 1.0 2 copy gt { exch } if pop + 4 1 roll + dup 3 1 roll sub + 0.0 2 copy lt { exch } if pop + 1.0 2 copy gt { exch } if pop + 4 1 roll + dup 3 1 roll sub + 0.0 2 copy lt { exch } if pop + 1.0 2 copy gt { exch } if pop + 4 1 roll +} + +\def\pgffuncshadingrgbtogray{% + 0.11 mul exch 0.59 mul add exch 0.3 mul add +} + +\def\pgffuncshadingcmyktorgb{% + % covert to CMY + dup 3 1 roll add + 1.0 2 copy gt { exch } if pop + 4 1 roll + dup 3 1 roll add + 1.0 2 copy gt { exch } if pop + 4 1 roll + add + 1.0 2 copy gt { exch } if pop + 3 1 roll + % covert to RGB + 1.0 exch sub + 3 1 roll + 1.0 exch sub + 3 1 roll + 1.0 exch sub + 3 1 roll +} + +\def\pgffuncshadingcmyktogray{% + exch 0.11 mul add exch 0.59 mul add exch 0.3 mul add + 1.0 2 copy gt { exch } if pop + 1.0 exch sub +} + +\def\pgffuncshadinggraytorgb{% + dup dup +} + +\def\pgffuncshadinggraytocmyk{% + 0.0 0.0 0.0 + 4 3 roll +} + +% Inserts a box into the text that contains a previously defined +% shading. +% +% #1 = Name of a shading +% +% Example: +% +% \pgfuseshading{redtogreentoblue} + +\def\pgfuseshading#1{% + \edef\pgf@shadingname{@pgfshading#1}% + \pgf@tryextensions{\pgf@shadingname}{\pgfalternateextension}% + \expandafter\pgfutil@ifundefined\expandafter{\pgf@shadingname}% + {\pgferror{Undefined shading "#1"}}% + {% + \edef\pgf@shade@adds{\csname pgf@num\pgf@shadingname\endcsname}% + \pgfutil@ifundefined{pgf@deps\pgf@shadingname}% + {}% + {% + \pgf@setup@shading@model + \begingroup + \pgfutil@globalcolorsfalse + \edef\@list{\csname pgf@deps\pgf@shadingname\endcsname}% + \pgfutil@for\@temp:=\@list\do{% + \pgfutil@ifundefined{applycolormixins}{}{\applycolormixins{\@temp}}% + \pgfutil@extractcolorspec{\@temp}{\pgf@tempcolor}% + \expandafter\pgfutil@convertcolorspec\pgf@tempcolor{\pgf@shading@model}{\pgf@color}% + \edef\pgf@shade@adds{\pgf@shade@adds,\pgf@color}% + }% + \pgfmath@smuggleone\pgf@shade@adds + \endgroup + }% + \expandafter\pgf@strip@shadename\pgf@shadingname!!% + \edef\pgf@shadingxname{@pgfshading\pgf@basename\pgf@shade@adds!}% + \pgfutil@ifundefined{\pgf@shadingxname}% + {% + \begingroup + \edef\@temp{\expandafter\noexpand\csname pgf@func\pgf@shadingname\endcsname}% + \edef\@args{{\pgf@basename\pgf@shade@adds}}% + \expandafter\expandafter\expandafter\def + \expandafter\expandafter\expandafter\@@args + \expandafter\expandafter\expandafter{\csname pgf@args\pgf@shadingname\endcsname}% + \expandafter\expandafter\expandafter\@temp\expandafter\@args\@@args + \expandafter\pgfmath@smuggleone\csname\pgf@shadingxname\endcsname + \endgroup + }% + {}% + \pgf@invokeshading{\csname\pgf@shadingxname\endcsname}% + }% +} + +\def\pgf@strip@shadename @pgfshading#1!!!{\def\pgf@basename{#1}} + +\def\pgf@invokeshading#1{% + \ifpgfpicture% + \pgfsys@shadinginsidepgfpicture{#1}% + \else% + \pgfsys@shadingoutsidepgfpicture{#1}% + \fi% +} + + +% Create an alias name for a shading +% +% #1 = name of the alias +% #2 = name of the original +% +% Example: +% +% \pgfaliasshading{shading!25}{shadingshaded} + +\def\pgfaliasshading#1#2{% + \expandafter\let\expandafter\pgf@temp\expandafter=\csname @pgfshading#2!\endcsname% + \expandafter\let\csname @pgfshading#1!\endcsname=\pgf@temp% + \expandafter\let\expandafter\pgf@temp\expandafter=\csname pgf@num@pgfshading#2!\endcsname% + \expandafter\let\csname pgf@num@pgfshading#1!\endcsname=\pgf@temp% + \expandafter\let\expandafter\pgf@temp\expandafter=\csname pgf@deps@pgfshading#2!\endcsname% + \expandafter\let\csname pgf@deps@pgfshading#1!\endcsname=\pgf@temp% + \expandafter\let\expandafter\pgf@temp\expandafter=\csname pgf@func@pgfshading#2!\endcsname% + \expandafter\let\csname pgf@func@pgfshading#1!\endcsname=\pgf@temp% + \expandafter\let\expandafter\pgf@temp\expandafter=\csname pgf@args@pgfshading#2!\endcsname% + \expandafter\let\csname pgf@args@pgfshading#1!\endcsname=\pgf@temp% +} + + + + +% Shades the current path, but does not discard it. +% +% #1 - a shading (see below) +% #2 - an angle +% +% Description: +% +% \pgfshadepath ``tries'' to fill the +% current path with a shading. The shading's original size should +% completely cover the area between (0,0) and (100bp,100bp). The +% shading will be rotated by #2 and then rescaled so that it +% completely covers the path. Then the path will be used (locally) for +% clipping and the shading is drawn. +% +% In addition to the rotation, any transformation set by the +%\pgfsetadditionalshadetransform will also be applied. +% +% After all this, the path can still be used for the normal +% stroking/clipping operations. +% +% The shading is rotated around its middle. If no rotation occurs, the +% lower left corner of the path will lie on (25bp, 25bp), the upper +% right corner on (75bp, 75bp). +% +% Example: +% +% \pgfdeclareverticalshading{myshading}{100bp}{color(0pt)=(red); color(100bp)=(green)} +% +% \pgfpathmoveto{\pgforigin} +% \pgfpathlineto{\pgfxy(1,0)} +% \pgfpathlineto{\pgfxy(1,1)} +% \pgfshadepath{myshading}{0} +% \pgfusepath{stroke} + +\def\pgfshadepath#1#2{% + \ifdim\pgf@pathminx=16000pt% + \pgfwarning{No path specified that can be filled}% + \else% + \begingroup% + % Calculate center: + \pgf@xb=.5\pgf@pathmaxx% + \advance\pgf@xb by.5\pgf@pathminx% + \pgf@yb=.5\pgf@pathmaxy% + \advance\pgf@yb by.5\pgf@pathminy% + % Calculate rotation: + \pgfmathparse{#2}% + \let\pgfshade@angle=\pgfmathresult + \pgfmathsin@\pgfshade@angle + \let\pgfshade@sin=\pgfmathresult + \pgfmathcos@\pgfshade@angle + \let\pgfshade@cos=\pgfmathresult + % width and height of the bounding box + \pgf@xa=\pgf@pathmaxx + \advance\pgf@xa by-\pgf@pathminx + \pgf@ya=\pgf@pathmaxy + \advance\pgf@ya by-\pgf@pathminy + % Calculate scaling: + % xscale = 1pt/50bp * (w*|cos(a)|+h*|sin(a)|)/(|cos(a)|+|sin(a)|) + % yscale = 1pt/50bp * (w*|sin(a)|+h*|cos(a)|)/(|cos(a)|+|sin(a)|) + % 1pt/50bp = .01992528 + \pgfmathabs@\pgfshade@sin + \let\pgfshade@abssin=\pgfmathresult + \pgfmathabs@\pgfshade@cos + \let\pgfshade@abscos=\pgfmathresult + \pgf@xc=\pgfshade@abscos\pgf@xa + \advance\pgf@xc by\pgfshade@abssin\pgf@ya + \pgf@yc=\pgfshade@abssin\pgf@xa + \advance\pgf@yc by\pgfshade@abscos\pgf@ya + \pgfmathadd@\pgfshade@abscos\pgfshade@abssin + \pgfmathdivide@{.01992528}{\pgfmathresult}% + \pgf@xc=\pgfmathresult\pgf@xc + \pgf@yc=\pgfmathresult\pgf@yc + \ifdim\pgf@xc<0.0001pt + \ifdim\pgf@xc>-0.0001pt + \pgf@no@shadetrue + \fi + \fi + \ifdim\pgf@yc<0.0001pt + \ifdim\pgf@yc>-0.0001pt + \pgf@no@shadetrue + \fi + \fi + \ifpgf@no@shade\else + \pgfsys@beginscope + \pgfsyssoftpath@invokecurrentpath + \pgfsys@clipnext + \pgfsys@discardpath + % Compute new transformation matrix: + % shift + \pgfsys@transformcm{1}{0}{0}{1}{\the\pgf@xb}{\the\pgf@yb}% + % rotation + \pgf@x=\pgfshade@sin pt% + \pgf@xa=-\pgf@x% + \pgfsys@transformcm{\pgfshade@cos}{\pgfshade@sin}{\pgf@sys@tonumber{\pgf@xa}}{\pgfshade@cos}{0pt}{0pt}% + % scaling + \pgfsys@transformcm{\pgf@sys@tonumber{\pgf@xc}}{0}{0}{\pgf@sys@tonumber{\pgf@yc}}{0pt}{0pt}% + % This will actually be the first transformation of the shading. + % Should it be applied first so that it becomes the last one? + \ifx\pgf@shade@extra@transform\pgfutil@empty% + \else% + \pgflowlevel{\pgf@shade@extra@transform}% + \fi% + \pgfuseshading{#1}% + \pgfsys@endscope% + \fi% + \endgroup% + \fi% +} + +\newif\ifpgf@no@shade + +% Additionally transform shade paths +% +% #1 = Transformation code that is used in addition to the normal +% shading transformation. +% +% Example: +% +% \pgfsetadditionalshadetransform{\pgftransformrotate{30}} + +\def\pgfsetadditionalshadetransform#1{\def\pgf@shade@extra@transform{#1}} +\let\pgf@shade@extra@transform=\pgfutil@empty + + + + + +\endinput diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcoretransformations.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcoretransformations.code.tex new file mode 100644 index 0000000000..be252065c1 --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcoretransformations.code.tex @@ -0,0 +1,819 @@ +% Copyright 2018 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{pgfcoretransformations.code.tex} + + +% Position transformations + +\newdimen\pgf@pt@x +\newdimen\pgf@pt@y + +\newdimen\pgf@pt@temp + +\newif\ifpgf@pt@identity +\pgf@pt@identitytrue + +\def\pgf@pt@aa{1.0} \def\pgf@pt@ab{0.0} +\def\pgf@pt@ba{0.0} \def\pgf@pt@bb{1.0} + + + +% Store the current transformation matrix in a macro. +% +% #1 = macro name +% +% Example: +% +% \pgfgettransform\mytransform + +\def\pgfgettransform#1{% + \edef#1{{\pgf@pt@aa}{\pgf@pt@ab}{\pgf@pt@ba}{\pgf@pt@bb}{\the\pgf@pt@x}{\the\pgf@pt@y}}% +} + +% Store the current transformation matrix in a set of macros, one for +% each single entry. +% +% #1-#4 are macro which store the matrix entries (0,0), (0,1), (1,0), +% (1,1) (in this order). It is the same order as for \pgftransformcm. +% +% #5 is a macro which will be filled with the x shift and +% #6 is a macro which will be filled with the y shift. +% +% Example: +% \pgfgettransformentries\aa\ab\ba\bb\shiftx\shifty +% +% -> +% +% \pgftransformcm\aa\ab\ba\bb{\pgfqpoint{\shiftx}{\shifty}} +% +% or +% +% \pgfsettransformentries\aa\ab\ba\bb\shiftx\shifty +\def\pgfgettransformentries#1#2#3#4#5#6{% + \edef#1{\pgf@pt@aa}% + \edef#2{\pgf@pt@ab}% attention: this is (1,0), i.e. the point which is usually labelled 'ba'! + \edef#3{\pgf@pt@ba}% attention: this is (0,1), i.e. the point which is usually labelled 'ab'! + \edef#4{\pgf@pt@bb}% + \edef#5{\the\pgf@pt@x}% + \edef#6{\the\pgf@pt@y}% +}% +\def\pgfsettransformentries#1#2#3#4#5#6{% + \pgfsettransform{{#1}{#2}{#3}{#4}{#5}{#6}}% +}% + +% Restore the current transformation matrix from a macro. +% +% #1 = macro name, previously used with \pgfgettransform +% +% Example: +% +% \pgfsettransform\mytransform + +\def\pgfsettransform#1{% + \edef\pgf@temp{#1}% + \expandafter\pgf@settransform\pgf@temp% +} +\def\pgf@settransform#1#2#3#4#5#6{% + \def\pgf@pt@aa{#1}% + \def\pgf@pt@ab{#2}% + \def\pgf@pt@ba{#3}% + \def\pgf@pt@bb{#4}% + \pgf@pt@x=#5% + \pgf@pt@y=#6% + \edef\pgf@idtest{#1,#2,#3,#4}% + \ifx\pgf@idtest\pgf@idmatrixtext% + \pgf@pt@identitytrue% + \else% + \pgf@pt@identityfalse% + \fi% +} + +\def\pgf@idmatrixtext{1.0,0.0,0.0,1.0} +\def\pgf@zerozerotext{0.0,0.0} +\def\pgf@one@text{1.0} +\def\pgf@zero@text{0.0} + +% Transformation command +% +% #1 = x dimension +% #2 = y dimension +% +% Description: +% +% Applies the pgfs transformation matrix to the point (#1,#2). The +% result is once more stored in the point. +% +% +% Example: +% +% \pgf@pos@transform{\pgf@x}{\pgf@y} + +\def\pgf@pos@transform#1#2{% + \ifpgf@pt@identity% + \else% + \pgf@pt@temp=#1% + #1=\pgf@pt@aa#1% + \advance#1 by\pgf@pt@ba#2% + #2=\pgf@pt@bb#2% + \advance#2 by\pgf@pt@ab\pgf@pt@temp% + \fi% + \advance#1 by\pgf@pt@x% + \advance#2 by\pgf@pt@y% +} +\def\pgf@pos@transform@glob{% + \ifpgf@pt@identity% + \else% + \pgf@pt@temp=\pgf@x% + \global\pgf@x=\pgf@pt@aa\pgf@x% + \global\advance\pgf@x by\pgf@pt@ba\pgf@y% + \global\pgf@y=\pgf@pt@bb\pgf@y% + \global\advance\pgf@y by\pgf@pt@ab\pgf@pt@temp% + \fi% + \global\advance\pgf@x by\pgf@pt@x% + \global\advance\pgf@y by\pgf@pt@y% +} + + +% Invert the current transformation matrix +% +% Description: +% +% This command replaces the current transformation matrix by its +% inverse. The inversion is not very exact if the matrix is nearly +% singular. +% +% Example: +% +% \pgftransforminvert + +\def\pgftransforminvert{% + % First, invert the shift. That's easy + \pgf@pt@x=-\pgf@pt@x + \pgf@pt@y=-\pgf@pt@y + \ifpgf@pt@identity% + \else% + % Sigh. Have to calculate the inverse of the matrix. + % Perhaps we are lucky and ba and bb are zero? + \edef\pgf@zerotest{\pgf@pt@ab,\pgf@pt@ba}% + \ifx\pgf@zerotest\pgf@zerozerotext% + % Ha! Just invert aa and bb + \pgfmathreciprocal@{\pgf@pt@aa}% + \let\pgf@pt@aa\pgfmathresult% + \pgfmathreciprocal@{\pgf@pt@bb}% + \let\pgf@pt@bb\pgfmathresult% + \else% + % Start with determinant + % Matrix = (aa ab + % ba bb) + {% + \pgfutil@tempdima=\pgf@pt@aa pt% + \pgfutil@tempdima=\pgf@pt@bb\pgfutil@tempdima% aa * bb + \pgfutil@tempdimb=\pgf@pt@ba pt% + \pgfutil@tempdimb=\pgf@pt@ab\pgfutil@tempdimb% ba * ab + \advance\pgfutil@tempdima by -\pgfutil@tempdimb% aa*bb - ba*ab + % Invert + \pgfmathreciprocal@{\pgf@sys@tonumber{\pgfutil@tempdima}}% + \pgfutil@tempdima=\pgfmathresult pt% + \pgf@x=\pgf@pt@bb\pgfutil@tempdima% bb/(det A) + \xdef\pgf@new@pt@aa{\pgf@sys@tonumber{\pgf@x}}% + \pgf@x=\pgf@pt@aa\pgfutil@tempdima% aa/(det A) + \xdef\pgf@new@pt@bb{\pgf@sys@tonumber{\pgf@x}}% + \pgfutil@tempdima=-\pgfutil@tempdima% + \pgf@x=\pgf@pt@ba\pgfutil@tempdima% -ba/(det A) + \xdef\pgf@new@pt@ba{\pgf@sys@tonumber{\pgf@x}}% + \pgf@x=\pgf@pt@ab\pgfutil@tempdima% -ab/(det A) + \xdef\pgf@new@pt@ab{\pgf@sys@tonumber{\pgf@x}}% + }% + \let\pgf@pt@aa\pgf@new@pt@aa% + \let\pgf@pt@ab\pgf@new@pt@ab% + \let\pgf@pt@ba\pgf@new@pt@ba% + \let\pgf@pt@bb\pgf@new@pt@bb% + \fi% + \pgf@pt@temp=\pgf@pt@x% + \pgf@pt@x=\pgf@pt@aa\pgf@pt@x% + \advance\pgf@pt@x by\pgf@pt@ba\pgf@pt@y% + \pgf@pt@y=\pgf@pt@bb\pgf@pt@y% + \advance\pgf@pt@y by\pgf@pt@ab\pgf@pt@temp% + \fi% +} + + + + +% PGF-Level concatenation of the transformation matrix with a given +% matrix. +% +% #1 - #5 = a concatenation matrix (see pdf spec). Entry #5 is a +% translation point. +% +% Description: +% +% All coordinates given to subsequent path construction commands will +% be transformed additionally by the given transformation matrix. If +% the command is followed by a 6th argument, the transformation is +% only applied to this argument. +% +% +% Example: +% +% \pgftransformcm{1}{0}{0}{1}{\pgfpoint{100pt}{0pt}} % 100pt to the right. +% +% \pgftransformcm{2}{0}{0}{2}{\pgfpointorigin} % double in size +% \pgfpathmoveto{\pgfpoint{0cm}{0cm}} +% \pgfpathlineto{\pgflineto{1cm}{1cm}} % actually 2cm/2cm + +\def\pgftransformcm#1#2#3#4#5{% + \edef\pgf@marshal{\noexpand\pgf@transformcm{#1}{#2}{#3}{#4}}% + \pgf@marshal{#5}% +} +\def\pgf@transformcm#1#2#3#4#5{% + {% + \pgf@process{#5}% + \pgf@xc=\pgf@x% + \pgf@yc=\pgf@y% + % + \pgfmathsetlength\pgf@x{#1}% + \pgfmathsetlength\pgf@y{#2}% + % + \pgf@xa=\pgf@pt@aa\pgf@x% + \advance\pgf@xa by \pgf@pt@ba\pgf@y% + % + \pgf@ya=\pgf@pt@ab\pgf@x% + \advance\pgf@ya by \pgf@pt@bb\pgf@y% + % + \pgfmathsetlength\pgf@x{#3}% + \pgfmathsetlength\pgf@y{#4}% + % + \pgf@xb=\pgf@pt@aa\pgf@x% + \advance\pgf@xb by \pgf@pt@ba\pgf@y% + % + \pgf@yb=\pgf@pt@ab\pgf@x% + \advance\pgf@yb by \pgf@pt@bb\pgf@y% + % + \pgf@x=\pgf@pt@aa\pgf@xc% + \advance\pgf@x by\pgf@pt@ba\pgf@yc% + \advance\pgf@x by\pgf@pt@x% + % + \pgf@y=\pgf@pt@ab\pgf@xc% + \advance\pgf@y by\pgf@pt@bb\pgf@yc% + \advance\pgf@y by\pgf@pt@y% + % + \global\pgf@x=\pgf@x% + \global\pgf@y=\pgf@y% + \xdef\pgf@tempaa{\pgf@sys@tonumber{\pgf@xa}}% + \xdef\pgf@tempab{\pgf@sys@tonumber{\pgf@ya}}% + \xdef\pgf@tempba{\pgf@sys@tonumber{\pgf@xb}}% + \xdef\pgf@tempbb{\pgf@sys@tonumber{\pgf@yb}}% + }% + \pgf@pt@x=\pgf@x% + \pgf@pt@y=\pgf@y% + \let\pgf@pt@aa=\pgf@tempaa% + \let\pgf@pt@ba=\pgf@tempba% + \let\pgf@pt@ab=\pgf@tempab% + \let\pgf@pt@bb=\pgf@tempbb% + \edef\pgf@idtest{\pgf@pt@aa,\pgf@pt@ba,\pgf@pt@ab,\pgf@pt@bb}% + \ifx\pgf@idtest\pgf@idmatrixtext% + \pgf@pt@identitytrue% + \else% + \pgf@pt@identityfalse% + \fi% +} + + + +% Transformation into a given triangle. The three corners of the +% triangle are called "origin", "x" and "y" are given. After this +% transformation has been applied, the canvas origin is at "origin", +% the vector (1pt,0pt) lies at "x" and the vector (0pt,1pt) lies at +% "y". +% +% #1 = origin +% #2 = x +% #3 = y +% +% Example: +% +% \pgftransformtriangle{\pgfpointorigin}{\pgfpoint{1cm}{1cm}}{\pgfpoint{-1cm}{1cm}} + +\def\pgftransformtriangle#1#2#3{% + \pgf@process{#2}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgf@process{#3}% + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + \pgf@process{#1}% + \advance\pgf@xa by-\pgf@x% + \advance\pgf@ya by-\pgf@y% + \advance\pgf@xb by-\pgf@x% + \advance\pgf@yb by-\pgf@y% + \pgftransformcm% + {\pgf@sys@tonumber\pgf@xa}{\pgf@sys@tonumber\pgf@ya}% + {\pgf@sys@tonumber\pgf@xb}{\pgf@sys@tonumber\pgf@yb}% + {\pgfpoint{\pgf@x}{\pgf@y}}% +} + + + +% Undo all transformations +% +% Example: +% +% \pgftansformreset + +\def\pgftransformreset{% + \pgf@pt@x=0pt% + \pgf@pt@y=0pt% + \let\pgf@pt@aa\pgf@one@text% + \let\pgf@pt@ba\pgf@zero@text% + \let\pgf@pt@ab\pgf@zero@text% + \let\pgf@pt@bb\pgf@one@text% + \pgf@pt@identitytrue% +} + + +% Undo all slanting/rotation, but not translations +% +% Example: +% +% \pgftransformresetnontranslations + +\def\pgftransformresetnontranslations{% + \let\pgf@pt@aa\pgf@one@text% + \let\pgf@pt@ba\pgf@zero@text% + \let\pgf@pt@ab\pgf@zero@text% + \let\pgf@pt@bb\pgf@one@text% + \pgf@pt@identitytrue% +} + + + + +% Shifting command and environment +% +% #1 = vector by which all subsequent points should be moved. +% +% Example: +% +% \pgftansformshift{\pgfpoint{1cm}{1cm}} + +\def\pgftransformshift#1{\pgftransformcm{1}{0}{0}{1}{#1}} +\def\pgftransformxshift#1{\pgftransformcm{1}{0}{0}{1}{\pgfpoint{#1}{+0pt}}} +\def\pgftransformyshift#1{\pgftransformcm{1}{0}{0}{1}{\pgfpoint{+0pt}{#1}}} + + + + +% Scaling commands +% +% #1 = scaling for all subsequent points. +% +% Example: +% +% \pgftransformscale{2} +% \pgftransformxscale{2} +% \pgftransformyscale{2} + +\def\pgftransformscale#1{\pgftransformcm{#1}{0}{0}{#1}{\pgfpointorigin}} +\def\pgftransformxscale#1{\pgftransformcm{#1}{0}{0}{1.0}{\pgfpointorigin}} +\def\pgftransformyscale#1{\pgftransformcm{1.0}{0}{0}{#1}{\pgfpointorigin}} + + + +% Slanting commands +% +% #1 = slanting in x-direction. 1 means 45 degrees. +% +% Example: +% +% \pgftransformxslant{2} +% \pgftransformyslant{2} + +\def\pgftransformxslant#1{\pgftransformcm{1.0}{0}{#1}{1.0}{\pgfpointorigin}} +\def\pgftransformyslant#1{\pgftransformcm{1.0}{#1}{0}{1.0}{\pgfpointorigin}} + + + +% Rotation commands +% +% #1 = degrees for the rotation +% +% Example: +% +% \pgftransformrotate{30} + +\def\pgftransformrotate#1{% + \pgfmathparse{#1}% + \let\pgftransform@angle=\pgfmathresult% + \pgfmathsin@{\pgftransform@angle}% + \let\pgftransform@sin=\pgfmathresult% + \pgfmathcos@{\pgftransform@angle}% + \let\pgftransform@cos=\pgfmathresult% + \pgf@x=\pgftransform@sin pt% + \pgf@xa=-\pgf@x% + \pgftransformcm{\pgftransform@cos}{\pgftransform@sin}{\pgf@sys@tonumber{\pgf@xa}}{\pgftransform@cos}{\pgfpointorigin}% +} + + + +% The following if's have the following effect: +% +% \ifpgfslopedattime decides whether the coordinate system of an +% xxxattime transformation command should be rotated such that text +% drawn on the line should be tangent to the line +% +% \ifpgfallowupsidedowattime decides whether the transformation should +% be done in such a way that the text is always ``upright,'' that is, +% text drawn in this coordinate system is never upside-down. +% +% \ifpgfresetnontranslationattime decides whether the coordinate +% system of an xxxattime transformation command should be reset +% (concerning the non-translations) before a possible rotation is +% applied. This is useful, for example, if the main coordinate system +% is scaled by, say, a factor of 2 and you do not want that to apply +% to the text, but you do want the rotation to apply. + +\newif\ifpgfslopedattime +\newif\ifpgfallowupsidedownattime +\newif\ifpgfresetnontranslationattime + + +% Transform to the coordinate system of a point on a line +% +% #1 = a time fraction of line where to put the label, where 0 means start, +% 1 means end, and for example 0.5 means the middle. +% #2 = start of line +% #3 = end of line +% +% Example: +% +% { +% \pgftransformlineattime{.5}{\pgfxy(0,0)}{\pgfxy(3,2)} +% \pgftext{Hi!} +% } +% +% { +% \pgftransformlineattime{.75}{\pgfxy(0,0)}{\pgfxy(3,2)} +% \pgftransformresetnontranslations +% \pgftext{Hi!} +% } +% +\def\pgftransformlineattime#1#2#3{% + \pgf@process{#2}% + \pgf@xb=\pgf@x% xb/yb = start point + \pgf@yb=\pgf@y% + \pgf@process{#3}% + \pgf@xc=\pgf@x% xc/yc = end point + \pgf@yc=\pgf@y% + \pgftransformshift{\pgfpointlineattime{#1}{\pgfqpoint{\pgf@xb}{\pgf@yb}}{\pgfqpoint{\pgf@xc}{\pgf@yc}}}% + \ifpgfresetnontranslationattime% + \pgftransformresetnontranslations% + \fi% + \ifpgfslopedattime% + \advance\pgf@xc by-\pgf@xb% + \advance\pgf@yc by-\pgf@yb% + \ifpgfallowupsidedownattime% + \else% + \ifdim\pgf@xc<0pt% + \pgf@xc=-\pgf@xc% + \pgf@yc=-\pgf@yc% + \fi% + \fi% + \pgf@x=\pgf@xc% + \pgf@y=\pgf@yc% + \pgfpointnormalised{}% x/y = normalised vector + \pgf@ya=-\pgf@y% + \pgftransformcm% + {\pgf@sys@tonumber{\pgf@x}}{\pgf@sys@tonumber{\pgf@y}}% + {\pgf@sys@tonumber{\pgf@ya}}{\pgf@sys@tonumber{\pgf@x}}{\pgfpointorigin}% + \fi% +} + + +% Transform to the coordinate system of a point on an arc +% +% #1 = a time fraction of line where to put the label, where 0 means start, +% 1 means end, and for example 0.5 means the middle. +% #2 = center of an ellipse +% #3 = 0-degree axis of the ellipse +% #4 = 90-degree axis of the ellipse +% #4 = start angle of the arc on this ellipse +% #5 = end angle of the arc on this ellipse +% +% Example: +% +% { +% \pgftransformlineattime{.5}{\pgfpoint{1cm}{1cm}}{\pgfpoint{1cm}{0cm}}{\pgfpoint{0cm}{1cm}}{30}{40} +% \pgftext{Hi!} +% } + +\def\pgftransformarcaxesattime#1#2#3#4#5#6{% + \pgfpointarcaxesattime{#1}{#2}{#3}{#4}{#5}{#6}% + \pgftransformshift{\pgfqpoint{\pgf@x}{\pgf@y}}% + \ifpgfresetnontranslationattime% + \pgftransformresetnontranslations% + \fi% + \ifpgfslopedattime% + \pgf@x=\pgf@xa% + \pgf@y=\pgf@ya% + \pgf@process{\pgfpointnormalised{}}% + \ifpgfallowupsidedownattime% + \else% + \ifdim\pgf@x<0pt% + \pgf@x=-\pgf@x% + \pgf@y=-\pgf@y% + \fi% + \fi% + \pgf@ya=-\pgf@y% + \pgftransformcm% + {\pgf@sys@tonumber{\pgf@x}}{\pgf@sys@tonumber{\pgf@y}}% + {\pgf@sys@tonumber{\pgf@ya}}{\pgf@sys@tonumber{\pgf@x}}{\pgfpointorigin}% + \fi% +} + + + + +% Transform to the coordinate system of a point on a curve +% +% #1 = a time fraction of line where to put the label, where 0 means start, +% 1 means end, and for example 0.5 means the middle. +% #2 = start of line +% #3 = first control +% #4 = second control +% #5 = end of line +% +% Example: +% +% { +% \pgftransformcurveattime{.5}{\pgfxy(0,0)}{\pgfxy(3,2)} +% \pgftext{Hi!} +% } +% +% { +% \pgftransformcurveattime{.75}{\pgfxy(0,0)}{\pgfxy(3,2)} +% \pgftransformresetnontranslations +% \pgftext{Hi!} +% } +% +\def\pgftransformcurveattime#1#2#3#4#5{% + \pgfpointcurveattime{#1}{#2}{#3}{#4}{#5}% + \pgftransformshift{\pgfqpoint{\pgf@x}{\pgf@y}}% + \ifpgfresetnontranslationattime% + \pgftransformresetnontranslations% + \fi% + \ifpgfslopedattime% + \pgf@x=\pgf@xa% + \pgf@y=\pgf@ya% + \advance\pgf@x by-\pgf@xb% + \advance\pgf@y by-\pgf@yb% + \ifpgfallowupsidedownattime% + \else% + \ifdim\pgf@x<0pt% + \pgf@x=-\pgf@x% + \pgf@y=-\pgf@y% + \fi% + \fi% + \pgfpointnormalised{}% x/y = normalised vector + \pgf@ya=-\pgf@y% + \pgftransformcm% + {\pgf@sys@tonumber{\pgf@x}}{\pgf@sys@tonumber{\pgf@y}}% + {\pgf@sys@tonumber{\pgf@ya}}{\pgf@sys@tonumber{\pgf@x}}{\pgfpointorigin}% + \fi% +} + + + + + +% Transform to the coordinate system of an arrow at the end of the +% line going from point #1 to point #2 with the correct rotation. +% +% #1 = a start point an (invisible) line +% #2 = an end point an (invisible) line +% +% Example: +% +% \pgftransformarrow{\pgfpointorigin}{\pgfpoint{1cm}{0cm}} + +\def\pgftransformarrow#1#2{% + \pgf@process{#2}% + \pgftransformshift{}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgf@process{#1}% + \advance\pgf@xa by-\pgf@x% + \advance\pgf@ya by-\pgf@y% + \pgf@x=\pgf@xa% + \pgf@y=\pgf@ya% + \pgfpointnormalised{}% + \pgf@ya=-\pgf@y% + \pgftransformcm% + {\pgf@sys@tonumber{\pgf@x}}{\pgf@sys@tonumber{\pgf@y}}% + {\pgf@sys@tonumber{\pgf@ya}}{\pgf@sys@tonumber{\pgf@x}}{\pgfqpoint{0pt}{0pt}}% +} + + + + +% Computes transformations adjustments for the current transformation +% matrix +% +% Description: +% +% This command is used when you install a transformation matrix that +% scales everything by a certain factor, but you still wish to draw +% something with "an absolute size". Suppose for instance that you +% install a transformation matrix that scales everything by a factor +% of 4 and you now wish to draw a horizontal line of length 1cm. Then, +% if you do not reset the transformation matrix, you can draw a line +% of logical length 2.5mm, which will then get scaled to a line of +% 1cm. +% +% Things get more difficult in case you scale things only, say, +% vertically. In this case, the adjustment necessary for horizontal +% lines is different from the one needed for vertical lines. +% +% This function computes the necessary scaling factors and puts them +% in the macros \pgfhorizontaltransformationadjustment and +% \pgfverticaltransformationadjustment. +% +% Note that the "right" way to draw a line of absolute length 1cm in a +% transformed coordinate system is to first compute the start point +% and to then reset the transformation matrix. The transformation +% adjustments computed here are important only in situations where you +% cannot do this, for instance when an "outer xsep" must be set. + +\def\pgftransformationadjustments{% + \ifpgf@pt@identity% + \let\pgfhorizontaltransformationadjustment\pgf@one@text% + \let\pgfverticaltransformationadjustment\pgf@one@text% + \else% + {% + \pgf@pt@x0pt% + \pgf@pt@y0pt% + \pgfpointtransformed{\pgfqpoint{1pt}{0pt}}% + \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}% + \pgfmathreciprocal@{\pgfmathresult}% + \global\let\pgf@temp@hori\pgfmathresult + \pgfpointtransformed{\pgfqpoint{0pt}{1pt}}% + \pgfmathveclen@{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}% + \pgfmathreciprocal@{\pgfmathresult}% + \global\let\pgf@temp@vert\pgfmathresult + \xdef\pgf@marshal@b{\def\noexpand\pgfverticaltransformationadjustment{\pgfmathresult}} + }% + \let\pgfhorizontaltransformationadjustment\pgf@temp@hori% + \let\pgfverticaltransformationadjustment\pgf@temp@vert% + \fi% +} + +\let\pgfhorizontaltransformationadjustment\pgf@one@text +\let\pgfverticaltransformationadjustment\pgf@one@text + + +% Low-level transformations + +% Causes the current high-level transformation command to be applied +% to the low-level. +% +% Description: +% +% All subsequent drawing will be transformed additionally by the +% current high-level transformation. Thus, the high-level +% transformation becomes the low-level transformation. The high-level +% transformation is reset at this point. + +\def\pgflowlevelsynccm{% + \pgfsys@transformcm% + {\pgf@pt@aa}{\pgf@pt@ab}% + {\pgf@pt@ba}{\pgf@pt@bb}% + {\pgf@pt@x}{\pgf@pt@y}% + \pgftransformreset% + \pgf@relevantforpicturesizefalse% +} + + + +% Causes a transformation command to be applied to the ``lowlevel'' +% transformation matrix. +% +% #1 - a high-level transformation command +% +% Description: +% +% All subsequent drawing will be transformed additionally by the given +% transformation matrix. Note that PGF will no longer be able to +% ``keep track'' of the coordinates. Also, transformations are applied +% to *everything*, including line thickness and line endings. Most +% often, this is not desirable. +% +% Example: +% +% \pgflowlevel{\pgftransformcm{1}{0}{0}{1}{\pgfpoint{100pt}{0pt}}} % 100bp to the right. +% +% \begin{pgflowlevelscope}{\pgftransformcm{2}{0}{0}{2}{\pgfpointorigin}} % double in size +% \pgfmoveto{\pgfpoint{0cm}{0cm}} +% \pgflineto{\pgflineto{1cm}{1cm}} % actually 2cm/2cm +% \end{pgflowlevelscope} + +\def\pgflowlevel#1{% + {% + \pgftransformreset% + #1% + \pgflowlevelsynccm% + }% + \pgf@relevantforpicturesizefalse% +} + +\def\pgflowlevelscope#1{\pgfscope\pgflowlevel{#1}} +\def\endpgflowlevelscope{\endpgfscope} + +\long\def\pgflowlevelobj#1#2{\pgfscope{\pgflowlevel{#1}#2}\endpgfscope} + + + +% View boxes + +% Establishes a view box scope +% +% #1 and #2 = two opposite corners of the source rectangle +% #3 and #4 = two opposite corners of the target rectangle +% #5 = "meet" or "slice" +% +% Description: +% +% Inside the viewbox scope, the source rectangle will be translated +% and scaled so that it becomes centered on the target rectangle and +% will, for "meet", be as large as possible so that it fits inside the +% target and, for "slice", be as small as possible so that it +% encompasses the target. + +\def\pgfviewboxscope#1#2#3#4#5{% + {% Compute rectangle corners + \pgf@process{#1}% + \pgf@pos@transform@glob + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgf@process{#2}% + \pgf@pos@transform@glob + \ifdim\pgf@x<\pgf@xa% + \pgf@xb\pgf@x% + \pgf@xc\pgf@xa% + \else% + \pgf@xb\pgf@xa% + \pgf@xc\pgf@x% + \fi% + \ifdim\pgf@y<\pgf@ya% + \pgf@yb\pgf@y% + \pgf@yc\pgf@ya% + \else% + \pgf@yb\pgf@ya% + \pgf@yc\pgf@y% + \fi% + \pgf@process{#3}% + \pgf@pos@transform@glob + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgf@process{#4}% + \pgf@pos@transform@glob + \ifdim\pgf@x<\pgf@xa% + \else% + \pgfutil@tempdima\pgf@x + \pgf@x\pgf@xa% + \pgf@xa\pgfutil@tempdima% + \fi% + \ifdim\pgf@y<\pgf@ya% + \else% + \pgfutil@tempdima\pgf@y + \pgf@y\pgf@ya% + \pgf@ya\pgfutil@tempdima% + \fi% + \pgfusetype{.view}% + \edef\pgf@marshal{\expandafter\noexpand\csname pgfsys@viewbox#5\endcsname{\the\pgf@x}{\the\pgf@y}{\the\pgf@xa}{\the\pgf@ya}{\the\pgf@xb}{\the\pgf@yb}{\the\pgf@xc}{\the\pgf@yc}}% + \pgf@marshal% + }% + \pgf@relevantforpicturesizefalse% +} + +\def\endpgfviewboxscope{\pgfsys@endviewbox} + +\let\startpgfviewboxscope=\pgfviewboxscope +\let\stoppgfviewboxscope=\endpgfviewboxscope + +% Forward declarations for nonlinear stuff (have no effect till module +% nonlineartransformations is loaded) + +\let\pgfapproximatenonlineartranslation\relax +\let\pgfapproximatenonlineartransformation\relax +\def\pgftransformnonlinear#1{\pgferror{You need to say + \string\usepgfmodule{nonlineartransformations} to use nonlinear transformations}} + + +\endinput diff --git a/graphics/pgf/base/tex/generic/basiclayer/pgfcoretransparency.code.tex b/graphics/pgf/base/tex/generic/basiclayer/pgfcoretransparency.code.tex new file mode 100644 index 0000000000..7da8f5a378 --- /dev/null +++ b/graphics/pgf/base/tex/generic/basiclayer/pgfcoretransparency.code.tex @@ -0,0 +1,312 @@ +% Copyright 2018 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{pgfcoretransparency.code.tex} + + +% Sets the opacity of stroking operations. +% +% #1 = opacity, where 1 means fully opaque and 0 means fully +% transparent. +% +% Example: +% +% \pgfsetstrokeopacity{0.5} + +\def\pgfsetstrokeopacity#1{% + \pgfmathparse{#1}% + \expandafter\pgfsys@stroke@opacity\expandafter{\pgfmathresult}} + + +% Sets the opacity of stroking operations. +% +% #1 = opacity, where 1 means fully opaque and 0 means fully +% transparent. +% +% Example: +% +% \pgfsetfillopacity{0.5} + +\def\pgfsetfillopacity#1{% + \pgfmathparse{#1}% + \expandafter\pgfsys@fill@opacity\expandafter{\pgfmathresult}} + + + +% Sets the current blend mode. See Section 7.2.4 of the PDF +% Specification 1.7 for an introduction to blend modes in general. +% +% #1 = One of the following modes, see also section 7.2.4 of the +% PDF Specification 1.7. (The PGF names, which are all lowercase with +% spaces as usual, must be mapped to the PDF or SVG by the drivers.) +% +% normal +% multiply +% screen +% overlay +% darken +% lighten +% color dodge +% color burn +% hard light +% soft light +% difference +% exclusion +% saturation +% color +% hue +% luminosity +% +% Example: +% +% \pgfsetblendmode{multiply} + +\def\pgfsetblendmode#1{\pgfsys@blend@mode{#1}} + + +% Declares a new fading based on the contents of a box. +% +% #1 = name of the fading +% #2 = content of a TeX box that specifies the fading +% +% Description: +% +% This command declares a new fading based on the contents of +% the TeX box. The mask can later be used to mask other graphics. +% +% The box is used to determine where the mask is opaque: At the +% beginning, the mask is completely transparent. Wherever the box +% contains something (like text or a picture or whatever), the +% luminosity of the text/graphic is used to determine how opaque the +% point will be. The greater the luminosity, the more opaque. The net +% effect is that white corresponds to "completely opaque" and black to +% "completely transparent". This is rather counterintuitive. Because +% of this, the special color "pgftransparent" is defined, which is the +% same as black. By setting the color to, say, +% \color{pgftransparent!10} you get something that is 10% transparent +% and \color{pgftransparent!90} gives you 90% transparency. +% +% By default, the drawing color is set to opaque. +% +% Example: +% +% \pgfdeclarefading{mymask}{ +% \fontsize{200}{200}\bfseries +% Ti\emph{k}Z +% } +% \pgfdeclarefading{myothermask}{ +% \tikz \shade [left color=transparent,right color=transparent!0] +% (0,0) rectangle (5,5); +% } + +\def\pgfdeclarefading#1#2{% + \setbox\pgfutil@tempboxa=\hbox{{\pgfsys@beginscope\pgfutil@color{white}\ignorespaces#2\pgfsys@endscope}}% + \pgfsys@fadingfrombox{#1}\pgfutil@tempboxa% +} + +\pgfutil@colorlet{pgftransparent}{black} + + +% Use a previously declared fading. +% +% #1 = name of the fading +% #2 = transformation code +% +% Description: +% +% The command should be used *inside* a pgfpicture to install a +% fading. The fading is a part of the graphic state. (This command +% works much like \pgfsetstrokeopacity). +% +% The mask will be centered on the origin. The transformation code #2 is +% applied to the mask (but not the contents of the actual picture). + +\def\pgfsetfading#1#2{% + {% + \pgftransformreset% + #2% + \pgfgettransform{\pgftrans@temp}% + \edef\pgf@marshal{\noexpand\pgfsys@usefading{#1}\pgftrans@temp}% + \pgf@marshal% + }% +} + + + +% Use a previously declared fading scaled for the current path. +% +% #1 - an fading +% #2 - extra transformations +% +% Description: +% +% This command works a bit like \pgfshadepath. "Works a bit like" +% means the following: The masks's original size should +% completely cover the area between (0,0) and (100bp,100bp). The +% mask is then rescaled so that it completely covers the path. Then +% the additional transformation #2 is applied. Finally, the mask is +% made part of the graphic state (as with \pgfsetfading). The path +% used for computation purposes only -- it is not drawn or otherwise +% used. +% +% If no transformations occur, the lower left corner of the path will +% lie on (25bp, 25bp), the upper right corner on (75bp, 75bp). +% +% If the path was empty, the fading will be used at its natural size, +% centered on the origin. +% +% Example: +% +% \pgfdeclarefading{fade right} +% {\tikz[left color=transparent!0,right color=transparent!100] +% (0,0) rectangle (100bp,100bp);} +% +% \pgfpathmoveto{\pgforigin} +% \pgfpathlineto{\pgfxy(1,0)} +% \pgfpathlineto{\pgfxy(1,1)} +% \pgfsetfadingforcurrentpath{fade right}{} +% \pgfusepath{fill} + +\def\pgfsetfadingforcurrentpath#1#2{% + \ifdim\pgf@pathminx=16000pt% + % Path was empty -> use natural size + \pgfsetfading{#1}{#2}% + \else% + \pgfsetfading{#1}{% + % Calculate center: + \pgf@xb=.5\pgf@pathmaxx% + \advance\pgf@xb by.5\pgf@pathminx% + \pgf@yb=.5\pgf@pathmaxy% + \advance\pgf@yb by.5\pgf@pathminy% + % Calculate scaling: + \pgf@xc=\pgf@pathmaxx% + \advance\pgf@xc by-\pgf@pathminx% + \ifdim\pgf@xc<0.1pt\pgf@xc=0.1pt\fi% + \pgf@yc=\pgf@pathmaxy% + \advance\pgf@yc by-\pgf@pathminy% + \ifdim\pgf@yc<0.1pt\pgf@yc=0.1pt\fi% + \pgf@xc=.02\pgf@xc% + \pgf@yc=.02\pgf@yc% + % Compute new transformation matrix: + \pgftransformcm{1}{0}{0}{1}{\pgfqpoint{\pgf@xb}{\pgf@yb}}% + \pgftransformcm{\pgf@sys@tonumber{\pgf@xc}}{0}{0}{\pgf@sys@tonumber{\pgf@yc}}{\pgfpointorigin}% + \pgfsys@clipfading% + #2% + }% + \fi% +} + + + + +% Use a previously declared fading scaled for the current path. +% +% #1 - an fading +% #2 - extra transformations +% +% Description: +% +% This command works like \pgfsetfadingforcurrentpath, only it takes +% the current line width into account: Before the path is considered, +% it is enlarged by half the line width in all directions. + +\def\pgfsetfadingforcurrentpathstroked#1#2{% + \ifdim\pgf@pathminx=16000pt% + % Path was empty -> use natural size + \pgfsetfading{#1}{#2}% + \else% + \pgfsetfading{#1}{% + % Calculate center: + \pgf@xb=.5\pgf@pathmaxx% + \advance\pgf@xb by.5\pgf@pathminx% + \pgf@yb=.5\pgf@pathmaxy% + \advance\pgf@yb by.5\pgf@pathminy% + % Calculate scaling: + \pgf@xc=\pgf@pathmaxx% + \advance\pgf@xc by-\pgf@pathminx% + \advance\pgf@xc by\pgflinewidth% + \ifdim\pgf@xc<0.1pt\pgf@xc=0.1pt\fi% + \pgf@yc=\pgf@pathmaxy% + \advance\pgf@yc by-\pgf@pathminy% + \advance\pgf@yc by\pgflinewidth% + \ifdim\pgf@yc<0.1pt\pgf@yc=0.1pt\fi% + \pgf@xc=.02\pgf@xc% + \pgf@yc=.02\pgf@yc% + % Compute new transformation matrix: + \pgftransformcm{1}{0}{0}{1}{\pgfqpoint{\pgf@xb}{\pgf@yb}}% + \pgftransformcm{\pgf@sys@tonumber{\pgf@xc}}{0}{0}{\pgf@sys@tonumber{\pgf@yc}}{\pgfpointorigin}% + \pgfsys@clipfading% + #2% + }% + \fi% +} + + +% Group things in a a transparency group +% +% Description: +% +% This takes groups pgf commands inside a pgfpicture in a transparency +% group. This means that any transparency settings apply to commands a +% whole. For instance, if a box contains two overlapping black +% circles and you draw them normally with 50% transparency, then the +% overlap will be darker than the rest. By comparison, if the circles +% are part of a transparency group, the overlap will get the same +% color as the rest. +% +% + +\def\pgftransparencygroup{% + \pgfutil@ifnextchar[{\pgftransparencygroup@}{\pgftransparencygroup@[]}% +} +\def\pgftransparencygroup@[#1]{% + \begingroup% + \pgfkeys{/pgf/transparency group options/.cd,% + isolated=false, + knockout=false, + #1}% + \setbox\pgfutil@tempboxa=\hbox\bgroup% +} +\pgfkeys{ + /pgf/transparency group options/.cd, + isolated/.is if=pgfsys@transparency@group@isolated, + knockout/.is if=pgfsys@transparency@group@knockout +} + +\def\endpgftransparencygroup{% + \egroup% + % Now compute the correct position. This is a bit tricky... + \ifdim\pgf@picminx=16000pt% + % Nothing needs to be done + \else% + % Safety margin to avoid clipping: + \advance\pgf@picminx by-1cm% + \advance\pgf@picmaxx by1cm% + \advance\pgf@picminy by-1cm% + \advance\pgf@picmaxy by1cm% + % Ok, set the box size to current picture size. + \setbox\pgfutil@tempboxa=\hbox{% + \vrule width0pt height\pgf@picmaxy depth-\pgf@picminy% + \hskip-\pgf@picminx% + \box\pgfutil@tempboxa% + \hskip\pgf@picmaxx% + }% + \pgfsys@transparencygroupfrombox\pgfutil@tempboxa% + \wd\pgfutil@tempboxa=0pt% + \ht\pgfutil@tempboxa=0pt% + \dp\pgfutil@tempboxa=0pt% + \hskip\pgf@picminx\box\pgfutil@tempboxa\hskip-\pgf@picminx% + \fi% + \endgroup% +} + +\let\startpgftransparencygroup=\pgftransparencygroup +\let\stoppgftransparencygroup=\endpgftransparencygroup + +\endinput |