diff options
Diffstat (limited to 'Master/texmf-dist/tex/generic/pgf/modules/pgfmoduledecorations.code.tex')
-rw-r--r-- | Master/texmf-dist/tex/generic/pgf/modules/pgfmoduledecorations.code.tex | 334 |
1 files changed, 291 insertions, 43 deletions
diff --git a/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduledecorations.code.tex b/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduledecorations.code.tex index 739a28395c2..9834e91f0ec 100644 --- a/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduledecorations.code.tex +++ b/Master/texmf-dist/tex/generic/pgf/modules/pgfmoduledecorations.code.tex @@ -1,4 +1,4 @@ -% Copyright 2008 by Mark Wibrow +% Copyright 2008 by Mark Wibrow and Till Tantau % % This file may be distributed and/or modified % @@ -57,10 +57,11 @@ start radius/.initial=2.5pt, end radius/.initial=2.5pt, radius/.style={start radius=#1,end radius=#1}, - path has corners/.is if=pgfdecoratepathhascorners + path has corners/.is if=pgfdecoratepathhascorners, + reverse path/.is if=pgf@decorate@inputsegmentobjects@reverse } \newif\ifpgfdecoratepathhascorners - +\newif\ifpgf@decorate@inputsegmentobjects@reverse % Declare a decoration % @@ -490,6 +491,7 @@ } + % Enviroment \pgfmetadecoration \endpgfmetadecoration % % Decorate a path with decoration automatons! @@ -539,12 +541,12 @@ % \endpgfpicture % \def\pgfmetadecoration#1{% - \begingroup% - \let\decoration\pgf@metadecoration@decoration% - \let\beforedecoration\pgf@metadecoration@beforedecoration% - \let\afterdecoration\pgf@metadecoration@afterdecoration% - \def\pgf@metadecoration@name{#1}% - \pgf@decoration@env% + \begingroup% + \let\decoration\pgf@metadecoration@decoration% + \let\beforedecoration\pgf@metadecoration@beforedecoration% + \let\afterdecoration\pgf@metadecoration@afterdecoration% + \def\pgf@metadecoration@name{#1}% + \pgf@decoration@env% } \def\endpgfmetadecoration{% @@ -611,6 +613,21 @@ \bgroup% } +\def\pgf@decorate@path@check@moveto#1{% + \expandafter\pgf@decorate@path@@check@moveto#1\pgf@decorate@stop\pgf@decorate@@stop} + +\def\pgf@decorate@token@stop{\pgf@decorate@stop}% +\def\pgf@decorate@path@@check@moveto#1#2#3#4\pgf@decorate@@stop#5#6{% + \def\pgf@decorate@temp{#4}% + \pgf@x=#2\relax% + \pgf@y=#3\relax% + \ifx\pgf@decorate@temp\pgf@decorate@token@stop% + #5% + \else% + #6% + \fi% +} + \def\pgf@decoration@endenv{% \egroup% \pgftransformreset% @@ -623,6 +640,18 @@ \ifx\pgfdecoratedpath\pgfutil@empty% \PackageError{PGF}{I cannot decorate an empty path}{}% \else% + % + % If the path consists of a single moveto token, make it + % a very small horizontal line. + % + \pgf@decorate@path@check@moveto\pgfdecoratedpath{% + \advance\pgf@x by0.0001pt\relax% + \edef\pgfdecoratedpath{% + \expandafter\noexpand\pgfdecoratedpath% + \noexpand\pgfsyssoftpath@linetotoken{\the\pgf@x}{\the\pgf@y}% + }% + }% + {}% % % Remove special round tokens and get points. % @@ -631,6 +660,16 @@ % Parse the soft path into a series of decorated input segment objects. % \pgf@decorate@parsesoftpath{\pgfdecoratedpath}{\pgf@decorate@inputsegmentobjects}% + % + % Setup further options + % + \pgfkeys{/pgf/every decoration/.try}% + % + % Reverse objects if necessary. + % + \ifpgf@decorate@inputsegmentobjects@reverse% + \pgf@decorate@inputsegmentobjects@reverse{\pgf@decorate@inputsegmentobjects}{\pgf@decorate@inputsegmentobjects}% + \fi% % \let\pgf@decorated@remainingdistance\pgf@decorate@totalpathlength% % @@ -647,13 +686,8 @@ \pgf@decorate@getnextinputsegmentobject\pgf@decorate@nextinputsegmentobject% \pgf@decorate@processnextinputsegmentobject% \pgf@decorate@distancetomove0pt\relax% - % - % Setup further options - % - \pgfkeys{/pgf/every decoration/.try}% \fi% -}% - +}% @@ -1194,25 +1228,24 @@ % Process the next input segment object. % \def\pgf@decorate@processnextinputsegmentobject{% - % + \let\pgfdecorationpreviousinputsegment\pgfdecoratecurrentinputsegment% \let\pgf@decorate@currentinputsegmentobject\pgf@decorate@nextinputsegmentobject% \pgf@decorate@getnextinputsegmentobject\pgf@decorate@nextinputsegmentobject% - % + % % If the current input segment object is a moveto, execute the % object macro and get the next input segment object. % - \expandafter\pgfutil@in@\expandafter\pgf@decorate@inputsegmentobject@moveto% - \expandafter{\pgf@decorate@currentinputsegmentobject}% - \ifpgfutil@in@% - \pgf@decorate@currentinputsegmentobject% + \pgf@decorate@is@closepath@false% + \pgf@decorate@currentinputsegmentobject% + \ifx\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentmoveto% + \pgfpathmoveto{\pgf@decorate@inputsegment@first}% + \let\pgfdecorationpreviousinputsegment\pgfdecorationcurrentinputsegment% \let\pgf@decorate@currentinputsegmentobject\pgf@decorate@nextinputsegmentobject% \pgf@decorate@getnextinputsegmentobject\pgf@decorate@nextinputsegmentobject% - \relax% + \pgf@decorate@is@closepath@false% + \pgf@decorate@currentinputsegmentobject% \fi% % - \pgf@decorate@is@closepath@false% - \pgf@decorate@currentinputsegmentobject% - % % Teensy hack in case a path goes nowhere. % \ifdim\pgfdecoratedinputsegmentlength=0pt\relax% @@ -1221,8 +1254,41 @@ \pgfdecoratedinputsegmentremainingdistance\pgfdecoratedinputsegmentlength\relax% \pgfdecoratedinputsegmentcompleteddistance0pt\relax% \def\pgf@decorate@inputsegmenttime{0}% - \pgfmathanglebetweenpoints{\pgf@decorate@inputsegment@first}{\pgf@decorate@inputsegment@supporta}% - \let\pgfdecoratedangle\pgfmathresult% + % + % Get the angle at the start of the input segment. + % + \ifx\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentcurveto% + \pgfmathanglebetweenpoints{\pgf@decorate@inputsegment@first}{\pgf@decorate@inputsegment@supporta}% + \let\pgfdecoratedangle\pgfmathresult% + \let\pgfdecoratedinputsegmentstartangle\pgfmathresult% + \pgfmathanglebetweenpoints{\pgf@decorate@inputsegment@supportb}{\pgf@decorate@inputsegment@last}% + \let\pgfdecoratedinputsegmentendangle\pgfmathresult% + \else% + \pgfmathanglebetweenpoints{\pgf@decorate@inputsegment@first}{\pgf@decorate@inputsegment@last}% + \let\pgfdecoratedangle\pgfmathresult% + \let\pgfdecoratedinputsegmentstartangle\pgfmathresult% + \let\pgfdecoratedinputsegmentendangle\pgfmathresult% + \fi% + % + % Get the angle to the next input segment. + % + \begingroup% + \pgf@decorate@nextinputsegmentobject% + \global\let\pgf@decorate@temp\pgfdecorationcurrentinputsegment% + \ifx\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentmoveto% + \expandafter\pgf@decorate@currentinputsegmentobject% + \fi% + \ifx\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentcurveto% + \pgfmathanglebetweenpoints{\pgf@decorate@inputsegment@first}{\pgf@decorate@inputsegment@supporta}% + \else% + \pgfmathanglebetweenpoints{\pgf@decorate@inputsegment@first}{\pgf@decorate@inputsegment@last}% + \fi% + \pgf@x-\pgfdecoratedangle pt\relax% + \advance\pgf@x\pgfmathresult pt\relax% + \edef\pgfdecoratedangletonextinputsegment{\the\pgf@x}% + \pgfmath@smuggleone\pgfdecoratedangletonextinputsegment% + \endgroup% + \let\pgfdecorationnextinputsegmentobject\pgf@decorate@temp% } @@ -1232,18 +1298,30 @@ \newif\ifpgf@decorate@is@closepath@% +% Input segment types. +% +% These allow comparison with \ifx using +% +% \pgfdecorationcurrentinputsegment +% \pgfdecorationnextinputsegment +% \pgfdecorationcurrentprevioussegment +% +\def\pgfdecorationinputsegmentmoveto{moveto} +\def\pgfdecorationinputsegmentlineto{lineto} +\def\pgfdecorationinputsegmentcurveto{curveto} +\def\pgfdecorationinputsegmentclosepath{closepath} +\def\pgfdecorationinputsegmentlast{last} % Input segment object moveto. % \def\pgf@decorate@inputsegmentobject@moveto#1{% - \pgfpathmoveto{#1}% \def\pgf@decorate@inputsegment@first{#1}% \def\pgf@decorate@inputsegment@supporta{#1}% \def\pgf@decorate@inputsegment@supportb{#1}% \def\pgf@decorate@inputsegment@last{#1}% \edef\pgf@decorate@lastmoveto{#1}% \def\pgfdecoratedinputsegmentlength{0pt}% - \let\pgf@decorate@splitinputsegmentobject\pgf@decorate@splitinputsegmentobject@move% + \let\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentmoveto% } % Input segment object lineto. @@ -1251,17 +1329,28 @@ \def\pgf@decorate@inputsegmentobject@lineto#1#2#3{% \def\pgfdecoratedinputsegmentlength{#1}% \def\pgf@decorate@inputsegment@first{#2}% + \def\pgf@decorate@inputsegment@last{#3}% % - % OK, lines don't need supports, but this means angle calculations - % do not have to be done individually for each object. + % Supports should be defined like this, so if treated as a curve, + % equal time steps will correspond to equal distances. % - \def\pgf@decorate@inputsegment@supporta{#3}% - \def\pgf@decorate@inputsegment@supportb{#2}% - \def\pgf@decorate@inputsegment@last{#3}% + \pgfpointdiff{#2}{#3}% + \pgf@xa\pgf@x% + \pgf@ya\pgf@y% + \pgfextract@process\pgf@decorate@inputsegment@supporta{% + \pgf@process{#2}% + \advance\pgf@x0.333333\pgf@xa% + \advance\pgf@y0.333333\pgf@ya% + }% + \pgfextract@process\pgf@decorate@inputsegment@supportb{% + \pgf@process{#2}% + \advance\pgf@x0.666666\pgf@xa% + \advance\pgf@y0.666666\pgf@ya% + }% % \let\pgf@decorate@movealonginputsegment\pgf@decorate@movealonginputsegment@line% \let\pgf@decorate@transformtoinputsegment\pgf@decorate@transformtoinputsegment@line% - \let\pgf@decorate@splitinputsegmentobject\pgf@decorate@splitinputsegmentobject@line% + \let\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentlineto% } % Input segment object curveto. @@ -1275,7 +1364,7 @@ % \let\pgf@decorate@movealonginputsegment\pgf@decorate@movealonginputsegment@curve% \let\pgf@decorate@transformtoinputsegment\pgf@decorate@transformtoinputsegment@curve% - \let\pgf@decorate@splitinputsegmentobject\pgf@decorate@splitinputsegmentobject@curve% + \let\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentcurveto% } % Input segment object closepath. @@ -1287,18 +1376,33 @@ % \def\pgfdecoratedinputsegmentlength{#1}% \def\pgf@decorate@inputsegment@first{#2}% - \def\pgf@decorate@inputsegment@supporta{#3}% - \def\pgf@decorate@inputsegment@supportb{#2}% - \def\pgf@decorate@inputsegment@last{#3}% - % + \def\pgf@decorate@inputsegment@last{#3}% + % + \pgfpointdiff{#2}{#3}% + \pgf@xa\pgf@x% + \pgf@ya\pgf@y% + \pgfextract@process\pgf@decorate@inputsegment@supporta{% + \pgf@process{#2}% + \advance\pgf@x0.333333\pgf@xa% + \advance\pgf@y0.333333\pgf@ya% + }% + \pgfextract@process\pgf@decorate@inputsegment@supportb{% + \pgf@process{#2}% + \advance\pgf@x0.666666\pgf@xa% + \advance\pgf@y0.666666\pgf@ya% + }% + % \let\pgf@decorate@movealonginputsegment\pgf@decorate@movealonginputsegment@line% \let\pgf@decorate@transformtoinputsegment\pgf@decorate@transformtoinputsegment@line% - \let\pgf@decorate@splitinputsegmentobject\pgf@decorate@splitinputsegmentobject@line% + \let\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentclosepath% } + % Input segment object endofinputsegments. % -\def\pgf@decorate@inputsegmentobject@endofinputsegments{} +\def\pgf@decorate@inputsegmentobject@endofinputsegments{% + \let\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentlast% +} @@ -1493,7 +1597,7 @@ % \pgfpathlineto{\pgfpoint{12pt}{0pt}} % \pgfgetpath\softpath % -% \pgf@decorate@parsesoftpath{\softpath}{\parsedsoftpath}{} +% \pgf@decorate@parsesoftpath{\softpath}{\parsedsoftpath} % % results in: % @@ -1855,6 +1959,150 @@ } +% Macro to reverse a set of input segment objects. +% +% #1 - a macro holding the input segment objects. +% #2 - a macro holding the reversed input segment objects. +% +\def\pgf@decorate@inputsegmentobjects@reverse#1#2{% + \def\pgf@decorate@path@storein{#2}% + \def\pgf@decorate@inputsegments@@temp{}% + \expandafter\pgf@decorate@inputsegments@@reverse@pass@first#1\pgf@stop} + +\def\pgf@decorate@inputsegments@@reverse@pass@first#1#2\pgf@stop{% + \def\pgf@decorate@temp{#1}% + \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter% + \pgf@decorate@inputsegments@@temp\expandafter\expandafter\expandafter% + {\expandafter\pgf@decorate@temp\pgf@decorate@inputsegments@@temp}% + \def\pgf@decorate@test{#2} + \ifx\pgf@decorate@test\pgfutil@empty% + \def\pgf@decorate@next{% + \expandafter\pgf@decorate@inputsegmentobjects@reverse@pass@second\pgf@decorate@inputsegments@@temp\pgf@stop% + }% + \else% + \def\pgf@decorate@next{\pgf@decorate@inputsegments@@reverse@pass@first#2\pgf@stop}% + \fi% + \pgf@decorate@next% +} +\def\pgf@decorate@inputsegmentobjects@reverse@pass@second#1#2#3\pgf@stop{% + \def\pgf@decorate@inputsegments@temp{#3}% + \def\pgf@decorate@inputsegments@@temp{}% + \let\pgf@decorate@current@inputsegmentobject=\pgfutil@empty + \let\pgf@decorate@last@object=\pgfutil@empty + \pgf@decorate@inputsegmentobjects@reverse@moveto@waitingtrue% + \pgf@decorate@inputsegmentobjects@reverse@closepath@waitingfalse% + \expandafter\pgf@decorate@path@@reverse@pass@second\pgf@decorate@inputsegments@temp\pgf@stop}% + + +\def\pgf@decorate@path@@reverse@pass@second#1{% + \ifx#1\pgf@stop% + \expandafter\def\expandafter\pgf@decorate@inputsegments@@temp\expandafter{% + \pgf@decorate@inputsegments@@temp% + {\pgf@decorate@inputsegmentobject@endofinputsegments}% + {\pgf@decorate@inputsegmentobject@endofinputsegments} + }% + \expandafter\let\pgf@decorate@path@storein=\pgf@decorate@inputsegments@@temp% + \let\pgf@decorate@next=\relax% + \else% + \ifx#1\pgf@decorate@inputsegmentobject@moveto% + \let\pgf@decorate@next=\pgf@decorate@inputsegmentobjects@reverse@moveto% + \else% + \ifx#1\pgf@decorate@inputsegmentobject@lineto% + \let\pgf@decorate@next=\pgf@decorate@inputsegmentobjects@reverse@lineto% + \else% + \ifx#1\pgf@decorate@inputsegmentobject@curveto% + \let\pgf@decorate@next=\pgf@decorate@inputsegmentobjects@reverse@curveto% + \else% + \ifx#1\pgf@decorate@inputsegmentobject@closepath% + \let\pgf@decorate@next=\pgf@decorate@inputsegmentobjects@reverse@closepath% + \else% + \fi% + \fi% + \fi% + \fi% + \fi% + \pgf@decorate@next% +} + +\newif\ifpgf@decorate@inputsegmentobjects@reverse@moveto@waiting + +\def\pgf@decorate@inputsegmentobjects@reverse@moveto#1{% + \ifpgf@decorate@inputsegmentobjects@reverse@closepath@waiting% + \edef\pgf@decorate@current@inputsegmentobject{% + {\noexpand\pgf@decorate@inputsegmentobject@closepath% + {\pgf@decorate@reverse@closepath@length}% + {\pgf@decorate@last}% + {#1}% + }% + }% + \pgf@decorate@inputsegmentobjects@reverse@closepath@waitingfalse% + \else% + \let\pgf@decorate@current@inputsegmentobject=\pgfutil@empty% + \fi% + \pgf@decorate@inputsegmentobjects@reverse@moveto@waitingtrue% + \pgf@decorate@path@@@reverse@pass@second% +} + +\newif\ifpgf@decorate@inputsegmentobjects@reverse@closepath@waiting + +\def\pgf@decorate@inputsegmentobjects@reverse@closepath#1#2#3{% + \pgf@decorate@inputsegmentobjects@reverse@closepath@waitingtrue% + \def\pgf@decorate@reverse@closepath@length{#1}% + \def\pgf@decorate@current@inputsegmentobject{}% + \pgf@decorate@inputsegmentobjects@reverse@lineto{#1}{#2}{#3}% +} + +\def\pgf@decorate@inputsegmentobjects@reverse@lineto#1#2#3#4{% + \ifpgf@decorate@inputsegmentobjects@reverse@moveto@waiting% + \def\pgf@decorate@current@inputsegmentobject{{\pgf@decorate@inputsegmentobject@moveto{#3}}}% + \pgf@decorate@inputsegmentobjects@reverse@moveto@waitingfalse% + \else% + \let\pgf@decorate@current@inputsegmentobject=\pgfutil@empty% + \fi% + \def\pgf@decorate@append@inputsegmentobject{{\pgf@decorate@inputsegmentobject@lineto{#1}{#3}{#2}}}% + \ifx#4\pgf@decorate@inputsegmentobject@moveto% + \ifpgf@decorate@inputsegmentobjects@reverse@closepath@waiting% + \def\pgf@decorate@append@inputsegmentobject{{\pgf@decorate@inputsegmentobject@closepath{#1}{#3}{#2}}}% + \pgf@decorate@inputsegmentobjects@reverse@closepath@waitingfalse% + \else% + \def\pgf@decorate@append@inputsegmentobject{{\pgf@decorate@inputsegmentobject@lineto{#1}{#3}{#2}}}% + \fi% + \fi% + \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter% + \pgf@decorate@current@inputsegmentobject\expandafter\expandafter\expandafter% + {\expandafter\pgf@decorate@current@inputsegmentobject\pgf@decorate@append@inputsegmentobject} + \def\pgf@decorate@last{#2}% + \pgf@decorate@path@@@reverse@pass@second#4% +} + +\def\pgf@decorate@inputsegmentobjects@reverse@curveto#1#2#3#4#5{% + \ifpgf@decorate@inputsegmentobjects@reverse@moveto@waiting% + \def\pgf@decorate@current@inputsegmentobject{% + {\pgf@decorate@inputsegmentobject@moveto{#5}}% + {\pgf@decorate@inputsegmentobject@curveto{#1}{#5}{#4}{#3}{#2}}% + }% + \pgf@decorate@inputsegmentobjects@reverse@moveto@waitingfalse% + \else% + \def\pgf@decorate@current@inputsegmentobject{{\pgf@decorate@inputsegmentobject@curveto{#1}{#5}{#4}{#3}{#2}}}% + \fi% + \def\pgf@decorate@last{#2}% + \pgf@decorate@path@@@reverse@pass@second% +} + +\def\pgf@decorate@path@@@reverse@pass@second{% + \ifx\pgf@decorate@current@inputsegmentobject\pgfutil@empty% + \else% + \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter% + \pgf@decorate@inputsegments@@temp\expandafter\expandafter\expandafter% + {\expandafter\pgf@decorate@inputsegments@@temp\pgf@decorate@current@inputsegmentobject}% + \fi% + \pgf@decorate@path@@reverse@pass@second% +}% + + + + + \let\startpgfdecoration=\pgfdecoration \let\stoppgfdecoration=\endpgfdecoration |