math-rad.mkvi / last modification: 2020-01-30 14:16
%D \module
%D   [       file=math-rad,
%D        version=2013.07.13,
%D          title=\CONTEXT\ Math Macros,
%D       subtitle=Radicals,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

\writestatus{loading}{ConTeXt Math Macros / Radicals}

\unprotect

%D \starttyping
%D $\sqrt[3]{10}$
%D \stoptyping
%D
%D This root command will be overloaded later:

%D Old stuff:

% \def\rootradical{\Uroot    \defaultmathfamily "221A } % can be done in char-def
% \def\surdradical{\Uradical \defaultmathfamily "221A } % can be done in char-def

\def\root#1\of{\rootradical{#1}} % #2

\unexpanded\def\sqrt{\doifelsenextoptionalcs\rootwithdegree\rootwithoutdegree}

\unexpanded\def\styledrootradical#1#2% so that \text works ok ... \rootradical behaves somewhat weird
  {\normalexpanded{\rootradical{\normalunexpanded{#1}}{\noexpand\triggermathstyle{\normalmathstyle}\normalunexpanded{#2}}}}

\unexpanded\def\rootwithdegree[#1]{\rootradical{#1}}
\unexpanded\def\rootwithoutdegree {\rootradical  {}}

%D Even older stuff:

% % is now a ordinary character
%
% \let\normalsurd\surd % \Uradical "0 "221A
% \unexpanded\def\surd{\normalsurd{}}


%D The real thing:

\installcorenamespace{mathradical}
\installcorenamespace{mathradicalalternative}

\installcommandhandler \??mathradical {mathradical} \??mathradical

\setupmathradical
  [\c!alternative=\v!normal,
   \c!mpoffset=.25\exheight]

\appendtoks
    \setuevalue{\currentmathradical}{\math_radical_handle{\currentmathradical}}
\to \everydefinemathradical

\unexpanded\def\math_radical_handle#tag%
  {\begingroup
   \edef\currentmathradical{#tag}%
   \doifelsenextoptionalcs\math_radical_degree_yes\math_radical_degree_nop}

\def\math_radical_alternative{\csname\??mathradicalalternative\mathradicalparameter\c!alternative\endcsname}

\def\m_math_no_degree{{}}

\def\math_radical_degree_yes[#degree]{\edef\currentmathradicaldegree{#degree}\math_radical_indeed}
\def\math_radical_degree_nop         {\let\currentmathradicaldegree\m_math_no_degree\math_radical_indeed}

\def\math_radical_indeed#body%
  {\math_radical_alternative{#body}\endgroup}

\setvalue{\??mathradicalalternative\v!default}%  #body%
  {\rootradical{\currentmathradicaldegree}}   % {#body}}

\setvalue{\??mathradicalalternative\v!normal}#body%
  {\edef\p_color{\mathradicalparameter\c!color}%
   \ifx\p_color\empty
     \styledrootradical{\currentmathradicaldegree}{#body}% {} really needed as \rootradical expands first
   \else\ifx\currentmathradicaldegree\empty
     \pushcolor[\p_color]%
     \styledrootradical{\currentmathradicaldegree}%
     {\popcolor#body}%
   \else
     \pushcolor[\p_color]%
     \styledrootradical{\popcolor\currentmathradicaldegree\pushcolor[\p_color]}%
     {\popcolor#body}%
   \fi\fi}

% As I had a long standing whish to see a proper final root element I decided
% to make one my own.
%
% \startMPcode
%   path p ; p := unitsquare xysized(4cm,1cm) ;
%
%   path q ; q := boundingbox p enlarged (bbheight(p)/10) ;
%   numeric h ; h := bbheight(q) ;
%
%   draw p ;
%   draw
%       llcorner q shifted (-h/2,h/2) --
%       llcorner q shifted (-h/4,0) --
%       ulcorner q --
%       urcorner q --
%       urcorner q shifted (0,-h/10) ;
% \stopMPcode
%
% \startMPextensions
%     vardef math_root(expr w,h,d,o) =
%         path q ; q := boundingbox unitsquare xysized(w,h) enlarged (o);
%         llcorner q shifted (-h/2,h/2) --
%         llcorner q shifted (-h/4,-d) --
%         ulcorner q --
%         urcorner q --
%         urcorner q shifted (0,-h/10)
%     enddef ;
% \stopMPextensions
%
% \startuniqueMPgraphic{root}{width,height,depth,offset,linewidth}
%     pickup pencircle scaled \MPvar{linewidth} ;
%     draw math_root(\MPvar{width},\MPvar{height},\MPvar{depth},\MPvar{offset}) ;
% \stopuniqueMPgraphic
%
% \unexpanded\def\sqrt#1%
%   {\begingroup
%    \setbox\scratchbox\mathstylehbox{#1}%
%    \scratchoffset\MPrawvar{root}{offset}%.25\exheight
%    \scratchwidth \wd\scratchbox
%    \scratchheight\ht\scratchbox
%    \scratchdepth \dp\scratchbox
%    \setbox2=\hbox\bgroup % todo: tag this box as sqrt
%      \uniqueMPgraphic
%        {root}%
%        {width=\the\scratchwidth,%
%         depth=\the\scratchdepth,%
%         height=\the\scratchheight,%
%         offset=\the\scratchoffset,
%         linewidth=\the\linewidth}%
%    \egroup
%    \scratchdimen\wd2
%    \lower\dimexpr\scratchoffset+\scratchdepth\relax\box2
%    \hskip-\scratchdimen
%    \hbox to \scratchdimen{\hss\box\scratchbox\hskip\scratchoffset}%
%    \endgroup}

\startMPextensions
    vardef math_radical_simple(expr w,h,d,o) =
        (-h/2-o,h/2-o) --
        (-h/4-o,-d-o)  --
        (-o,h+o)       --
        (w+o,h+o)      --
        (w+o,h-h/10+o)
    enddef ;
\stopMPextensions

\startuniqueMPgraphic{math:radical:default}%{...}
    draw
        math_radical_simple(OverlayWidth,OverlayHeight,OverlayDepth,OverlayOffset)
        withpen pencircle xscaled (2OverlayLineWidth) yscaled (3OverlayLineWidth/4) rotated 30
      % dashed evenly
        withcolor OverlayLineColor ;
\stopuniqueMPgraphic

% todo: spacing .. this is just an experiment (article driven)

\setvalue{\??mathradicalalternative\v!mp}#body% we could use dowithnextbox
  {\begingroup
   \scratchoffset\mathradicalparameter\c!mpoffset
   \setbox\nextbox\mathstylehbox{#body}%
   % we use the \overlay variables as these are passes anyway and
   % it's more efficient than using parameters
   \d_overlay_width    \wd\nextbox
   \d_overlay_height   \ht\nextbox
   \d_overlay_depth    \dp\nextbox
   \d_overlay_offset   \scratchoffset
   \d_overlay_linewidth\linewidth
   \edef\overlaylinecolor{\mathradicalparameter\c!color}%
   %
   \edef\p_mp{\mathradicalparameter\c!mp}%
   %
   \setbox\scratchbox\hpack\bgroup % todo: tag this box as sqrt
     \uniqueMPgraphic
       {\p_mp}%
      %{...}%
   \egroup
   \scratchdimen       \wd\scratchbox
   \scratchtopoffset   \dimexpr\scratchoffset+\dp\nextbox\relax
   \scratchbottomoffset\dimexpr\scratchoffset+\ht\nextbox/2\relax
   \hpack to \scratchdimen{\hss\box\nextbox\hskip\scratchoffset}%
   \hskip-\scratchdimen
   \lower\dimexpr\scratchtopoffset\box\scratchbox%
   \ifx\currentmathradicaldegree\empty \else
     \setbox\scratchbox\mathstylehbox{\scriptscriptstyle\currentmathradicaldegree\hss}%
     \wd\scratchbox\scratchdimen
     \hskip-\scratchdimen
     \raise\dimexpr\scratchbottomoffset\box\scratchbox
   \fi
   \endgroup}

\definemathradical[sqrt][mp=math:radical:default]

% \setupmathradical[sqrt][alternative=normal,color=darkblue]
% \setupmathradical[sqrt][alternative=mp,color=darkgreen]

%D Because I wanted to illustrate some more fun stuff another mechanism
%D is provided as well ... let's put some dangerous tools in the hand of
%D math jugglers like Aditya.

\installcorenamespace{mathornament}
\installcorenamespace{mathornamentalternative}

\installcommandhandler \??mathornament {mathornament} \??mathornament

\setupmathornament
  [\c!alternative=\v!mp, % currently mp only .. maybe some day layer too
   \c!mpoffset=.25\exheight]

\appendtoks
    \setuevalue{\currentmathornament}{\math_ornament_handle{\currentmathornament}}
\to \everydefinemathornament

\unexpanded\def\math_ornament_handle#tag#body%
  {\begingroup
   \edef\currentmathornament{#tag}%
   \csname\??mathornamentalternative\mathornamentparameter\c!alternative\endcsname{#body}%
   \endgroup}

\setvalue{\??mathornamentalternative\v!mp}#body% we could use dowithnextbox
  {\begingroup
   \scratchoffset\mathornamentparameter\c!mpoffset
   \setbox\nextbox\mathstylehbox{#body}%
   \d_overlay_width    \wd\nextbox
   \d_overlay_height   \ht\nextbox
   \d_overlay_depth    \dp\nextbox
   \d_overlay_offset   \scratchoffset
   \d_overlay_linewidth\linewidth
   \edef\overlaylinecolor{\mathornamentparameter\c!color}%
   \edef\p_mp{\mathornamentparameter\c!mp}%
   % the width of the graphic determines the width of the final result
   \setbox\scratchbox\hpack{\uniqueMPgraphic{\p_mp}}% todo: add code key + tag
   \hpack to \wd\scratchbox{\hss\box\nextbox\hss}%
   \hskip-\wd\scratchbox
   \box\scratchbox
   \endgroup}

% \startMPextensions
%     vardef math_ornament_hat(expr w,h,d,o,l) =
%         image ( path p ; p :=
%             (w/2,h + 10l) --
%             (o + w,h + o) --
%             (w/2,h + 7l) --
%             (-o,h + o) --
%             cycle ;
%             fill p ;
%             setbounds currentpicture to (-o,0) -- (w+o,0) -- (w+o,h+2o) -- (-o,h+2o) -- cycle ;
%         )
%     enddef ;
% \stopMPextensions
%
% \startuniqueMPgraphic{math:ornament:hat}
%     draw
%         math_ornament_hat(
%             OverlayWidth,
%             OverlayHeight,
%             OverlayDepth,
%             OverlayOffset,
%             OverlayLineWidth
%         )
%     withpen
%         pencircle
%             xscaled (2OverlayLineWidth)
%             yscaled (3OverlayLineWidth/4)
%             rotated 30
%     withcolor
%         OverlayLineColor ;
%         draw boundingbox currentpicture;
% \stopuniqueMPgraphic
%
% \definemathornament [mathhat] [mp=math:ornament:hat]
%
% \dorecurse{8}{$\mathhat{\blackrule[width=#1ex,color=gray]}$ }

\protect \endinput