summaryrefslogtreecommitdiff
path: root/graphics/pgf/base/doc/pgfmanual-en-base-shadings.tex
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/pgf/base/doc/pgfmanual-en-base-shadings.tex')
-rw-r--r--graphics/pgf/base/doc/pgfmanual-en-base-shadings.tex762
1 files changed, 762 insertions, 0 deletions
diff --git a/graphics/pgf/base/doc/pgfmanual-en-base-shadings.tex b/graphics/pgf/base/doc/pgfmanual-en-base-shadings.tex
new file mode 100644
index 0000000000..0d5497362a
--- /dev/null
+++ b/graphics/pgf/base/doc/pgfmanual-en-base-shadings.tex
@@ -0,0 +1,762 @@
+% 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 Free Documentation License.
+%
+% See the file doc/generic/pgf/licenses/LICENSE for more details.
+
+
+\section{Shadings}
+\label{section-shadings}
+
+\subsection{Overview}
+
+A shading is an area in which the color changes smoothly between different
+colors. Similarly to an image, a shading must first be declared before it can
+be used. Also similarly to an image, a shading is put into a \TeX-box. Hence,
+in order to include a shading in a |{pgfpicture}|, you have to use |\pgftext|
+around it.
+
+There are different kinds of shadings: horizontal, vertical, radial, and
+functional shadings. However, you can rotate and clip shadings like any other
+graphics object, which allows you to create more complicated shadings.
+Horizontal shadings could be created by rotating a vertical shading by 90
+degrees, but explicit commands for creating both horizontal and vertical
+shadings are included for convenience.
+
+Once you have declared a shading, you can insert it into the text using the
+command |\pgfuseshading|. This command cannot be used directly in a
+|{pgfpicture}|, you have to put a |\pgftext| around it. The second command for
+using shadings, |\pgfshadepath|, on the other hand, can only be used inside
+|{pgfpicture}| environments. It will ``fill'' the current path with the
+shading.
+
+A horizontal shading is a horizontal bar of a certain height whose color
+changes smoothly. You must at least specify the colors at the left and at the
+right end of the bar, but you can also add color specifications for points in
+between. For example, suppose you wish to create a bar that is red at the left
+end, green in the middle, and blue at the end, and you would like the bar to be
+4cm long. This could be specified as follows:
+%
+\begin{codeexample}[code only]
+rgb(0cm)=(1,0,0); rgb(2cm)=(0,1,0); rgb(4cm)=(0,0,1)
+\end{codeexample}
+%
+This line means that at 0cm (the left end) of the bar, the color should be red,
+which has red-green-blue (rgb) components (1,0,0). At 2cm, the bar should be
+green, and at 4cm it should be blue. Instead of |rgb|, you can currently also
+specify |cmyk| as color model, in which case four values are needed,
+|gray| as color model, in which case only one value is needed, or
+|color|, in which case you must provide the name of a color in parentheses. In
+a color specification the individual specifications must be separated using a
+semicolon, which may be followed by a whitespace (like a space or a newline).
+Individual specifications must be given in increasing order.
+
+\subsubsection{Color models}
+
+\noindent\emph{by David Purton}
+
+An attempt is made to produce shadings consistent with the currently selected
+|xcolor| package color model. The |rgb|, |cmyk|, and |gray| color models from
+the |xcolor| package are supported.
+
+\textbf{Note:} The color model chosen for a shading is based on the |xcolor|
+color model \emph{at the time the shading is created}. This is either when
+|\pgfdeclare*shading| is called with no optional argument or when
+|\pgfuseshading| is called if |\pgfdeclare*shading| was called with an
+optional argument.
+
+If the |xcolor| package |natural| color model is in use then the shading color
+model will be \textsc{rgb} by default. In practice this means that if you are
+using the |natural| color model of the |xcolor| package you can get mismatched
+colors if you, for example, create a shading from green (which is defined as
+\textsc{rgb}) to magenta (which is defined as \textsc{cmyk}). The shading will
+finish with \textsc{rgb} magenta which will look different to the
+\textsc{cmyk} magenta used in solid colors.
+
+You can avoid mismatched colors by loading the |xcolor| package first with an
+explicit color model (|rgb|, |cmyk|, or |gray|).
+
+\begin{codeexample}[code only]
+\begin{tikzpicture}
+ \fill[green] (0,0) rectangle (1,1);
+ \shade[left color=green, right color=magenta] (1.25,0) rectangle (3.75,1);
+ \fill[magenta] (4,0) rectangle (5,1);
+\end{tikzpicture}
+\end{codeexample}
+
+\begin{center}
+ \begin{minipage}{5cm}
+ |xcolor| |natural| color model:\medskip
+
+ \begin{tikzpicture}
+ \fill[green] (0,0) rectangle (1,1);
+ \shade[left color=green, right color=magenta] (1.25,0) rectangle (3.75,1);
+ \fill[magenta] (4,0) rectangle (5,1);
+ \end{tikzpicture}
+ \end{minipage}\hspace{2cm}%
+ \begin{minipage}{5cm}
+ |xcolor| |cmyk| color model:\medskip
+
+ \selectcolormodel{cmyk}
+ \begin{tikzpicture}
+ \fill[green] (0,0) rectangle (1,1);
+ \shade[left color=green, right color=magenta] (1.25,0) rectangle (3.75,1);
+ \fill[magenta] (4,0) rectangle (5,1);
+ \end{tikzpicture}
+ \end{minipage}\medskip
+
+ \begin{minipage}{5cm}
+ |xcolor| |rgb| color model:\medskip
+
+ \selectcolormodel{rgb}
+ \begin{tikzpicture}
+ \fill[green] (0,0) rectangle (1,1);
+ \shade[left color=green, right color=magenta] (1.25,0) rectangle (3.75,1);
+ \fill[magenta] (4,0) rectangle (5,1);
+ \end{tikzpicture}
+ \end{minipage}\hspace{2cm}%
+ \begin{minipage}{5cm}
+ |xcolor| |gray| color model:\medskip
+
+ \selectcolormodel{gray}
+ \begin{tikzpicture}
+ \fill[green] (0,0) rectangle (1,1);
+ \shade[left color=green, right color=magenta] (1.25,0) rectangle (3.75,1);
+ \fill[magenta] (4,0) rectangle (5,1);
+ \end{tikzpicture}
+ \end{minipage}
+\end{center}
+
+\subsection{Declaring Shadings}
+
+\subsubsection{Horizontal and Vertical Shadings}
+
+\begin{command}{\pgfdeclarehorizontalshading\oarg{color list}\marg{shading name}\marg{shading height}\marg{color specification}}
+ Declares a horizontal shading named \meta{shading name} of the specified
+ \meta{height} with the specified colors. The width of the bar is deduced
+ automatically from the maximum dimension in the specification.
+ %
+\begin{codeexample}[]
+\pgfdeclarehorizontalshading{myshadingA}
+ {1cm}{rgb(0cm)=(1,0,0); color(2cm)=(green); color(4cm)=(blue)}
+\pgfuseshading{myshadingA}
+\end{codeexample}
+
+ The effect of the \meta{color list}, which is a comma-separated list of
+ colors, is the following: Normally, when this list is empty, once a shading
+ has been declared, it becomes ``frozen''. This means that even if you
+ change a color that was used in the declaration of the shading later on,
+ the shading will not change. By specifying a \meta{color list} you can
+ specify that the shading should be recalculated whenever one of the colors
+ listed in the list changes (this includes effects like color mixins and
+ |xcolor| color models). Thus, when you specify a \meta{color list},
+ whenever the shading is used, \pgfname\ first converts the colors in the
+ list to tuples in the current |xcolor| color model using the current
+ values of the colors and taking any mixins and blends into account. If the
+ resulting tuples have not yet been used,
+ a new shading is internally created and used. Note that if the option
+ \meta{color list} is used, then no shading is created until the first use
+ of |\pgfuseshading|. In particular, the colors mentioned in the shading
+ need not be defined when the declaration is given.
+
+ When a shading is recalculated because of a change in the colors mentioned
+ in \meta{color list}, the complete shading is recalculated. Thus even
+ colors not mentioned in the list will be used with their current values,
+ not with the values they had upon declaration.
+ %
+\begin{codeexample}[]
+\pgfdeclarehorizontalshading[mycolor]{myshadingB}
+ {1cm}{rgb(0cm)=(1,0,0); color(2cm)=(mycolor)}
+\colorlet{mycolor}{green}
+\pgfuseshading{myshadingB}
+\colorlet{mycolor}{blue}
+\pgfuseshading{myshadingB}
+\end{codeexample}
+ %
+\end{command}
+
+\begin{command}{\pgfdeclareverticalshading\oarg{color list}\marg{shading name}\marg{shading width}\marg{color specification}}
+ Declares a vertical shading named \meta{shading name} of the specified
+ \meta{width}. The height of the bar is deduced automatically. The effect of
+ \meta{color list} is the same as for horizontal shadings.
+ %
+\begin{codeexample}[]
+\pgfdeclareverticalshading{myshadingC}
+ {4cm}{rgb(0cm)=(1,0,0); rgb(1.5cm)=(0,1,0); rgb(2cm)=(0,0,1)}
+\pgfuseshading{myshadingC}
+\end{codeexample}
+ %
+\end{command}
+
+
+\subsubsection{Radial Shadings}
+
+\begin{command}{\pgfdeclareradialshading\oarg{color list}\marg{shading name}\marg{center point}\marg{color specification}}
+ Declares a radial shading. A radial shading is a circle whose inner color
+ changes as specified by the color specification. Assuming that the center
+ of the shading is at the origin, the color of the center will be the color
+ specified for 0cm and the color of the border of the circle will be the
+ color for the maximum dimension given in the \meta{color specified}. This
+ maximum will also be the radius of the circle. If the \meta{center point}
+ is not at the origin, the whole shading inside the circle (whose size
+ remains exactly the same) will be distorted such that the given center now
+ has the color specified for 0cm. The effect of \meta{color list} is the
+ same as for horizontal shadings.
+ %
+\begin{codeexample}[]
+\pgfdeclareradialshading{sphere}{\pgfpoint{0.5cm}{0.5cm}}%
+ {rgb(0cm)=(0.9,0,0);
+ rgb(0.7cm)=(0.7,0,0);
+ rgb(1cm)=(0.5,0,0);
+ rgb(1.05cm)=(1,1,1)}
+\pgfuseshading{sphere}
+\end{codeexample}
+ %
+\end{command}
+
+
+\subsubsection{General (Functional) Shadings}
+
+\begin{command}{\pgfdeclarefunctionalshading\oarg{color list}\marg{shading
+ name}\marg{lower left corner}\marg{upper right corner}\\
+ \marg{init code}\marg{type 4 function}%
+}
+ \emph{Warning: These shadings are the least portable of all and they put
+ the heaviest burden of the renderer. They are slow and, possibly, will not
+ print correctly!}
+
+ This command creates a \emph{functional shading}. For such a shading, the
+ color of each point is calculated by calling a function that takes the
+ coordinates of the point as input and yields the color as an output. Note
+ that the function is evaluated by the \emph{renderer}, not by \pgfname\ or
+ \TeX\ or someone else at compile-time. This means that the evaluation of
+ this function has to be done \emph{extremely quickly} and the function
+ should be \emph{very simple}. For this reason, only a very restricted set
+ of operations are possible in the function and functions should be kept
+ small. Any errors in the function will only be noticed by the renderer.
+
+ The syntax for specifying functions is the following: You use a simplified
+ form of a subset of the PostScript language. This subset will be understood
+ by the PDF-renderer (yes, PDF-renderers do have a basic understanding of
+ PostScript) and also by PostScript renders. This subset is detailed in
+ Section~3.9.4 of the PDF-specification (version~1.7). In essence, the
+ specification states that these functions may contain ``expressions
+ involving integers, real numbers, and boolean values only. There are no
+ composite data structures such as strings or arrays, no procedures, and no
+ variables or names.'' The allowed operators are (exactly) the following:
+ \texttt{abs}, \texttt{add}, \texttt{atan}, \texttt{ceiling}, \texttt{cos},
+ \texttt{cvi}, \texttt{cvr}, \texttt{div}, \texttt{exp}, \texttt{floor},
+ \texttt{idiv}, \texttt{ln}, \texttt{log}, \texttt{mod}, \texttt{mul},
+ \texttt{neg}, \texttt{round}, \texttt{sin}, \texttt{sqrt}, \texttt{sub},
+ \texttt{truncate}, \texttt{and}, \texttt{bitshift}, \texttt{eq},
+ \texttt{false}, \texttt{ge}, \texttt{gt}, \texttt{le}, \texttt{lt},
+ \texttt{ne}, \texttt{not}, \texttt{or}, \texttt{true}, \texttt{xor},
+ \texttt{if}, \texttt{ifelse}, \texttt{copy}, \texttt{dup}, \texttt{exch},
+ \texttt{index}, \texttt{pop}.
+
+ When the function is evaluated, the top two stack elements are the
+ coordinates of the point for which the color should be computed. The
+ coordinates are dimensionless and given in big points, so for the
+ coordinate $(50bp, 72.27pt)$ the top two stack elements would be
+ \texttt{50.0} and \texttt{72.0}. Otherwise, the (virtual) stack is empty
+ (or should be treated as if it were empty). The function should then
+ replace these two values by three values, representing the red, green, and
+ blue color of the point for an \textsc{rgb} shading, four colors,
+ representing the cyan, magenta, yellow, and black color of the point for a
+ \textsc{cmyk} shading, or one value representing the gray color for a
+ grayscale shading. The numbers should be real values, not integers
+ since, Apple's PDF renderer is broken in this regard (use \texttt{cvr} at
+ the end if necessary).
+
+ Conceptually, the function will be evaluated once for each point of the
+ rectangle \meta{lower left corner} to \meta{upper right corner}, which
+ should be a \pgfname-point expression like |\pgfpoint{100bp}{100bp}|. 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
+ \emph{if you know what you are doing} (or if you are adventurous, of
+ course).
+
+ As for other shadings, the optional \meta{color list} is used to determine
+ whether a shading needs to be recalculated when a color has changed.
+
+ The \meta{init code} is executed each time a shading is (re)calculated.
+ Typically, it will contain code to extract coordinates from colors.
+ %
+\begin{codeexample}[]
+\pgfdeclarefunctionalshading{twospots}
+ {\pgfpointorigin}{\pgfpoint{4cm}{4cm}}{}{
+ % Save coordinates for later
+ 2 copy
+ % Compute distance from (40bp,45bp), with x doubled
+ 45 sub dup mul exch
+ 40 sub dup mul 0.5 mul add sqrt
+ % exponential decay
+ dup mul neg 1.0005 exch exp 1.0 exch sub
+ % Compute distance from (70bp,70bp) from stored coordinate, scaled
+ 3 1 roll
+ 70 sub dup mul .5 mul exch
+ 70 sub dup mul add sqrt
+ % Decay
+ dup mul neg 1.002 exch exp 1.0 exch sub
+ % red component
+ 1.0 3 1 roll
+}
+\pgfuseshading{twospots}
+\end{codeexample}
+
+ Inside the PostScript function \meta{type 4 function} you cannot use colors
+ directly. Rather, you must push the color components on the stack. For
+ this, it is useful to call one of |\pgfshadecolortorgb|,
+ |\pgfshadecolortocmyk|, or |\pgfshadecolortogray| in the \meta{init code}:
+
+ \begin{command}{\pgfshadecolortorgb\marg{color name}\marg{macro}}
+ This command takes \meta{color name} as input, converts it to
+ \textsc{rgb} and stores the color's
+ red/green/blue components 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 \meta{macro}. This macro can then be used inside the
+ \meta{type 4 function} argument for |\pgfdeclarefunctionalshading|.
+ %
+\begin{codeexample}[]
+\pgfdeclarefunctionalshading[mycol]{sweep}{\pgfpoint{-1cm}{-1cm}}
+{\pgfpoint{1cm}{1cm}}{\pgfshadecolortorgb{mycol}{\myrgb}}{
+ 2 copy % whirl
+ % Calculate "safe" atan of position
+ 2 copy abs exch abs add 0.0001 ge { atan } { pop } ifelse
+ 3 1 roll
+ dup mul exch
+ dup mul add sqrt
+ 30 mul
+ add
+ sin
+ 1 add 2 div
+ 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
+}
+\colorlet{mycol}{white}%
+\pgfuseshading{sweep}%
+\colorlet{mycol}{red}%
+\pgfuseshading{sweep}
+\end{codeexample}
+
+ In addition, three macros suffixed with |red|, |green| and |blue| are
+ defined, which store the individual components of \meta{color name}.
+ These can also be used in the \meta{type 4 function} argument.
+ %
+\begin{codeexample}[]
+\pgfshadecolortorgb{orange}{\mycol}
+|\mycol|=\mycol |\mycolred|=\mycolred |\mycolgreen|=\mycolgreen |\mycolblue|=\mycolblue
+\end{codeexample}
+ \end{command}
+
+\begin{codeexample}[]
+\pgfdeclarefunctionalshading[col1,col2,col3,col4]{bilinear interpolation}
+{\pgfpointorigin}{\pgfpoint{100bp}{100bp}}
+{
+\pgfshadecolortorgb{col1}{\first}\pgfshadecolortorgb{col2}{\second}
+\pgfshadecolortorgb{col3}{\third}\pgfshadecolortorgb{col4}{\fourth}
+}{
+ 100 div exch 100 div 2 copy % Calculate y/100 x/100.
+ neg 1 add exch neg 1 add % Calculate 1-y/100 1-x/100.
+ 3 1 roll 2 copy exch 5 2 roll 6 copy 6 copy % Set up stack.
+ \firstred mul exch \secondred mul add mul % Process red component.
+ 4 1 roll
+ \thirdred mul exch \fourthred mul add mul
+ add
+ 13 1 roll
+ \firstgreen mul exch \secondgreen mul add mul % Process green component.
+ 4 1 roll
+ \thirdgreen mul exch \fourthgreen mul add mul
+ add
+ 7 1 roll
+ \firstblue mul exch \secondblue mul add mul % Process blue component.
+ 4 1 roll
+ \thirdblue mul exch \fourthblue mul add mul
+ add
+}
+
+\colorlet{col1}{blue}
+\colorlet{col2}{yellow}
+\colorlet{col3}{red}
+\colorlet{col4}{green}
+\pgfuseshading{bilinear interpolation}
+\end{codeexample}
+
+ \begin{command}{\pgfshadecolortocmyk\marg{color name}\marg{macro}}
+ This command takes \meta{color name} as input, converts it to
+ \textsc{cmyk} and stores the color's cyan/magenta/yellow/black
+ components real numbers between 0.0 and 1.0 separated by spaces.
+
+ In addition, four macros suffixed with |cyan|, |magenta|, |yellow| and
+ |black| are defined, which store the individual components of
+ \meta{color name}.
+ %
+ \end{command}
+
+ \begin{command}{\pgfshadecolortogray\marg{color name}\marg{macro}}
+ This command takes \meta{color name} as input converts it to grayscale
+ and stores the color's value as a real number between 0.0 and 1.0.
+
+ Although it's not needed, for consistency a second macro suffixed with
+ |gray| is also defined.
+ %
+ \end{command}
+ %
+\end{command}
+
+\paragraph{Color model independent functional shadings.}
+
+By nature, the PostScript code used in functional shadings must output one of
+\textsc{rgb}, \textsc{cmyk}, or grayscale data. Therefore,
+|\pgfdeclarefunctionalshading| is \emph{not} portable across color models.
+
+Take particular care that the same color model is in use at declaration time
+and use time for functional shadings declared with an optional argument as
+otherwise the PostScript data will not match the declared color space and
+you will end up with a malformed PDF.
+
+Having said this, it \emph{is} possible to create portable functional shadings
+by providing conditional code to append color transformations to the
+PostScript data. A variety of |\pgffuncshading*to*| (e.g.,
+|\pgffuncshadingrgbtocmyk|) macros along with |\ifpgfshadingmodel*| (e.g.,
+|\ifpgfshadingmodelcmyk|) conditionals are provided to assist with these
+transformations. Obviously, this will make the PostScript code less efficient
+than if you work in your intended color model.
+
+\pgfdeclarefunctionalshading[black]{portabletwospots}
+ {\pgfpointorigin}{\pgfpoint{3.5cm}{3.5cm}}{}{
+ 2 copy
+ 45 sub dup mul exch
+ 40 sub dup mul 0.5 mul add sqrt
+ dup mul neg 1.0005 exch exp 1.0 exch sub
+ 3 1 roll
+ 70 sub dup mul .5 mul exch
+ 70 sub dup mul add sqrt
+ dup mul neg 1.002 exch exp 1.0 exch sub
+ 1.0 3 1 roll
+ \ifpgfshadingmodelcmyk
+ \pgffuncshadingrgbtocmyk
+ \fi
+ \ifpgfshadingmodelgray
+ \pgffuncshadingrgbtogray
+ \fi
+}
+\begin{center}
+ \begin{minipage}{3.5cm}
+ |xcolor| |rgb| model:\medskip
+
+ \selectcolormodel{rgb}
+ \pgfuseshading{portabletwospots}
+ \end{minipage}\hspace{2cm}
+ \begin{minipage}{3.5cm}
+ |xcolor| |cmyk| model:\medskip
+
+ \selectcolormodel{cmyk}
+ \pgfuseshading{portabletwospots}
+ \end{minipage}\hspace{2cm}
+ \begin{minipage}{3.5cm}
+ |xcolor| |gray| model:\medskip
+
+ \selectcolormodel{gray}
+ \pgfuseshading{portabletwospots}
+ \end{minipage}
+\end{center}
+
+\begin{codeexample}[code only]
+\pgfdeclarefunctionalshading[black]{portabletwospots}{\pgfpointorigin}{\pgfpoint{3.5cm}{3.5cm}}{}{
+ 2 copy
+ 45 sub dup mul exch
+ 40 sub dup mul 0.5 mul add sqrt
+ dup mul neg 1.0005 exch exp 1.0 exch sub
+ 3 1 roll
+ 70 sub dup mul .5 mul exch
+ 70 sub dup mul add sqrt
+ dup mul neg 1.002 exch exp 1.0 exch sub
+ 1.0 3 1 roll
+ \ifpgfshadingmodelcmyk
+ \pgffuncshadingrgbtocmyk
+ \fi
+ \ifpgfshadingmodelgray
+ \pgffuncshadingrgbtogray
+ \fi
+}
+\end{codeexample}
+
+\begin{command}{\pgffuncshadingrgbtocmyk}
+ Within the \meta{type 4 function} argument of
+ |\pgfdeclarefunctionalshading|, this command can be used to convert the
+ top 3 elements on the stack from \textsc{rgb} to \textsc{cmyk}. In
+ combination with the |\ifpgfshadingmodelcmyk| conditional this macro can
+ be used to make functional shading declarations more portable across color
+ models.
+\end{command}
+
+\begin{command}{\pgffuncshadingrgbtogray}
+ Within the \meta{type 4 function} argument of
+ |\pgfdeclarefunctionalshading|, this command can be used to convert the
+ top 3 elements on the stack from \textsc{rgb} to grayscale. In combination
+ with the |\ifpgfshadingmodelgray| conditional this macro can be used to
+ make functional shading declarations more portable across color models.
+\end{command}
+
+\begin{command}{\pgffuncshadingcmyktorgb}
+ Within the \meta{type 4 function} argument of
+ |\pgfdeclarefunctionalshading|, this command can be used to convert the
+ top 4 elements on the stack from \textsc{cmyk} to \textsc{rgb}. In
+ combination with the |\ifpgfshadingmodelrgb| conditional this macro can be
+ used to make functional shading declarations more portable across color
+ models.
+\end{command}
+
+\begin{command}{\pgffuncshadingcmyktogray}
+ Within the \meta{type 4 function} argument of
+ |\pgfdeclarefunctionalshading|, this command can be used to convert the
+ top 4 elements on the stack from \textsc{cmyk} to grayscale. In combination
+ with the |\ifpgfshadingmodelgray| conditional this macro can be used to
+ make functional shading declarations more portable across color models.
+\end{command}
+
+\begin{command}{\pgffuncshadinggraytorgb}
+ Within the \meta{type 4 function} argument of
+ |\pgfdeclarefunctionalshading|, this command can be used to convert the
+ top element on the stack from grayscale to \textsc{rgb}. In combination with
+ the |\ifpgfshadingmodelrgb| conditional this macro can be used to make
+ functional shading declarations more portable across color models.
+\end{command}
+
+\begin{command}{\pgffuncshadinggraytocmyk}
+ Within the \meta{type 4 function} argument of
+ |\pgfdeclarefunctionalshading|, this command can be used to convert the
+ top element on the stack from grayscale to \textsc{cmyk}. In combination
+ with the |\ifpgfshadingmodelcmyk| conditional this macro can be used to
+ make functional shading declarations more portable across color models.
+\end{command}
+
+{\let\ifpgfshadingmodelrgb=\relax
+ \let\ifpgfshadingmodelcmyk=\relax
+ \let\ifpgfshadingmodelgray=\relax
+ \begin{command}{\ifpgfshadingmodelrgb}
+ Within the \meta{type 4 function} argument of
+ |\pgfdeclarefunctionalshading|, this command can be used to test if the
+ |xcolor| color model is |rgb| \emph{at the time the shading is created}.
+ This can be used to ensure that the data output in the \meta{type 4
+ function} correctly matches the active color model.
+ \end{command}
+
+ \begin{command}{\ifpgfshadingmodelcmyk}
+ Within the \meta{type 4 function} argument of
+ |\pgfdeclarefunctionalshading|, this command can be used to test if the
+ |xcolor| color model is |cmyk| \emph{at the time the shading is created}.
+ This can be used to ensure that the data output in the \meta{type 4
+ function} correctly matches the active color model.
+ \end{command}
+
+ \begin{command}{\ifpgfshadingmodelgray}
+ Within the \meta{type 4 function} argument of
+ |\pgfdeclarefunctionalshading|, this command can be used to test if the
+ |xcolor| color model is |gray| \emph{at the time the shading is created}.
+ This can be used to ensure that the data output in the \meta{type 4
+ function} correctly matches the active color model.
+ \end{command}
+}
+
+\subsection{Using Shadings}
+\label{section-shading-a-path}
+
+\begin{command}{\pgfuseshading\marg{shading name}}
+ Inserts a previously declared shading into the text. If you wish to use it
+ in a |pgfpicture| environment, you should put a |\pgftext| around it.
+ %
+\begin{codeexample}[]
+\begin{pgfpicture}
+ \pgfdeclareverticalshading{myshadingD}
+ {20pt}{color(0pt)=(red); color(20pt)=(blue)}
+ \pgftext[at=\pgfpoint{1cm}{0cm}] {\pgfuseshading{myshadingD}}
+ \pgftext[at=\pgfpoint{2cm}{0.5cm}]{\pgfuseshading{myshadingD}}
+\end{pgfpicture}
+\end{codeexample}
+ %
+\end{command}
+
+\begin{command}{\pgfshadepath\marg{shading name}\marg{angle}}
+ This command must be used inside a |{pgfpicture}| environment. The effect
+ is a bit complex, so let us go over it step by step.
+
+ First, \pgfname\ will set up a local scope.
+
+ Second, it uses the current path to clip everything inside this scope.
+ However, the current path is once more available after the scope, so it can
+ be used, for example, to stroke it.
+
+ Now, the \meta{shading name} should be a shading whose width and height are
+ 100\,bp, that is, 100 big points. \pgfname\ has a look at the bounding box
+ of the current path. This bounding box is computed automatically when a
+ path is computed; however, it can sometimes be (quite a bit) too large,
+ especially when complicated curves are involved.
+
+ Inside the scope, the low-level transformation matrix is modified. The
+ center of the shading is translated (moved) such that it lies on the center
+ of the bounding box of the path. The low-level coordinate system is also
+ scaled such that the shading ``covers'' the path (the details are a bit
+ more complex, see below). Then, the coordinate system is rotated by
+ \meta{angle}. Finally, if the macro |\pgfsetadditionalshadetransform| has
+ been used, an additional transformation is applied.
+
+ After everything has been set up, the shading is inserted. Due to the
+ transformations and clippings, the effect will be that the shading seems
+ to ``fill'' the path.
+
+ If both the path and the shadings were always rectangles and if rotations
+ were never involved, it would be easy to scale shadings such they always
+ cover the path. However, when a vertical shading is rotated, it must
+ obviously be ``magnified'' so that it still covers the path. Things get
+ worse when the path is not a rectangle itself.
+
+ For these reasons, things work slightly differently ``in reality''. The
+ shading is scaled and translated such that the point
+ $(50\mathrm{bp},50\mathrm{bp})$, which is the middle of the shading, is at
+ the middle of the path and such that the point
+ $(25\mathrm{bp},25\mathrm{bp})$ is at the lower left corner of the path and
+ that $(75\mathrm{bp},75\mathrm{bp})$ is at upper right corner.
+
+ In other words, only the center quarter of the shading will actually
+ ``survive the clipping'' if the path is a rectangle. If the path is not a
+ rectangle, but, say, a circle, even less is seen of the shading. Here is an
+ example that demonstrates this effect:
+ %
+\begin{codeexample}[]
+\pgfdeclareverticalshading{myshadingE}{100bp}
+ {color(0bp)=(red); color(25bp)=(green); color(75bp)=(blue); color(100bp)=(black)}
+\pgfuseshading{myshadingE}
+\hskip 1cm
+\begin{pgfpicture}
+ \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{2cm}{1cm}}
+ \pgfshadepath{myshadingE}{0}
+ \pgfusepath{stroke}
+ \pgfpathrectangle{\pgfpoint{3cm}{0cm}}{\pgfpoint{1cm}{2cm}}
+ \pgfshadepath{myshadingE}{0}
+ \pgfusepath{stroke}
+ \pgfpathrectangle{\pgfpoint{5cm}{0cm}}{\pgfpoint{2cm}{2cm}}
+ \pgfshadepath{myshadingE}{45}
+ \pgfusepath{stroke}
+ \pgfpathcircle{\pgfpoint{9cm}{1cm}}{1cm}
+ \pgfshadepath{myshadingE}{45}
+ \pgfusepath{stroke}
+\end{pgfpicture}
+\end{codeexample}
+
+ As can be seen above in the last case, the ``hidden'' part of the shading
+ actually \emph{can} become visible if the shading is rotated. The reason is
+ that it is scaled as if no rotation took place, then the rotation is done.
+
+ The following graphics show which part of the shading are actually shown:
+ %
+\begin{codeexample}[]
+\pgfdeclareverticalshading{myshadingF}{100bp}
+ {color(0bp)=(red); color(25bp)=(green); color(75bp)=(blue); color(100bp)=(black)}
+\begin{tikzpicture}
+ \draw (50bp,50bp) node {\pgfuseshading{myshadingF}};
+ \draw[white,thick] (25bp,25bp) rectangle (75bp,75bp);
+ \draw (50bp,0bp) node[below] {first two applications};
+
+ \begin{scope}[xshift=5cm]
+ \draw (50bp,50bp) node{\pgfuseshading{myshadingF}};
+ \draw[rotate around={45:(50bp,50bp)},white,thick] (25bp,25bp) rectangle (75bp,75bp);
+ \draw (50bp,0bp) node[below] {third application};
+ \end{scope}
+
+ \begin{scope}[xshift=10cm]
+ \draw (50bp,50bp) node{\pgfuseshading{myshadingF}};
+ \draw[white,thick] (50bp,50bp) circle (25bp);
+ \draw (50bp,0bp) node[below] {fourth application};
+ \end{scope}
+\end{tikzpicture}
+\end{codeexample}
+
+ An advantage of this approach is that when you rotate a radial shading, no
+ distortion is introduced:
+ %
+\begin{codeexample}[]
+\pgfdeclareradialshading{ballshading}{\pgfpoint{-10bp}{10bp}}
+ {color(0bp)=(red!15!white); color(9bp)=(red!75!white);
+ color(18bp)=(red!70!black); color(25bp)=(red!50!black); color(50bp)=(black)}
+\pgfuseshading{ballshading}
+\hskip 1cm
+\begin{pgfpicture}
+ \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{1cm}{1cm}}
+ \pgfshadepath{ballshading}{0}
+ \pgfusepath{}
+ \pgfpathcircle{\pgfpoint{3cm}{0cm}}{1cm}
+ \pgfshadepath{ballshading}{0}
+ \pgfusepath{}
+ \pgfpathcircle{\pgfpoint{6cm}{0cm}}{1cm}
+ \pgfshadepath{ballshading}{45}
+ \pgfusepath{}
+\end{pgfpicture}
+\end{codeexample}
+
+ If you specify a rotation of $90^\circ$ and if the path is not a square,
+ but an elongated rectangle, the ``desired'' effect results: The shading
+ will exactly vary between the colors at the 25bp and 75bp boundaries. Here
+ is an example:
+ %
+\begin{codeexample}[]
+\pgfdeclareverticalshading{myshadingG}{100bp}
+ {color(0bp)=(red); color(25bp)=(green); color(75bp)=(blue); color(100bp)=(black)}
+\begin{pgfpicture}
+ \pgfpathrectangle{\pgfpointorigin}{\pgfpoint{2cm}{1cm}}
+ \pgfshadepath{myshadingG}{0}
+ \pgfusepath{stroke}
+ \pgfpathrectangle{\pgfpoint{3cm}{0cm}}{\pgfpoint{2cm}{1cm}}
+ \pgfshadepath{myshadingG}{90}
+ \pgfusepath{stroke}
+ \pgfpathrectangle{\pgfpoint{6cm}{0cm}}{\pgfpoint{2cm}{1cm}}
+ \pgfshadepath{myshadingG}{45}
+ \pgfusepath{stroke}
+\end{pgfpicture}
+\end{codeexample}
+
+ As a final example, let us define a ``rainbow spectrum'' shading for use
+ with \tikzname.
+ %
+\begin{codeexample}[]
+\pgfdeclareverticalshading{rainbow}{100bp}
+ {color(0bp)=(red); color(25bp)=(red); color(35bp)=(yellow);
+ color(45bp)=(green); color(55bp)=(cyan); color(65bp)=(blue);
+ color(75bp)=(violet); color(100bp)=(violet)}
+\begin{tikzpicture}[shading=rainbow]
+ \shade (0,0) rectangle node[white] {\textsc{pride}} (2,1);
+ \shade[shading angle=90] (3,0) rectangle +(1,2);
+\end{tikzpicture}
+\end{codeexample}
+
+ Note that rainbow shadings are \emph{way} too colorful in almost all
+ applications.
+\end{command}
+
+\begin{command}{\pgfsetadditionalshadetransform\marg{transformation}}
+ This command allows you to specify an additional transformation that should
+ be applied to shadings when the |\pgfshadepath| command is used. The
+ \meta{transformation} should be transformation code like
+ |\pgftransformrotate{20}|.
+\end{command}
+
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: "pgfmanual"
+%%% End: