% 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 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