%D \module
%D   [       file=mp-page.mpiv,
%D        version=1999.03.10,
%D          title=\CONTEXT\ \METAPOST\ graphics,
%D       subtitle=page enhancements,
%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.

%D This module is rather preliminary and subjected to
%D changes.

if known context_page : endinput ; fi ;

boolean context_page ; context_page := true ;

if unknown PageStateAvailable :
    boolean PageStateAvailable ;
    PageStateAvailable := false ;
fi ;

if unknown OnRightPage :
    boolean OnRightPage ;
    OnRightPage := true ;
fi ;

if unknown OnOddPage :
    boolean OnOddPage ;
    OnOddPage := true ;
fi ;

if unknown InPageBody :
    boolean InPageBody ;
    InPageBody := false ;
fi ;

string CurrentLayout ;

CurrentLayout       := "default" ;

PageNumber          := 0 ;
PaperHeight         := 845.04684pt  ;
PaperWidth          := 597.50787pt  ;
PrintPaperHeight    := 845.04684pt  ;
PrintPaperWidth     := 597.50787pt  ;
TopSpace            :=  71.12546pt  ;
BottomSpace         :=   0.0pt      ;
BackSpace           :=  71.13275pt  ;
CutSpace            :=   0.0pt      ;
MakeupHeight        := 711.3191pt   ;
MakeupWidth         := 426.78743pt  ;
TopHeight           :=   0.0pt      ;
TopDistance         :=   0.0pt      ;
HeaderHeight        :=  56.90294pt  ;
HeaderDistance      :=   0.0pt      ;
TextHeight          := 597.51323pt  ;
FooterDistance      :=   0.0pt      ;
FooterHeight        :=  56.90294pt  ;
BottomDistance      :=   0.0pt      ;
BottomHeight        :=   0.0pt      ;
LeftEdgeWidth       :=   0.0pt      ;
LeftEdgeDistance    :=   0.0pt      ;
LeftMarginWidth     :=   75.58197pt ;
LeftMarginDistance  :=   11.99829pt ;
TextWidth           :=  426.78743pt ;
RightMarginDistance :=   11.99829pt ;
RightMarginWidth    :=   75.58197pt ;
RightEdgeDistance   :=    0.0pt     ;
RightEdgeWidth      :=    0.0pt     ;

PageOffset          :=    0.0pt     ;
PageDepth           :=    0.0pt     ;

LayoutColumns       :=    0         ;
LayoutColumnDistance:=    0.0pt     ;
LayoutColumnWidth   :=    0.0pt     ;

LeftEdge             :=  -4 ; Top             := -40 ;
LeftEdgeSeparator    :=  -3 ; TopSeparator    := -30 ;
LeftMargin           :=  -2 ; Header          := -20 ;
LeftMarginSeparator  :=  -1 ; HeaderSeparator := -10 ;
Text                 :=   0 ; Text            :=   0 ;
RightMarginSeparator :=  +1 ; FooterSeparator := +10 ;
RightMargin          :=  +2 ; Footer          := +20 ;
RightEdgeSeparator   :=  +3 ; BottomSeparator := +30 ;
RightEdge            :=  +4 ; Bottom          := +40 ;

Margin      := LeftMargin  ; % obsolete
Edge        := LeftEdge    ; % obsolete
InnerMargin := RightMargin ; % obsolete
InnerEdge   := RightEdge   ; % obsolete
OuterMargin := LeftMargin  ; % obsolete
OuterEdge   := LeftEdge    ; % obsolete

InnerMarginWidth     := 0pt ;
OuterMarginWidth     := 0pt ;
InnerMarginDistance  := 0pt ;
OuterMarginDistance  := 0pt ;

InnerEdgeWidth     := 0pt ;
OuterEdgeWidth     := 0pt ;
InnerEdgeDistance  := 0pt ;
OuterEdgeDistance  := 0pt ;

% path Area[][] ;
% pair Location[][] ;
% path Field[][] ;

% numeric Hstep[] ;
% numeric Hsize[] ;
% numeric Vstep[] ;
% numeric Vsize[] ;

path Page ;

numeric HorPos ;
numeric VerPos ;

% for VerPos=Top step 10 until Bottom:
%     for HorPos=LeftEdge step 1 until RightEdge:
%         Area[HorPos][VerPos] := origin--cycle ;
%         Area[VerPos][HorPos] := Area[HorPos][VerPos] ;
%         Location[HorPos][VerPos] := origin ;
%         Location[VerPos][HorPos] := Location[HorPos][VerPos] ;
%         Field[HorPos][VerPos] := origin--cycle ;
%         Field[VerPos][HorPos] := Field[HorPos][VerPos] ;
%     endfor ;
% endfor ;

% def LoadPageState =
%   scantokens "input mp-state.tmp" ;
% enddef ;

def SwapPageState =
    if not OnRightPage :
             BackSpace := PaperWidth-MakeupWidth-BackSpace ;
              CutSpace := PaperWidth-MakeupWidth-CutSpace ;
                     i := LeftMarginWidth ;
       LeftMarginWidth := RightMarginWidth ;
      RightMarginWidth := i ;
                     i := LeftMarginDistance ;
    LeftMarginDistance := RightMarginDistance ;
   RightMarginDistance := i ;
                     i := LeftEdgeWidth ;
         LeftEdgeWidth := RightEdgeWidth ;
        RightEdgeWidth := i ;
                     i := LeftEdgeDistance ;
      LeftEdgeDistance := RightEdgeDistance ;
     RightEdgeDistance := i ;

  % these are now available as ..Width and ..Distance

                Margin := LeftMargin ;
                  Edge := LeftEdge ;
           InnerMargin := RightMargin ;
             InnerEdge := RightEdge ;
           OuterMargin := LeftMargin ;
             OuterEdge := LeftEdge ;
    else :
                Margin := RightMargin ;
                  Edge := RightEdge ;
           InnerMargin := LeftMargin ;
             InnerEdge := LeftEdge ;
           OuterMargin := RightMargin ;
             OuterEdge := RightEdge ;
    fi ;
enddef ;

% def SetPageAreas =
%
%     numeric Vsize[], Hsize[], Vstep[], Hstep[] ;
%
%     Vsize[Top]             = TopHeight ;
%     Vsize[TopSeparator]    = TopDistance ;
%     Vsize[Header]          = HeaderHeight ;
%     Vsize[HeaderSeparator] = HeaderDistance ;
%     Vsize[Text]            = TextHeight ;
%     Vsize[FooterSeparator] = FooterDistance ;
%     Vsize[Footer]          = FooterHeight ;
%     Vsize[BottomSeparator] = BottomDistance ;
%     Vsize[Bottom]          = BottomHeight ;
%
%     Vstep[Top]             = Vstep[TopSeparator]   +Vsize[TopSeparator] ;
%     Vstep[TopSeparator]    = PaperHeight-TopSpace ;
%     Vstep[Header]          = Vstep[TopSeparator]   -Vsize[Header] ;
%     Vstep[HeaderSeparator] = Vstep[Header]         -Vsize[HeaderSeparator] ;
%     Vstep[Text]            = Vstep[HeaderSeparator]-Vsize[Text] ;
%     Vstep[FooterSeparator] = Vstep[Text]           -Vsize[FooterSeparator] ;
%     Vstep[Footer]          = Vstep[FooterSeparator]-Vsize[Footer] ;
%     Vstep[BottomSeparator] = Vstep[Footer]         -Vsize[BottomSeparator] ;
%     Vstep[Bottom]          = Vstep[BottomSeparator]-Vsize[Bottom] ;
%
%     Hsize[LeftEdge]             = LeftEdgeWidth ;
%     Hsize[LeftEdgeSeparator]    = LeftEdgeDistance ;
%     Hsize[LeftMargin]           = LeftMarginWidth ;
%     Hsize[LeftMarginSeparator]  = LeftMarginDistance ;
%     Hsize[Text]                 = MakeupWidth ;
%     Hsize[RightMarginSeparator] = RightMarginDistance ;
%     Hsize[RightMargin]          = RightMarginWidth ;
%     Hsize[RightEdgeSeparator]   = RightEdgeDistance ;
%     Hsize[RightEdge]            = RightEdgeWidth ;
%
%     Hstep[LeftEdge]             = Hstep[LeftEdgeSeparator]   -Hsize[LeftEdge] ;
%     Hstep[LeftEdgeSeparator]    = Hstep[LeftMargin]          -Hsize[LeftEdgeSeparator] ;
%     Hstep[LeftMargin]           = Hstep[LeftMarginSeparator] -Hsize[LeftMargin] ;
%     Hstep[LeftMarginSeparator]  = Hstep[Text]                -Hsize[LeftMarginSeparator] ;
%     Hstep[Text]                 = BackSpace ;
%     Hstep[RightMarginSeparator] = Hstep[Text]                +Hsize[Text] ;
%     Hstep[RightMargin]          = Hstep[RightMarginSeparator]+Hsize[RightMarginSeparator] ;
%     Hstep[RightEdgeSeparator]   = Hstep[RightMargin]         +Hsize[RightMargin] ;
%     Hstep[RightEdge]            = Hstep[RightEdgeSeparator]  +Hsize[RightEdgeSeparator] ;
%
%     for VerPos=Top step 10 until Bottom:
%         for HorPos=LeftEdge step 1 until RightEdge:
%             Area[HorPos][VerPos] := unitsquare xscaled Hsize[HorPos] yscaled Vsize[VerPos] ;
%             Area[VerPos][HorPos] := Area[HorPos][VerPos] ;
%             Location[HorPos][VerPos] := (Hstep[HorPos],Vstep[VerPos]) ;
%             Location[VerPos][HorPos] := Location[HorPos][VerPos] ;
%             Field[HorPos][VerPos] := Area[HorPos][VerPos] shifted Location[HorPos][VerPos] ;
%             Field[VerPos][HorPos] := Field[HorPos][VerPos] ;
%         endfor ;
%     endfor ;
%
%     Page := unitsquare xscaled PaperWidth yscaled PaperHeight ;
%
% enddef ;
%
% def BoundPageAreas =
%     % pickup pencircle scaled 0pt ;
%     bboxmargin := 0 ; setbounds currentpicture to Page ;
% enddef ;
%
% def StartPage =
%     begingroup ;
%     if PageStateAvailable :
%         LoadPageState ;
%         SwapPageState ;
%     fi ;
%     SetPageAreas ;
%     BoundPageAreas ;
% enddef ;
%
% def StopPage =
%     BoundPageAreas ;
%     endgroup ;
% enddef ;

% Because metapost > 1.50 has dynamic memory management and is less
% efficient than before we now delay calculations ... (on a document
% with 150 pages the time spent in mp was close to 5 seconds which was
% only due to initialising the page related areas, something that was
% hardly noticeable before. At least now we're back to half a second
% for such a case.

def SetPageVsize =
    numeric Vsize[] ;
    Vsize[Top]             = TopHeight ;
    Vsize[TopSeparator]    = TopDistance ;
    Vsize[Header]          = HeaderHeight ;
    Vsize[HeaderSeparator] = HeaderDistance ;
    Vsize[Text]            = TextHeight ;
    Vsize[FooterSeparator] = FooterDistance ;
    Vsize[Footer]          = FooterHeight ;
    Vsize[BottomSeparator] = BottomDistance ;
    Vsize[Bottom]          = BottomHeight ;
enddef ;

def SetPageHsize =
    numeric Hsize[] ;
    Hsize[LeftEdge]             = LeftEdgeWidth ;
    Hsize[LeftEdgeSeparator]    = LeftEdgeDistance ;
    Hsize[LeftMargin]           = LeftMarginWidth ;
    Hsize[LeftMarginSeparator]  = LeftMarginDistance ;
    Hsize[Text]                 = MakeupWidth ;
    Hsize[RightMarginSeparator] = RightMarginDistance ;
    Hsize[RightMargin]          = RightMarginWidth ;
    Hsize[RightEdgeSeparator]   = RightEdgeDistance ;
    Hsize[RightEdge]            = RightEdgeWidth ;
enddef ;

def SetPageVstep =
    numeric Vstep[] ;
    Vstep[Top]             = Vstep[TopSeparator]   +Vsize[TopSeparator] ;
    Vstep[TopSeparator]    = PaperHeight-TopSpace ;
    Vstep[Header]          = Vstep[TopSeparator]   -Vsize[Header] ;
    Vstep[HeaderSeparator] = Vstep[Header]         -Vsize[HeaderSeparator] ;
    Vstep[Text]            = Vstep[HeaderSeparator]-Vsize[Text] ;
    Vstep[FooterSeparator] = Vstep[Text]           -Vsize[FooterSeparator] ;
    Vstep[Footer]          = Vstep[FooterSeparator]-Vsize[Footer] ;
    Vstep[BottomSeparator] = Vstep[Footer]         -Vsize[BottomSeparator] ;
    Vstep[Bottom]          = Vstep[BottomSeparator]-Vsize[Bottom] ;
enddef ;

def SetPageHstep =
    numeric Hstep[] ;
    Hstep[LeftEdge]             = Hstep[LeftEdgeSeparator]   -Hsize[LeftEdge] ;
    Hstep[LeftEdgeSeparator]    = Hstep[LeftMargin]          -Hsize[LeftEdgeSeparator] ;
    Hstep[LeftMargin]           = Hstep[LeftMarginSeparator] -Hsize[LeftMargin] ;
    Hstep[LeftMarginSeparator]  = Hstep[Text]                -Hsize[LeftMarginSeparator] ;
    Hstep[Text]                 = BackSpace ;
    Hstep[RightMarginSeparator] = Hstep[Text]                +Hsize[Text] ;
    Hstep[RightMargin]          = Hstep[RightMarginSeparator]+Hsize[RightMarginSeparator] ;
    Hstep[RightEdgeSeparator]   = Hstep[RightMargin]         +Hsize[RightMargin] ;
    Hstep[RightEdge]            = Hstep[RightEdgeSeparator]  +Hsize[RightEdgeSeparator] ;
enddef ;

def SetPageArea =
    path Area[][] ;
    for VerPos=Top step 10 until Bottom:
        for HorPos=LeftEdge step 1 until RightEdge:
            Area[HorPos][VerPos] := unitsquare xscaled Hsize[HorPos] yscaled Vsize[VerPos] ;
            Area[VerPos][HorPos] := Area[HorPos][VerPos] ;
        endfor ;
    endfor ;
enddef ;

def SetPageLocation =
    pair Location[][] ;
    for VerPos=Top step 10 until Bottom:
        for HorPos=LeftEdge step 1 until RightEdge:
            Location[HorPos][VerPos] := (Hstep[HorPos],Vstep[VerPos]) ;
            Location[VerPos][HorPos] := Location[HorPos][VerPos] ;
        endfor ;
    endfor ;
enddef ;

def SetPageField =
    path Field[][] ;
    for VerPos=Top step 10 until Bottom:
        for HorPos=LeftEdge step 1 until RightEdge:
            Field[HorPos][VerPos] := unitsquare xscaled Hsize[HorPos] yscaled Vsize[VerPos] shifted (Hstep[HorPos],Vstep[VerPos]) ;
            Field[VerPos][HorPos] := Field[HorPos][VerPos] ;
        endfor ;
    endfor ;
enddef ;

def SetPagePage =
    path Page ;
    Page := unitsquare xscaled PaperWidth yscaled PaperHeight ;
enddef ;

def mfun_page_Area     = hide(SetPageArea     ;) Area     enddef ;
def mfun_page_Location = hide(SetPageLocation ;) Location enddef ;
def mfun_page_Field    = hide(SetPageField    ;) Field    enddef ;
def mfun_page_Vsize    = hide(SetPageVsize    ;) Vsize    enddef ;
def mfun_page_Hsize    = hide(SetPageHsize    ;) Hsize    enddef ;
def mfun_page_Vstep    = hide(SetPageVstep    ;) Vstep    enddef ;
def mfun_page_Hstep    = hide(SetPageHstep    ;) Hstep    enddef ;
def mfun_page_Page     = hide(SetPagePage     ;) Page     enddef ;

def SetPageVariables =
    let Area     = mfun_page_Area     ;
    let Location = mfun_page_Location ;
    let Field    = mfun_page_Field    ;
    let Vsize    = mfun_page_Vsize    ;
    let Hsize    = mfun_page_Hsize    ;
    let Vstep    = mfun_page_Vstep    ;
    let Hstep    = mfun_page_Hstep    ;
    let Page     = mfun_page_Page     ;
enddef ;

SetPageVariables ;

let SetPageAreas = SetPageVariables ;  % compatiblity

def BoundPageAreas =
    % pickup pencircle scaled 0pt ;
    bboxmargin := 0 ; setbounds currentpicture to Page ;
enddef ;

def StartPage =
    begingroup ;
    if mfun_first_run :
        if PageStateAvailable :
            LoadPageState ;
            SwapPageState ;
        fi ;
        SetPageVariables ;
    fi ;
    BoundPageAreas ;
enddef ;

def StopPage =
    BoundPageAreas ;
    endgroup ;
enddef ;

% cover pages

def BoundCoverAreas =
    % todo: add cropmarks
    bboxmargin := 0 ; setbounds currentpicture to Paper enlarged PaperBleed ;
enddef ;

def SetCoverAreas =

    if unknown SpineWidth :
        SpineWidth := 8mm ;
    fi ;

    if unknown PaperBleed :
        PaperBleed := 0 ;
    fi ;

    FrontPageWidth  := PaperWidth ;
    BackPageWidth   := PaperWidth ;
    PaperWidth      := 2 * PaperWidth + SpineWidth ;

    FrontPageHeight := PaperHeight ;
    BackPageHeight  := PaperHeight ;
    PaperHeight     := PaperHeight ;
    SpineHeight     := PaperHeight ;

    path Paper     ; Paper     := unitsquare xscaled PaperWidth      yscaled PaperHeight ;
    path Spine     ; Spine     := unitsquare xscaled SpineWidth      yscaled PaperHeight shifted (BackPageWidth,0);
    path BackPage  ; BackPage  := unitsquare xscaled BackPageWidth   yscaled PaperHeight ;
    path FrontPage ; FrontPage := unitsquare xscaled FrontPageWidth  yscaled PaperHeight shifted (BackPageWidth+SpineWidth,0) ;

enddef ;

% def StartCover =
%     begingroup ;
%     if PageStateAvailable :
%         LoadPageState ;
%      %  SwapPageState ;
%     fi ;
%     SetPageAreas ;
%     SetCoverAreas ;
%     BoundCoverAreas ;
% enddef ;

def StartCover =
    begingroup ;
    if mfun_first_run :
        if PageStateAvailable :
            LoadPageState ;
         %  SwapPageState ;
        fi ;
        SetPageVariables ; % was SetPageAreas ;
        SetCoverAreas ;
    fi ;
    BoundCoverAreas ;
enddef ;

def StopCover =
    BoundCoverAreas ;
    endgroup ;
enddef ;

% overlays:

def OverlayBox =
    (unitsquare xyscaled (OverlayWidth,OverlayHeight))
enddef ;

% handy

def innerenlarged =
      hide(LoadPageState)
      if OnRightPage : leftenlarged  else : rightenlarged fi
enddef ;

def outerenlarged =
      hide(LoadPageState)
      if OnRightPage : rightenlarged else : leftenlarged  fi
enddef ;

% obsolete

def llEnlarged (expr p,d) = (llcorner p shifted (-d,-d)) enddef ;
def lrEnlarged (expr p,d) = (lrcorner p shifted (+d,-d)) enddef ;
def urEnlarged (expr p,d) = (urcorner p shifted (+d,+d)) enddef ;
def ulEnlarged (expr p,d) = (ulcorner p shifted (-d,+d)) enddef ;

def Enlarged (expr p, d) =
      (llEnlarged (p,d) --
       lrEnlarged (p,d) --
       urEnlarged (p,d) --
       ulEnlarged (p,d) -- cycle)
enddef ;
