%D \module
%D   [       file=meta-pdf,
%D        version=2006.06.07,
%D          title=\METAPOST\ Graphics,
%D       subtitle=Conversion to \PDF,
%D         author=Hans Hagen \& others (see text),
%D           date=\currentdate,
%D      copyright=\PRAGMA]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

\registerctxluafile{meta-pdf}{1.003}

%D We will clean up the color mess later.

\writestatus{loading}{MetaPost Graphics / MPS to PDF}

\unprotect

%D \macros
%D   {convertMPtoPDF}
%D
%D The next set of macros implements \METAPOST\ to \PDF\
%D conversion. The traditional method is in the MkII file.
%D
%D The main conversion command is:
%D
%D \starttyping
%D \convertMPtoPDF {filename} {x scale} {y scale}
%D \stoptyping
%D
%D The dimensions are derived from the bounding box. So we
%D only have to say:
%D
%D \starttyping
%D \convertMPtoPDF{mp-pra-1.eps}{1}{1}
%D \convertMPtoPDF{mp-pra-1.eps}{.5}{.5}
%D \stoptyping

\def\PDFMPformoffset
  {\ifdefined\objectoffset\objectoffset\else\zeropoint\fi}

%D The main macro:

\def\convertMPtoPDF#1#2#3% scaling no longer supported at this level (so #2 & #3 ignored)
  {\vbox\bgroup
     \message{[MP to PDF]}%
     \xdef\MPfilename{#1}%
     \glet\MPwidth \!!zeropoint
     \glet\MPheight\!!zeropoint
     \glet\MPllx   \!!zerocount
     \glet\MPlly   \!!zerocount
     \glet\MPurx   \!!zerocount
     \glet\MPury   \!!zerocount
     \forgetall
     \offinterlineskip
     \setbox\scratchbox\vbox\bgroup
       \ctxlua{mptopdf.convertmpstopdf("\MPfilename")}\removeunwantedspaces
     \egroup
     \setbox\scratchbox\hbox\bgroup
        \hskip-\MPllx\onebasepoint
        \raise-\MPlly\onebasepoint
        \box\scratchbox
     \egroup
     \setbox\scratchbox\vbox to \MPheight\bgroup
       \vfill
       \hsize\MPwidth
       \smashbox\scratchbox
       \box\scratchbox
     \egroup
     \wd\scratchbox\MPwidth
     \ht\scratchbox\MPheight
     \dopackageMPgraphic\scratchbox
   \egroup}

%D Objects (move all to backend)

% \def\dopackageMPgraphic#1% #1 = boxregister
%   {\scratchdimen\PDFMPformoffset\relax
%    \ifdim\scratchdimen>\zeropoint % compensate for error
%      \setbox#1\vbox spread 2\scratchdimen
%        {\forgetall\vss\hbox spread 2\scratchdimen{\hss\box#1\hss}\vss}%
%    \fi
%    \setMPPDFobject{#1}%
%    \ifdim\scratchdimen>\zeropoint % compensate for error
%      \vbox to \MPheight
%        {\forgetall\vss\hbox to \MPwidth{\hss\getMPPDFobject\hss}\vss}%
%    \else
%      \getMPPDFobject
%    \fi}
%
% \def\setMPPDFobject#1% boxnumber
%   {\the\pdfbackendeveryxform
%    \finalizeobjectbox{#1}%
%    \immediate\pdfxform resources{\pdfcurrentresources}#1%
%    \edef\getMPPDFobject{\noexpand\pdfrefxform\the\pdflastxform}}
%
% \let\getMPPDFobject\relax

% we don't need to package as each page has all resources anyway

\let\dopackageMPgraphic\box

%D \macros
%D   {deleteMPgraphic,
%D    startMPresources,
%D    stopMPresources}

\ifx\deleteMPgraphic\undefined
  \def\deleteMPgraphic#1{}
\fi

\ifx\startMPresources\undefined
  \let\startMPresources\relax
  \let\stopMPresources\relax
\fi

%D We implement extensions by using the \METAPOST\ special
%D mechanism. Opposite to \TEX's specials, the \METAPOST\ ones
%D are flushed before or after the graphic data, but thereby
%D are no longer connected to a position.
%D
%D We implement specials by overloading the \type {fill}
%D operator. By counting the fills, we can let the converter
%D treat the appropriate fill in a special way. The
%D specification of the speciality can have two forms,
%D determined by the setting of a boolean variable:
%D
%D \starttyping
%D _inline_specials_ := false ; % comment like code (default)
%D _inline_specials_ := true  ; % command like code
%D \stoptyping
%D
%D When the specification is embedded as comment, it looks
%D like:
%D
%D \starttyping
%D %%MetaPostSpecial <size> <data> <number> <identifier>
%D \stoptyping
%D
%D The in||line alternative is more tuned for \POSTSCRIPT,
%D since it permits us to define a macro \type {special}.
%D
%D \starttyping
%D inline  : <data> <number> <identifier> <size> special
%D \stoptyping
%D
%D The \type {identifier} determines what to do, and the data
%D can be used to accomplish this. A type~2 shading function
%D has identifier~2. Alltogether, the number of parameters is
%D specified in \type {size}. The \type {number} is the number
%D of the fill that needs the special treatment. For a type~2
%D and~3 shaded fill, the datablock contains the following

%D data:
%D
%D \starttyping
%D from to n inner_r g b x y        outer_r g b x y
%D from to n inner_r g b x y radius outer_r g b x y radius
%D \stoptyping

\newconditional\manyMPspecials \settrue\manyMPspecials

%D Since colors are not subjected to transformations, we can
%D only use colors as signal. In our case, we use a dummy colored
%D path with a red color component of \type {0.n}, so \type
%D {0.001} is the first path and \type {0.010} the tenth. Since
%D \METAPOST strips trailing zeros, we have to padd the string.

\newif\ifMPcmykcolors
\newif\ifMPspotcolors

%D We support specials but assume that the files are somewhat simple
%D ones wo we have dropped a few. The reason is that runtime \METAPOST\
%D processing now uses \MPLIB\ so we only need to deal with the
%D conversion here. See meta-pdh.mkiv (and older files) for more
%D details. Here we just give a few examples.
%D
%D \startbuffer[mp]
%D   fill fullcircle xyscaled (3cm,1cm) withcolor \MPcolor{test} ;
%D \stopbuffer
%D
%D \startbuffer[cmyk]
%D \startcombination[4*1]
%D   {\definecolor[test][c=1,y=.3,k=.3] \processMPbuffer[mp]} {c=1 y=.3 k=.3}
%D   {\definecolor[test][c=.9,y=.15]    \processMPbuffer[mp]} {c=.9 y=.15}
%D   {\definecolor[test][c=.25,y=.8]    \processMPbuffer[mp]} {c=.25 y=.8}
%D   {\definecolor[test][c=.45,y=.1]    \processMPbuffer[mp]} {c=.45 y=.1}
%D \stopcombination
%D \stopbuffer
%D
%D \placefigure
%D   {\CMYK\ support disabled,
%D    conversion to \RGB.}
%D   {\setupcolors[cmyk=nee,state=start]\getbuffer[cmyk]}
%D
%D \placefigure
%D   {\CMYK\ support enabled,
%D    no support in \METAPOST.}
%D   {\setupcolors[cmyk=ja,mpcmyk=nee,state=start]\getbuffer[cmyk]}
%D
%D \placefigure
%D   {\CMYK\ support enabled,
%D    no conversion to \RGB,
%D    support in \METAPOST}
%D   {\setupcolors[cmyk=ja,state=start]\getbuffer[cmyk]}
%D
%D Transparency support used specials 60 (rgb) and 61
%D (cmyk).
%D
%D \startbuffer
%D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0);
%D
%D fill p rotated  90 withcolor transparent(1,.5,yellow) ;
%D fill p rotated 210 withcolor transparent(1,.5,green) ;
%D fill p rotated 330 withcolor transparent(1,.5,blue) ;
%D \stopbuffer
%D
%D \typebuffer
%D
%D \startlinecorrection \processMPbuffer \stoplinecorrection
%D
%D One can also communicate colors between \CONTEXT\ and
%D \METAPOST:
%D
%D \startbuffer
%D \definecolor[tcyan]   [c=1,k=.2,t=.5]
%D \definecolor[tmagenta][m=1,k=.2,t=.5]
%D \definecolor[tyellow] [y=1,k=.2,t=.5]
%D \stopbuffer
%D
%D \typebuffer \getbuffer
%D
%D \startbuffer
%D u := 2cm ; path p ; p := fullcircle scaled u shifted (u/4,0);
%D
%D fill p rotated  90 withcolor \MPcolor{tcyan} ;
%D fill p rotated 210 withcolor \MPcolor{tmagenta} ;
%D fill p rotated 330 withcolor \MPcolor{tyellow} ;
%D \stopbuffer
%D
%D \startlinecorrection \processMPbuffer \stoplinecorrection
%D
%D Shading is an example of a more advanced graphic feature,
%D but users will seldom encounter those complications. Here
%D we only show a few simple examples, but many other
%D alternatives are possible by setting up the functions built
%D in \PDF\ in the appropriate way.
%D
%D Shading has to do with interpolation between two or more
%D points or user supplied ranges. In \PDF, the specifications
%D of a shade has to be encapsulated in objects and passed on
%D as resources. This is a \PDF\ level 1.3. feature. One can
%D simulate three dimensional shades as well and define simple
%D functions using a limited set of \POSTSCRIPT\ primitives.
%D Given the power of \METAPOST\ and these \PDF\ features, we
%D can achieve superb graphic effects.
%D
%D Since everything is hidden in \TEX\ and \METAPOST\ graphics,
%D we can stick to high level \CONTEXT\ command, as shown in
%D the following exmples.
%D
%D \startbuffer
%D \startuniqueMPgraphic{CircularShade}
%D   path  p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ;
%D   circular_shade(p,0,.2red,.9red) ;
%D \stopuniqueMPgraphic
%D
%D \startuniqueMPgraphic{LinearShade}
%D   path  p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ;
%D   linear_shade(p,0,.2blue,.9blue) ;
%D \stopuniqueMPgraphic
%D
%D \startuniqueMPgraphic{DuotoneShade}
%D   path  p ; p := unitsquare xscaled \overlaywidth yscaled \overlayheight ;
%D   linear_shade(p,2,.5green,.5red) ;
%D \stopuniqueMPgraphic
%D \stopbuffer
%D
%D \typebuffer \getbuffer
%D
%D These graphics can be hooked into the overlay mechanism,
%D which is available in many commands.
%D
%D \startbuffer
%D \defineoverlay[demo 1][\uniqueMPgraphic{CircularShade}]
%D \defineoverlay[demo 2][\uniqueMPgraphic  {LinearShade}]
%D \defineoverlay[demo 3][\uniqueMPgraphic {DuotoneShade}]
%D \stopbuffer
%D
%D \typebuffer \getbuffer
%D
%D These backgrounds can for instance be applied to \type
%D {\framed}:
%D
%D \startbuffer
%D \setupframed[width=3cm,height=2cm,frame=off]
%D \startcombination[3*1]
%D   {\framed[backgroundachtergrond=demo 1]{\bfd \white Demo 1}} {}
%D   {\framed[backgroundachtergrond=demo 2]{\bfd \white Demo 2}} {}
%D   {\framed[backgroundachtergrond=demo 3]{\bfd \white Demo 3}} {}
%D \stopcombination
%D \stopbuffer
%D
%D \typebuffer
%D
%D \startlinecorrection
%D \getbuffer
%D \stoplinecorrection
%D
%D There are a few more alternatives, determined by the second
%D parameter passed to \type {circular_shade} and alike.
%D
%D \def\SomeShade#1#2#3#4#5%
%D   {\startuniqueMPgraphic{Shade-#1}
%D      width := \overlaywidth ;
%D      height := \overlayheight ;
%D      path p ; p := unitsquare xscaled width yscaled height ;
%D      #2_shade(p,#3,#4,#5) ;
%D    \stopuniqueMPgraphic
%D    \defineoverlay[Shade-#1][\uniqueMPgraphic{Shade-#1}]%
%D    \framed[backgroundachtergrond=Shade-#1,width=2cm,height=2cm,frame=off]{}}
%D
%D \startlinecorrection
%D \startcombination[5*1]
%D   {\SomeShade{10}{circular}{0}{.3blue}{.9blue}} {circular 0}
%D   {\SomeShade{11}{circular}{1}{.3blue}{.9blue}} {circular 1}
%D   {\SomeShade{12}{circular}{2}{.3blue}{.9blue}} {circular 2}
%D   {\SomeShade{13}{circular}{3}{.3blue}{.9blue}} {circular 3}
%D   {\SomeShade{14}{circular}{4}{.3blue}{.9blue}} {circular 4}
%D \stopcombination
%D \stoplinecorrection
%D
%D \startlinecorrection
%D \startcombination[5*1]
%D   {\SomeShade{20}{circular}{0}{.9green}{.3green}} {circular 0}
%D   {\SomeShade{21}{circular}{1}{.9green}{.3green}} {circular 1}
%D   {\SomeShade{22}{circular}{2}{.9green}{.3green}} {circular 2}
%D   {\SomeShade{23}{circular}{3}{.9green}{.3green}} {circular 3}
%D   {\SomeShade{24}{circular}{4}{.9green}{.3green}} {circular 4}
%D \stopcombination
%D \stoplinecorrection
%D
%D \startlinecorrection
%D \startcombination[4*1]
%D   {\SomeShade{30}{linear}{0}{.3red}{.9red}} {linear 0}
%D   {\SomeShade{31}{linear}{1}{.3red}{.9red}} {linear 1}
%D   {\SomeShade{32}{linear}{2}{.3red}{.9red}} {linear 2}
%D   {\SomeShade{33}{linear}{3}{.3red}{.9red}} {linear 3}
%D \stopcombination
%D \stoplinecorrection
%D
%D These macros closely cooperate with the \METAPOST\ module
%D \type {mp-spec.mp}, which is part of the \CONTEXT\
%D distribution.
%D
%D The low level (\PDF) implementation is based on the \TEX\
%D based \METAPOST\ to \PDF\ converter. Shading is supported
%D by overloading the \type {fill} operator as implemented
%D earlier. In \PDF\ type~2 and~3 shading functions are
%D specified in terms of:
%D
%D \starttabulate[|Tl|l|]
%D \NC /Domain \NC sort of meeting range \NC \NR
%D \NC /C0     \NC inner shade \NC \NR
%D \NC /C1     \NC outer shade \NC \NR
%D \NC /N      \NC smaller values, bigger inner circles \NC \NR
%D \stoptabulate
%D
%D An example of using both special features is the
%D following.
%D
%D \starttyping
%D \startMPpage
%D   externalfigure "hakker1b.png" scaled 22cm rotated  10 shifted (-2cm,0cm);
%D   externalfigure "hakker1b.png" scaled 10cm rotated -10 ;
%D   externalfigure "hakker1b.png" scaled  7cm rotated  45 shifted (8cm,12cm) ;
%D   path p ; p := unitcircle xscaled 15cm yscaled 20cm;
%D   path q ; q := p rotatedaround(center p,90) ;
%D   path r ; r := buildcycle(p,q) ; clip currentpicture to r ;
%D   path s ; s := boundingbox currentpicture enlarged 5mm ;
%D   picture c ; c := currentpicture ; currentpicture := nullpicture ;
%D   circular_shade(s,0,.2red,.9red) ;
%D   addto currentpicture also c ;
%D \stopMPpage
%D \stoptyping

\startMPinitializations
  mp_shade_version := 2 ;
\stopMPinitializations

%D This is done much cleaner in \MPLIB.

% %D A common hook.
%
% \let\MPfshowcommand\empty
%
% \def\MPStextext#1#2#3#4#5% if we clean up this plugin model, we can
%   {\def\MPtextdata{#3}%  % delegate the splitter to lua + redesign
%    \def\MPtextsize{#2}%
%    \def\lastMPmoveX{#4}%
%    \def\lastMPmoveY{#5}%
%    \defconvertedcommand\MPtextdata\MPtextdata % no edef
%    \splitstring\MPtextdata\at::::\to\MPtexttag\and\MPtextnumber
%    \executeifdefined{handleMPtext\MPtexttag}
%      {\setbox\scratchbox\hbox
%         {\font\temp=#1\space at #2\onebasepoint
%          \let\c\char
%          \temp
%          \MPfshowcommand{#3}}%
%       \setbox\scratchbox\hbox
%         {\hskip#4\onebasepoint
%          \raise#5\onebasepoint
%          \box\scratchbox}%
%       \smashbox\scratchbox
%       \box\scratchbox}}

\unexpanded\def\MPStextext#1#2#3#4#5% if we clean up this plugin model, we can
  {\setbox\scratchbox\hbox
     {\font\temp=#1\space at #2\onebasepoint \let\c\char \temp #3}%
   \setbox\scratchbox\hbox
     {\hskip#4\onebasepoint \raise#5\onebasepoint \box\scratchbox}%
   \smashbox\scratchbox
   \box\scratchbox}

%D The boundingbox.

\def\MPSboundingbox#1#2#3#4%
  {\xdef\MPllx{#1}\xdef\MPlly{#2}\xdef\MPurx{#3}\xdef\MPury{#4}%
   \xdef\MPwidth {\the\dimexpr#3\onebasepoint-#1\onebasepoint\relax}%
   \xdef\MPheight{\the\dimexpr#4\onebasepoint-#2\onebasepoint\relax}}

\MPSboundingbox0000

%D Test code:
%D
%D \startbuffer
%D \startMPcode
%D     fill fullcircle scaled 3cm withcolor red ;
%D     fill fullcircle scaled 2cm withcolor green ;
%D     fill fullcircle scaled 1cm withcolor blue ;
%D     currentpicture := currentpicture shifted (-4cm,0) ;
%D     fill fullcircle scaled 3cm withcolor cmyk(0,0,1,0) ;
%D     fill fullcircle scaled 2cm withcolor cmyk(0,1,0,0) ;
%D     fill fullcircle scaled 1cm withcolor cmyk(0,0,1,0) ;
%D     currentpicture := currentpicture shifted (-4cm,0) ;
%D     draw fullcircle scaled 3cm dashed evenly ;
%D     draw fullcircle scaled 2cm dashed withdots  ;
%D     draw origin withpen pencircle scaled 3mm;
%D     currentpicture := currentpicture shifted (-4cm,0) ;
%D     fill fullcircle scaled 2cm shifted (-.5cm,+.5cm) withcolor transparent(1,.5,red);
%D     fill fullcircle scaled 2cm shifted (-.5cm,-.5cm) withcolor transparent(1,.5,red);
%D     fill fullcircle scaled 2cm shifted (+.5cm,+.5cm) withcolor transparent(1,.5,green);
%D     fill fullcircle scaled 2cm shifted (+.5cm,-.5cm) withcolor transparent(1,.5,cmyk(1,0,1,.5));
%D     currentpicture := currentpicture shifted (12cm,-4cm) ;
%D     draw "o e p s" infont defaultfont scaled 2 shifted (-1cm,0) ;
%D     currentpicture := currentpicture shifted (-4cm,0) ;
%D     % bug: shift
%D     draw fullcircle scaled 3cm withpen pencircle yscaled 3mm xscaled 2mm rotated 30  ;
%D     draw fullcircle scaled 2cm withpen pencircle yscaled 3mm xscaled 2mm rotated 20 withcolor red ;
%D     filldraw fullcircle scaled 1cm withpen pencircle yscaled 3mm xscaled 2mm rotated 10 withcolor green ;
%D     currentpicture := currentpicture shifted (-4cm,0) ;
%D     % shade cannot handle shift
%D     circular_shade(fullcircle scaled 3cm,0,.2red,.9green) ;
%D     circular_shade(fullcircle scaled 3cm shifted(+4cm,0),0,cmyk(1,0,0,0),cmyk(0,1,0,0)) ;
%D     filldraw boundingbox currentpicture enlarged -3cm withpen pencircle scaled 1pt withcolor .5white ;
%D \stopMPcode
%D \stopbuffer
%D
%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection

\protect \endinput
