%D \module
%D   [       file=mp-grph.mpiv,
%D        version=2000.12.14,
%D          title=\CONTEXT\ \METAPOST\ graphics,
%D       subtitle=graphic text support,
%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 licen-en.pdf for
%C details.

%D Under construction.

if known context_grph : endinput ; fi ;

boolean context_grph ; context_grph := true ;

picture _currentpicture_ ;

numeric _fig_nesting_ ; _fig_nesting_ := 0 ;

def beginfig (expr c) =
    _fig_nesting_ := _fig_nesting_ + 1 ;
    if _fig_nesting_ = 1 :
        begingroup
        charcode := c ;
        resetfig ;
        scantokens extra_beginfig ;
    fi ;
enddef ;

def endfig =
    ; % safeguard
    if _fig_nesting_ = 1 :
        scantokens extra_endfig ;
        shipit ;
        endgroup ;
    fi ;
    _fig_nesting_ := _fig_nesting_ - 1 ;
enddef;

def resetfig =
    clearxy ;
    clearit ;
    clearpen ;
    pickup defaultpen ;
    interim linecap := linecap ;
    interim linejoin := linejoin ;
    interim miterlimit := miterlimit ;
    save _background_ ; color _background_ ; _background_ :=  background  ;
    save  background  ; color  background  ;  background  := _background_ ;
    drawoptions () ;
enddef ;

def protectgraphicmacros =
    save showtext ;
    save beginfig ; let beginfig = begingraphictextfig ;
    save endfig   ; let endfig   = endgraphictextfig ;
    save end      ; let end      = relax ;
    interim prologues := prologues ;
    resetfig ; % resets currentpicture
enddef ;

numeric currentgraphictext ; currentgraphictext := 0 ;

def data_mpo_file = job_name & "-mpgraph.mpo" enddef ;
def data_mpy_file = job_name & "-mpgraph.mpy" enddef ;

def begingraphictextfig (expr n) =
    foundpicture := n ;
    scratchpicture := nullpicture ;
enddef ;

def endgraphictextfig =
    if foundpicture = currentgraphictext :
        expandafter endinput
    else :
        scratchpicture := nullpicture ;
    fi ;
enddef ;

def loadfigure primary filename =
    doloadfigure (filename)
enddef ;

def doloadfigure (expr filename) text figureattributes =
    begingroup ;
    save figurenumber, figurepicture, number, fixedplace ;
    numeric figurenumber  ; figurenumber := 0 ;
    boolean figureshift ; figureshift := true ;
    picture figurepicture ; figurepicture := currentpicture ;
    def number primary n = hide(figurenumber := n) enddef ;
    def fixedplace = hide(figureshift := false) enddef ;
    protectgraphicmacros ;
    % defaults
    interim linecap    := rounded ;
    interim linejoin   := rounded ;
    interim miterlimit := 10 ;
    %
    currentpicture := nullpicture ;
    draw fullcircle figureattributes ; % expand number
    currentpicture := nullpicture ;
    def beginfig (expr n) =
        currentpicture := nullpicture ;
        if (figurenumber=n) or (figurenumber=0) :
            let endfig = endinput ;
        fi ;
    enddef ;
    let endfig = relax ;
    readfile(filename) ;
    if figureshift :
        currentpicture := currentpicture shifted -llcorner currentpicture ;
    fi ;
    addto figurepicture also currentpicture figureattributes ;
    currentpicture := figurepicture  ;
    endgroup ;
enddef ;

def graphictext primary t =
    hide (
        if mfun_trial_run :
            let mfun_graphic_text = mfun_no_graphic_text ;
        else :
            let mfun_graphic_text = mfun_do_graphic_text ;
        fi
    )
    mfun_graphic_text(t)
enddef ;

def mfun_do_graphic_text (expr t) =
    % withprescript "gt_stage=final"
    begingroup ;
    save figurepicture ; picture figurepicture ;
    figurepicture := currentpicture ; currentpicture := nullpicture ;
    currentgraphictext := currentgraphictext + 1 ;
    mfun_finish_graphic_text % picks up directives
enddef ;

def mfun_no_graphic_text (expr t) text rest =
    draw unitsquare withprescript "gt_stage=trial" withpostscript t
enddef ;

def mfun_finish_graphic_text text x_op_x =
    protectgraphicmacros ; % resets currentpicture
    interim linecap    := butt ;     % normally rounded
    interim linejoin   := mitered ;  % normally rounded
    interim miterlimit := 10 ;       % todo
    let normalwithshade = withshade ;
    save foundpicture, scratchpicture, str ;
    save fill, draw, withshade, reversefill, outlinefill ;
    save withfillcolor, withdrawcolor ; % quite important
    numeric foundpicture ; picture scratchpicture ; string str ;
    def draw expr p =
        % the first, naive implementation was:
        %   addto scratchpicture doublepath p withpen currentpen ;
        % but it is better to turn lines into fills
        addto scratchpicture contour boundingbox
            image (addto currentpicture doublepath p withpen currentpen) ;
    enddef ;
    def fill expr p =
        addto scratchpicture contour p withpen currentpen ;
    enddef ;
    def f_op_f = enddef ; boolean f_color ; f_color := false ;
    def d_op_d = enddef ; boolean d_color ; d_color := false ;
    def s_op_s = enddef ; boolean s_color ; s_color := false ;
    boolean reverse_fill ; reverse_fill := false ;
    boolean outline_fill ; outline_fill := false ;
    def reversefill =
        hide(reverse_fill := true )
    enddef ;
    def outlinefill =
        hide(outline_fill := true )
    enddef ;
    def withshade primary c =
        hide(def s_op_s = normalwithshade c enddef ; s_color := true )
    enddef ;
    def withfillcolor primary c =
        hide(def f_op_f = withcolor c enddef ; f_color := true )
    enddef ;
    def withdrawcolor primary c =
        hide(def d_op_d = withcolor c enddef ; d_color := true )
    enddef ;
    scratchpicture := nullpicture ;
    addto scratchpicture doublepath origin x_op_x ; % pre-roll
    for i within scratchpicture : % Below here is a dirty tricky test!
        if (urcorner dashpart i) = origin :
            outline_fill := false ;
        fi ;
    endfor ;
    scratchpicture := nullpicture ;
    readfile(data_mpy_file) ;
    scratchpicture := (scratchpicture shifted -llcorner scratchpicture) scaled (1/10) ;
    if not d_color and not f_color :
        d_color := true ;
    fi
    if s_color :
        d_color := false ;
        f_color := false ;
    fi ;
    currentpicture := figurepicture ;
    if d_color and not reverse_fill :
        for i within scratchpicture :
            if f_color and outline_fill :
                addto currentpicture doublepath pathpart i _op_ x_op_x f_op_f dashed nullpicture ;
            fi ;
            if filled i :
                addto currentpicture doublepath pathpart i _op_ x_op_x d_op_d ;
            fi ;
        endfor ;
    fi ;
    if f_color :
        for i within scratchpicture :
            if filled i :
                addto currentpicture contour pathpart i _op_ x_op_x f_op_f withpen pencircle scaled 0 ;
            fi ;
        endfor ;
    fi ;
    if d_color and reverse_fill :
        for i within scratchpicture :
            if filled i :
                addto currentpicture doublepath pathpart i _op_ x_op_x d_op_d ;
            fi ;
        endfor ;
    fi ;
    if s_color :
        for i within scratchpicture :
            if filled i :
                addto currentpicture contour pathpart i _op_ x_op_x s_op_s ;
            fi ;
        endfor ;
    else :
        for i within scratchpicture :
            if stroked i :
                addto currentpicture doublepath pathpart i _op_ x_op_x d_op_d ;
            fi ;
        endfor ;
    fi ;
    endgroup ;
enddef ;

% example
%
% beginfig (1) ;
%     graphictext
%         "\vbox{\hsize10cm \input tufte }"
%         scaled 8
%         withdrawcolor blue
%         withfillcolor red
%         withpen pencircle scaled 2pt ;
% endfig ;
%
% beginfig(1) ;
%       loadfigure "gracht.mp" rotated 20 ;
%       loadfigure "koe.mp" number 1 scaled 2 ;
% endfig ;
%
% end
