%%
%% This is file `pst-spectrum.tex',
%%
%% IMPORTANT NOTICE:
%%
%% Package `pst-spectrum.tex'
%%
%% Manuel Luque <Manuel.Luque27 _at_ gmail.com>
%% Herbert Voß <hvoss@tug.org>
%%
%% This program can be redistributed and/or modified under the terms
%% of the LaTeX Project Public License Distributed from CTAN archives
%% in directory macros/latex/base/lppl.txt.
%%
%% DESCRIPTION:
%%   `pst-spectrum is a PSTricks package to draw sspectrum of light
%%
\csname PSTspectrumLoaded\endcsname
\let\PSTspectrumLoaded\endinput
\ifx\PSTricksLoaded\endinput\else \input pstricks.tex\fi
%\ifx\PSTplotLoaded \endinput\else \input pst-plot.tex\fi
%\ifx\PSTnodesLoaded\endinput\else \input pst-node.tex \fi
%\ifx\PSTnodesLoaded\endinput\else \input pst-cie.tex \fi
%
\def\fileversion{1.01}
\def\filedate{2026/04/23}
\message{`PST-spectrum' v\fileversion, \filedate\space (ml,hv)}
%
\RequirePackage{multido,expl3}
\ExplSyntaxOn
  \cs_new_eq:NN \ps@Calc \fp_eval:n
\ExplSyntaxOff

\edef\PstAtCode{\the\catcode`\@} \catcode`\@=11\relax
\pst@addfams{pst-spectrum}
\pstheader{pst-spectrum.pro}

\define@key[psset]{pst-spectrum}{gamma}[2.2]{\def\psk@psspectrum@GAM{#1 }}
\define@key[psset]{pst-spectrum}{begin}[360]{\def\psk@psspectrum@begin{#1 }}
\define@key[psset]{pst-spectrum}{end}[830]{\def\psk@psspectrum@end{#1 }}
\define@boolkey[psset]{pst-spectrum}[Pst@]{axe}[true]{}
\define@boolkey[psset]{pst-spectrum}[Pst@]{invers}[true]{}
\define@boolkey[psset]{pst-spectrum}[Pst@]{values}[true]{}
\define@boolkey[psset]{pst-spectrum}[Pst@]{noBox}[true]{}
\psset[pst-spectrum]{gamma=2.2,begin=360,end=830,axe=true,invers,values,noBox=false}

% primary illuminants
\define@choicekey*+[psset]{pst-spectrum}{ColorSpace}{%
  Adobe,CIE,ColorMatch,NTSC,Pal-Secam,ProPhoto,SMPTE,sRGB}[sRGB]{% 
  \def\pst@spectrum@ColorSpace{#1}%
}{\PackageWarning{pst-spectrum}{erroneous input (#1) for ColorSpace ignored. 
  Using sRGB.}%
  \def\pst@spectrum@ColorSpace{#1}%
}
\psset[pst-spectrum]{ColorSpace=sRGB}
%
% datas
\define@choicekey*+[psset]{pst-spectrum}{datas}{CIE1964,CIE1931}[CIE1931]{% 
  \def\pst@spectrum@datas{#1}%
}{\PackageWarning{pst-spectrum}{erroneous input (#1) for datas ignored. Using CIE1931.}%
  \def\pst@spectrum@datas{#1}%
}
\psset[pst-spectrum]{datas=CIE1931}
%
\def\psDeltaX{1}
\def\psDeltaY{0.7}
%
\def\psCIEspectrum{\def\pst@par{}\pst@object{psCIEspectrum}}
\def\psCIEspectrum@i{%
  \@ifnextchar({\psCIEspectrum@ii}{\psCIEspectrum@iii(-6,-1)(6,1)}}
\def\psCIEspectrum@ii(#1){%
  \@ifnextchar({\psCIEspectrum@iii(#1)}{\psCIEspectrum@iii(-6,-1)(#1)}}
\def\psCIEspectrum@iii(#1,#2)(#3,#4){%
  \begingroup
  \use@par
  \ifPst@noBox\else
  \pspicture(\ps@Calc{#1-\psDeltaX},\ps@Calc{#2-\psDeltaY})%
            (\ps@Calc{#3+\psDeltaX},\ps@Calc{#4+0.5*\psDeltaY})
  \fi
  \ifPst@invers
    \psframe*(\ps@Calc{#1-\psDeltaX},\ps@Calc{#2-\psDeltaY})%
            (\ps@Calc{#3+\psDeltaX},\ps@Calc{#4+0.5*\psDeltaY})
    \ifPst@values
      \multido{\i=-6+2,\iL=400+50}{7}{%
        \psline[linecolor=white](\i,-1)(\i,-1.2)
        \uput[d](\i,-1.2){\textcolor{white}{\iL}}}%
    \fi
  \else%  white background and noframe
%    \psframe(\ps@Calc{#1-\psDeltaX},\ps@Calc{#2-\psDeltaY})%
%            (\ps@Calc{#3+\psDeltaX},\ps@Calc{#4+0.5*\psDeltaY})
    \ifPst@values
      \multido{\i=-6+2,\iL=400+50}{7}{%
        \psline(\i,-1)(\i,-1.2)
        \uput[d](\i,-1.2){\iL}}%
    \fi
  \fi
  \addto@pscode{
	/WLbegin \psk@psspectrum@begin def
	/WLend \psk@psspectrum@end def
 	WLbegin 360 lt {/WLbegin 360 def} if
 	WLend 830 gt {/WLend 830 def} if
	/L1 WLbegin 360 sub def
	/L2 WLend 360 sub def
	/GAM {1 \psk@psspectrum@GAM div} def
	/ColorSpace (\pst@spectrum@ColorSpace) def
	/datas (\pst@spectrum@datas) def
	/DW L2 L1 sub def
	/X1 #1 \pst@number\psxunit mul def 
	/X2 #3 \pst@number\psxunit mul def
	/Y1 #2 \pst@number\psyunit mul def 
	/Y2 #4 \pst@number\psyunit mul def
	/DX X2 X1 sub def
	/Coeff DX DW div def
	/Times-Roman findfont 7 scalefont setfont
 	/chaine 15 string def
 	/imprime {chaine cvs show } def
 	/SYTEM {ColorSpace cvx exec} def
 	/TAB {datas cvx exec} def
 	spectrumdict begin TAB spectre end
  }%
  \use@pscode
  \ifPst@noBox\else\endpspicture\fi
  \endgroup
}%

\def\psxspectrum{\def\pst@par{}\pst@object{psxspectrum}}
\def\psxspectrum@i{%
  \@ifnextchar({\psxspectrum@ii}{\psxspectrum@iii(-5,0)(5,1)}}
\def\psxspectrum@ii(#1){%
  \@ifnextchar({\psxspectrum@iii(#1)}{\psxspectrum@iii(-5,0)(#1)}}
\def\psxspectrum@iii(#1,#2)(#3,#4){%
  \begin@SpecialObj
    \use@par
%  \begingroup
%  \pst@killglue
%  \use@par
  \pstVerb{
	/L1 \psk@psspectrum@begin def
	/L2 \psk@psspectrum@end def
	/gamma \psk@psspectrum@GAM def
	/DW L2 L1 sub def
	/X1 #1 \pst@number\psxunit mul def /X2 #3 \pst@number\psxunit mul def
	/Y1 #2 \pst@number\psyunit mul def /Y2 #4 \pst@number\psyunit mul def
	/DX X2 X1 sub def
	/Coeff DX DW div def
	/Times-Roman findfont 7 scalefont setfont
 	/chaine 15 string def
 	/imprime { chaine cvs show } def
  }%
  \addto@pscode{
	/max { 2 copy lt {exch} if pop } def
	/min { 2 copy gt {exch} if pop } def
	/rho {
	  1 dict begin
	  /x exch def
	  0 x max 1 min gamma exp
	  end
	} def
	/hue {
	  L 440 lt { 4 L 440 sub 380 440 sub div rho add 6 div } if
	  L 440 ge L 490 lt and { 4 L 440 sub 490 440 sub div rho sub 6 div	} if
	  L 490 ge L 510 lt and { 2 L 510 sub 490 510 sub div rho add 6 div  } if
	  L 510 ge L 580 lt and { 2 L 510 sub 580 510 sub div rho sub 6 div } if
	  L 580 ge L 645 lt and { 0 L 645 sub 580 645 sub div rho add 6 div } if
	  L 645 ge {0} if
 	} def
	/saturation 1 def
	/brightness {
	  L 420 lt {0.3 0.7 L 380 sub 420 380 sub div mul add rho} if
	  L 420 ge L 700 le and {1} if
	  L 700 gt {0.3 0.7 L 780 sub 700 780 sub div mul add rho} if
	} def
	/HSB {
	  1 dict begin
	  /L exch def % lambda en nm
 	  hue saturation brightness
	  end
	} def
	gsave
	L1 1 L2 {
	  /Li exch def
	  X1 Li L1 sub Coeff mul add Y1 moveto
	  X1 Li L1 sub Coeff mul add Y2 lineto
	  Li HSB sethsbcolor
	  1.5 setlinewidth
	  stroke
	} for
	% pstack
	\ifPst@values
	newpath
	X1 Y1 moveto X2 Y1 lineto 1 setlinewidth 0 setgray stroke
	% 10 divisions
	X1 X2 X1 sub 10 div X2 {
	  /Xi exch def
	  Xi Y1 moveto Xi Y1 4 sub 
	  lineto stroke
	} for
	grestore
	X1 X2 X1 sub 10 div X2 {
	  /Xi exch def
	  /Li L2 L1 sub X2 X1 sub div Xi X1 sub mul L1 add round cvi def
	  Xi Y1 5 sub moveto
	  gsave
	  0 setgray
	  -90 rotate Li imprime
	  grestore
	} for
	\fi
  }%
  \end@SpecialObj
%  \use@pscode
%  \endgroup
}%



% spectre d'aprés Dan Bruton
\def\psCIEspectrumDB{\def\pst@par{}\pst@object{psCIEspectrumDB}}
\def\psCIEspectrumDB@i{%
  \@ifnextchar({\psCIEspectrumDB@ii}{\psCIEspectrumDB@iii(-6,-1)(6,1)}}
\def\psCIEspectrumDB@ii(#1){%
  \@ifnextchar({\psCIEspectrumDB@iii(#1)}{\psCIEspectrumDB@iii(-6,-1)(#1)}}
\def\psCIEspectrumDB@iii(#1,#2)(#3,#4){%
  \begingroup
  \use@par
  \pspicture(\ps@Calc{#1-\psDeltaX},\ps@Calc{#2-\psDeltaY})%
            (\ps@Calc{#3+\psDeltaX},\ps@Calc{#4+0.5*\psDeltaY})
  \ifPst@invers
    \psframe*(\ps@Calc{#1-\psDeltaX},\ps@Calc{#2-\psDeltaY})%
            (\ps@Calc{#3+\psDeltaX},\ps@Calc{#4+0.5*\psDeltaY})
    \ifPst@values
      \multido{\i=-6+2,\iL=400+50}{7}{%
        \psline[linecolor=white](\i,-1)(\i,-1.2)
        \uput[d](\i,-1.2){\textcolor{white}{\iL}}}%
    \fi
  \else%  white background and noframe
%    \psframe(\ps@Calc{#1-\psDeltaX},\ps@Calc{#2-\psDeltaY})%
%            (\ps@Calc{#3+\psDeltaX},\ps@Calc{#4+0.5*\psDeltaY})
    \ifPst@values
      \multido{\i=-6+2,\iL=400+50}{7}{%
        \psline(\i,-1)(\i,-1.2)
        \uput[d](\i,-1.2){\iL}}%
    \fi
  \fi
  \addto@pscode{
	/WLbegin \psk@psspectrum@begin def
	/WLend \psk@psspectrum@end def
	/L1 WLbegin def
	/L2 WLend  def
	/GAM \psk@psspectrum@GAM def
	/DW L2 L1 sub def
	/X1 #1 \pst@number\psxunit mul def /X2 #3 \pst@number\psxunit mul def
	/Y1 #2 \pst@number\psyunit mul def /Y2 #4 \pst@number\psyunit mul def
	/DX X2 X1 sub def
	/Coeff DX DW div def
	/Times-Roman findfont 7 scalefont setfont
	/chaine 15 string def
	/imprime { chaine cvs show } def
  	spectrumdict begin spectreDB end
  }%
  \use@pscode
  \endpspicture
  \endgroup
}
\catcode`\@=\PstAtCode\relax
\endinput
