% Copyright 2019 by Till Tantau and others % 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{pgflibraryshadings.code.tex} % % An hsv color wheel. Initial code graciously donated by Ken Starks. % \pgfdeclarefunctionalshading[black]{color wheel white center} {\pgfpoint{-50bp}{-50bp}} {\pgfpoint{50bp}{50bp}} {} { % x y 2 copy % ... x y x y 2 copy abs exch abs add 0.0001 ge {atan 360.0 div} % ... x y heading; heading being in %the interval [0, 1.0] { pop } % silently deal with error: return % arbitrary heading of zero for origin ifelse % because we will use it for 'Hue' 3 1 roll % ... heading x y dup mul % ... heading x y*y exch dup mul % ... heading y*y x*x add sqrt % ... heading ra_pt (distance from origin in points) 25.0 div % scale it means a ra of 25bp dup 1.0 ge % BOOLEAN. ready to clamp to interval [0, 1.0] { pop 1.0 }{} ifelse % We shall use the scaled ra as 'Saturation' %2.5 mul 0.25 sub % now, Ra in [0.1, 0.5] --> Saturation % in [0.0, 1.0]. Saturation varies between the two radii 1.0 % ... H S V ( with 'Value' set to literal constant of 1.0 ) % C version to use as model: % H' = H * 6 % i = floor(H') % f = H' - i % P = V * (1.0 - S) % Q = V * (1.0 - (S*f)) % T = V * (1.0 - (S * (1.0 - f))) 3 2 roll 6.0 mul dup 4 1 roll % H' S V H' floor cvr % H' S V i dup 5 1 roll % i H' S V i 3 index sub neg % i H' S V f 1.0 3 index sub % i H' S V f (1.0 - S ) 2 index mul % i H' S V f P 6 1 roll % P i H' S V f dup 3 index mul neg 1.0 add % P i H' S V f ( 1.0 - (f*S)) 2 index mul % P i H' S V f Q 7 1 roll % Q P i H' S V f neg 1.0 add % Q P i H' S V (1.0 - f) 2 index mul neg 1.0 add % Q P i H' S V (1.0 - S * (1.0 - f)) 1 index mul % Q P i H' S V T 7 2 roll % V T Q P i H' S pop pop % V T Q P i %%% % end of BLOCK B. The rest is just stack manipulation dup 0.5 le % TEST II [ i == 0 ] { % BLOCK C [ take stack to V T P ] pop exch pop } { dup 1.5 le % TEST III [ i == 1 ] { % BLOCK D [ take stack to Q V P ] pop exch 4 1 roll exch pop } { dup 2.5 le % TEST IV [ i == 2 ] { % BLOCK E [ take stack to P V T ] pop 4 1 roll pop } { dup 3.5 le % TEST V [ i == 3 ] { % BLOCK F [ take stack to P Q V ] pop exch 4 2 roll pop } { dup 4.5 le % TEST VI [ i == 4 ] { % BLOCK G [ take stack to T P V ] pop exch pop 3 -1 roll } { % BLOCK H [ take stack to V P Q ] pop 3 1 roll exch pop } ifelse } ifelse % for V } ifelse % for IV } ifelse % for III } ifelse % for II \ifpgfshadingmodelcmyk \pgffuncshadingrgbtocmyk \fi \ifpgfshadingmodelgray \pgffuncshadingrgbtogray \fi }% \pgfdeclarefunctionalshading[black]{color wheel black center} {\pgfpoint{-50bp}{-50bp}} {\pgfpoint{50bp}{50bp}} {} { % x y 2 copy % ... x y x y 2 copy abs exch abs add 0.0001 ge {atan 360.0 div} % ... x y heading; heading being in %the interval [0, 1.0] { pop } % silently deal with error: return % arbitrary heading of zero for origin ifelse % because we will use it for 'Hue' 3 1 roll % ... heading x y dup mul % ... heading x y*y exch dup mul % ... heading y*y x*x add sqrt % ... heading ra_pt (distance from origin in points) 25.0 div % scale it means a ra of 25bp dup 1.0 ge % BOOLEAN. ready to clamp to interval [0, 1.0] { pop 1.0 }{} ifelse % We shall use the scaled ra as 'Saturation' %2.5 mul 0.25 sub % now, Ra in [0.1, 0.5] --> Saturation % in [0.0, 1.0]. Saturation varies between the two radii 1.0 exch % ... H S V ( with 'Value' set to literal constant of 1.0 ) % C version to use as model: % H' = H * 6 % i = floor(H') % f = H' - i % P = V * (1.0 - S) % Q = V * (1.0 - (S*f)) % T = V * (1.0 - (S * (1.0 - f))) 3 2 roll 6.0 mul dup 4 1 roll % H' S V H' floor cvr % H' S V i dup 5 1 roll % i H' S V i 3 index sub neg % i H' S V f 1.0 3 index sub % i H' S V f (1.0 - S ) 2 index mul % i H' S V f P 6 1 roll % P i H' S V f dup 3 index mul neg 1.0 add % P i H' S V f ( 1.0 - (f*S)) 2 index mul % P i H' S V f Q 7 1 roll % Q P i H' S V f neg 1.0 add % Q P i H' S V (1.0 - f) 2 index mul neg 1.0 add % Q P i H' S V (1.0 - S * (1.0 - f)) 1 index mul % Q P i H' S V T 7 2 roll % V T Q P i H' S pop pop % V T Q P i %%% % end of BLOCK B. The rest is just stack manipulation dup 0.5 le % TEST II [ i == 0 ] { % BLOCK C [ take stack to V T P ] pop exch pop } { dup 1.5 le % TEST III [ i == 1 ] { % BLOCK D [ take stack to Q V P ] pop exch 4 1 roll exch pop } { dup 2.5 le % TEST IV [ i == 2 ] { % BLOCK E [ take stack to P V T ] pop 4 1 roll pop } { dup 3.5 le % TEST V [ i == 3 ] { % BLOCK F [ take stack to P Q V ] pop exch 4 2 roll pop } { dup 4.5 le % TEST VI [ i == 4 ] { % BLOCK G [ take stack to T P V ] pop exch pop 3 -1 roll } { % BLOCK H [ take stack to V P Q ] pop 3 1 roll exch pop } ifelse } ifelse % for V } ifelse % for IV } ifelse % for III } ifelse % for II \ifpgfshadingmodelcmyk \pgffuncshadingrgbtocmyk \fi \ifpgfshadingmodelgray \pgffuncshadingrgbtogray \fi }% \pgfdeclarefunctionalshading[black]{color wheel} {\pgfpoint{-50bp}{-50bp}} {\pgfpoint{50bp}{50bp}} {} { % x y 2 copy abs exch abs add 0.0001 ge {atan 360.0 div} % ... x y heading; heading being in %the interval [0, 1.0] { pop } % silently deal with error: return % arbitrary heading of zero for origin ifelse % because we will use it for 'Hue' 1.0 1.0 % ... H S V % C version to use as model: % H' = H * 6 % i = floor(H') % f = H' - i % P = V * (1.0 - S) % Q = V * (1.0 - (S*f)) % T = V * (1.0 - (S * (1.0 - f))) 3 2 roll 6.0 mul dup 4 1 roll % H' S V H' floor cvr % H' S V i dup 5 1 roll % i H' S V i 3 index sub neg % i H' S V f 1.0 3 index sub % i H' S V f (1.0 - S ) 2 index mul % i H' S V f P 6 1 roll % P i H' S V f dup 3 index mul neg 1.0 add % P i H' S V f ( 1.0 - (f*S)) 2 index mul % P i H' S V f Q 7 1 roll % Q P i H' S V f neg 1.0 add % Q P i H' S V (1.0 - f) 2 index mul neg 1.0 add % Q P i H' S V (1.0 - S * (1.0 - f)) 1 index mul % Q P i H' S V T 7 2 roll % V T Q P i H' S pop pop % V T Q P i %%% % end of BLOCK B. The rest is just stack manipulation dup 0.5 le % TEST II [ i == 0 ] { % BLOCK C [ take stack to V T P ] pop exch pop } { dup 1.5 le % TEST III [ i == 1 ] { % BLOCK D [ take stack to Q V P ] pop exch 4 1 roll exch pop } { dup 2.5 le % TEST IV [ i == 2 ] { % BLOCK E [ take stack to P V T ] pop 4 1 roll pop } { dup 3.5 le % TEST V [ i == 3 ] { % BLOCK F [ take stack to P Q V ] pop exch 4 2 roll pop } { dup 4.5 le % TEST VI [ i == 4 ] { % BLOCK G [ take stack to T P V ] pop exch pop 3 -1 roll } { % BLOCK H [ take stack to V P Q ] pop 3 1 roll exch pop } ifelse } ifelse % for V } ifelse % for IV } ifelse % for III } ifelse % for II \ifpgfshadingmodelcmyk \pgffuncshadingrgbtocmyk \fi \ifpgfshadingmodelgray \pgffuncshadingrgbtogray \fi }% % % A bilinear interpolation. % \colorlet{lower left}{white}% \colorlet{lower right}{white}% \colorlet{upper left}{white}% \colorlet{upper right}{white}% \pgfdeclarefunctionalshading[lower left,lower right,upper left,upper right]{bilinear interpolation} {\pgfpointorigin} {\pgfpoint{100bp}{100bp}} { \pgfshadecolortorgb{lower left}{\pgf@lib@shadings@ll}\pgfshadecolortorgb{lower right}{\pgf@lib@shadings@lr} \pgfshadecolortorgb{upper right}{\pgf@lib@shadings@ur}\pgfshadecolortorgb{upper left}{\pgf@lib@shadings@ul} }{ 25 sub 50 div exch 25 sub 50 div 2 copy % Calculate y/100 x/100. % 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. \pgf@lib@shadings@llred mul exch \pgf@lib@shadings@lrred mul add mul % Process red component. 4 1 roll \pgf@lib@shadings@urred mul exch \pgf@lib@shadings@ulred mul add mul add 13 1 roll \pgf@lib@shadings@llgreen mul exch \pgf@lib@shadings@lrgreen mul add mul % Process green component. 4 1 roll \pgf@lib@shadings@urgreen mul exch \pgf@lib@shadings@ulgreen mul add mul add 7 1 roll \pgf@lib@shadings@llblue mul exch \pgf@lib@shadings@lrblue mul add mul % Process blue component. 4 1 roll \pgf@lib@shadings@urblue mul exch \pgf@lib@shadings@ulblue mul add mul add \ifpgfshadingmodelcmyk \pgffuncshadingrgbtocmyk \fi \ifpgfshadingmodelgray \pgffuncshadingrgbtogray \fi }% % % A Mandelbrot set shading. Just for fun... % \pgfdeclarefunctionalshading[black]{Mandelbrot set} {\pgfpoint{-50bp}{-50bp}} {\pgfpoint{50bp}{50bp}}{} { 12.5 div exch 12.5 div exch 1 index 1 index % Stack: c_r c_i z_r z_i % Formula: z' = z^2 + c = (z_r + i z_i)^2 + c_r + i c_i % = (z_r^2 - z_i^2 + c_r) + i (2 z_r z_i + c_i) % % First iteration % 1. Compute z_r^2 -z_i^2 + c_r 1 index dup mul % z_r^2 1 index dup mul % z_i^2 sub % z_r^2 - z_i^2 4 index add % z_r^2 -z_i^2 + c_r % 2. Compute 2 z_r z_i + c_i 3 1 roll mul 2 mul % 2 z_r z_i 2 index add % 2 z_r z_i + c_i % Second iteration % 1. Compute z_r^2 -z_i^2 + c_r 1 index dup mul % z_r^2 1 index dup mul % z_i^2 sub % z_r^2 - z_i^2 4 index add % z_r^2 -z_i^2 + c_r % 2. Compute 2 z_r z_i + c_i 3 1 roll mul 2 mul % 2 z_r z_i 2 index add % 2 z_r z_i + c_i % Third iteration % 1. Compute z_r^2 -z_i^2 + c_r 1 index dup mul % z_r^2 1 index dup mul % z_i^2 sub % z_r^2 - z_i^2 4 index add % z_r^2 -z_i^2 + c_r % 2. Compute 2 z_r z_i + c_i 3 1 roll mul 2 mul % 2 z_r z_i 2 index add % 2 z_r z_i + c_i % Fourth iteration % 1. Compute z_r^2 -z_i^2 + c_r 1 index dup mul % z_r^2 1 index dup mul % z_i^2 sub % z_r^2 - z_i^2 4 index add % z_r^2 -z_i^2 + c_r % 2. Compute 2 z_r z_i + c_i 3 1 roll mul 2 mul % 2 z_r z_i 2 index add % 2 z_r z_i + c_i % Check for break (to avoid too large numbers) 1 index dup mul 1 index dup mul add 4 lt { % Fifth iteration % 1. Compute z_r^2 -z_i^2 + c_r 1 index dup mul % z_r^2 1 index dup mul % z_i^2 sub % z_r^2 - z_i^2 4 index add % z_r^2 -z_i^2 + c_r % 2. Compute 2 z_r z_i + c_i 3 1 roll mul 2 mul % 2 z_r z_i 2 index add % 2 z_r z_i + c_i % Sixth iteration % 1. Compute z_r^2 -z_i^2 + c_r 1 index dup mul % z_r^2 1 index dup mul % z_i^2 sub % z_r^2 - z_i^2 4 index add % z_r^2 -z_i^2 + c_r % 2. Compute 2 z_r z_i + c_i 3 1 roll mul 2 mul % 2 z_r z_i 2 index add % 2 z_r z_i + c_i % Seventh iteration % 1. Compute z_r^2 -z_i^2 + c_r 1 index dup mul % z_r^2 1 index dup mul % z_i^2 sub % z_r^2 - z_i^2 4 index add % z_r^2 -z_i^2 + c_r % 2. Compute 2 z_r z_i + c_i 3 1 roll mul 2 mul % 2 z_r z_i 2 index add % 2 z_r z_i + c_i % Check for break (to avoid too large numbers) 1 index dup mul 1 index dup mul add 4 lt { % Eighth iteration % 1. Compute z_r^2 -z_i^2 + c_r 1 index dup mul % z_r^2 1 index dup mul % z_i^2 sub % z_r^2 - z_i^2 4 index add % z_r^2 -z_i^2 + c_r % 2. Compute 2 z_r z_i + c_i 3 1 roll mul 2 mul % 2 z_r z_i 2 index add % 2 z_r z_i + c_i % Ninth iteration % 1. Compute z_r^2 -z_i^2 + c_r 1 index dup mul % z_r^2 1 index dup mul % z_i^2 sub % z_r^2 - z_i^2 4 index add % z_r^2 -z_i^2 + c_r % 2. Compute 2 z_r z_i + c_i 3 1 roll mul 2 mul % 2 z_r z_i 2 index add % 2 z_r z_i + c_i % Tenth iteration % 1. Compute z_r^2 -z_i^2 + c_r 1 index dup mul % z_r^2 1 index dup mul % z_i^2 sub % z_r^2 - z_i^2 4 index add % z_r^2 -z_i^2 + c_r % 2. Compute 2 z_r z_i + c_i 3 1 roll mul 2 mul % 2 z_r z_i 2 index add % 2 z_r z_i + c_i } { pop pop 1000.0 1000.0 } ifelse } { pop pop 1000.0 1000.0 } ifelse % Compute distance dup mul exch dup mul add sqrt dup 4 1 roll 2 gt { pop pop 2.0 exch div 1.0 exch sub dup dup} {pop pop pop 0.0 0.0 0.0} ifelse \ifpgfshadingmodelcmyk \pgffuncshadingrgbtocmyk \fi \ifpgfshadingmodelgray \pgffuncshadingrgbtogray \fi }%