%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 changes.

if known context_page : endinput ; fi ;

boolean context_page ; context_page := true ;

% def LoadPageState =
%     % now always set
% enddef ;
%
% 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 ;
%
% numeric mfun_temp ;
%
% def SwapPageState =
%     if not OnRightPage :
%              BackSpace := PaperWidth-MakeupWidth-BackSpace ;
%               CutSpace := PaperWidth-MakeupWidth-CutSpace ;
%              mfun_temp := LeftMarginWidth ;
%        LeftMarginWidth := RightMarginWidth ;
%       RightMarginWidth := mfun_temp ;
%              mfun_temp := LeftMarginDistance ;
%     LeftMarginDistance := RightMarginDistance ;
%    RightMarginDistance := mfun_temp ;
%              mfun_temp := LeftEdgeWidth ;
%          LeftEdgeWidth := RightEdgeWidth ;
%         RightEdgeWidth := mfun_temp ;
%              mfun_temp := LeftEdgeDistance ;
%       LeftEdgeDistance := RightEdgeDistance ;
%      RightEdgeDistance := mfun_temp ;
%
%   % 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 ;

% the new way:

def LoadPageState = enddef ; % now always set
def SwapPageState = enddef ; % dynamic

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

% Next we implement the the page area model. First some constants.

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

numeric HorPos ; HorPos := 0 ;
numeric VerPos ; VerPos := 0 ;

% We used to initialize these variables each (sub)run but at some point MP
% became too slow for this. See later.

% path Area[][] ;
% pair Location[][] ;
% path Field[][] ;
%
% numeric Hstep[] ;
% numeric Hsize[] ;
% numeric Vstep[] ;
% numeric Vsize[] ;
%
% 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 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 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 SetAreaVariables =
    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 ;
enddef ;

% we should make Page no path .. from now on don't assume this .. for a while we keek it

vardef FrontPageWidth  = PaperWidth enddef ;
vardef BackPageWidth   = PaperWidth enddef ;
vardef CoverWidth      = 2 * PaperWidth + SpineWidth enddef ;
vardef CoverHeight     = PaperHeight enddef ;

vardef FrontPageHeight = PaperHeight enddef ;
vardef BackPageHeight  = PaperHeight enddef ;
vardef SpineHeight     = PaperHeight enddef ;

def SetPagePage      = path Page      ; Page      := unitsquare xscaled PaperWidth      yscaled PaperHeight ; enddef ;
def SetPageCoverPage = path CoverPage ; CoverPage := unitsquare xscaled CoverWidth      yscaled CoverHeight ; enddef ;
def SetPageSpine     = path Spine     ; Spine     := unitsquare xscaled SpineWidth      yscaled CoverHeight shifted (BackPageWidth,0) ; enddef ;
def SetPageBackPage  = path BackPage  ; BackPage  := unitsquare xscaled BackPageWidth   yscaled CoverHeight ; enddef ;
def SetPageFrontPage = path FrontPage ; FrontPage := unitsquare xscaled FrontPageWidth  yscaled CoverHeight shifted (BackPageWidth+SpineWidth,0) ; enddef ;

def mfun_page_Page      = hide(SetPagePage     ;) Page      enddef ;
def mfun_page_CoverPage = hide(SetPageCoverPage;) CoverPage enddef ;
def mfun_page_Spine     = hide(SetPageSpine    ;) Spine     enddef ;
def mfun_page_BackPage  = hide(SetPageBackPage ;) BackPage  enddef ;
def mfun_page_FrontPage = hide(SetPageFrontPage;) FrontPage enddef ;

def SetPageVariables =
    SetAreaVariables ;
    %
    let Page      = mfun_page_Page ;
    let CoverPage = mfun_page_CoverPage ;
    let Spine     = mfun_page_Spine ;
    let BackPage  = mfun_page_BackPage ;
    let FrontPage = mfun_page_FrontPage ;
enddef ;

SetPageVariables ;

let SetPageAreas = SetPageVariables ;  % compatiblity

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

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

def StopPage =
    BoundPageAreas ;
    endgroup ;
enddef ;

% cover pages

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

let SetCoverAreas = SetPageVariables ;  % compatiblity

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

def StopCover =
    BoundCoverAreas ;
    endgroup ;
enddef ;

% overlays:

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

def BoundToOverlayBox =
    setbounds currentpicture to OverlayBox;
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 ;

% for the moment we put these here:

string  RuleDirection ; RuleDirection := "" ;
string  RuleOption    ; RuleOption    := "" ;
numeric RuleWidth     ; RuleWidth     := 0 ;
numeric RuleHeight    ; RuleHeight    := 0 ;
numeric RuleDepth     ; RuleDepth     := 0 ;
numeric RuleH         ; RuleH         := 0 ;
numeric RuleV         ; RuleV         := 0 ;
numeric RuleThickness ; RuleThickness := 0 ;
numeric RuleFactor    ; RuleFactor    := 0 ;
numeric RuleOffset    ; RuleOffset    := 0 ;
                    def RuleColor      = (.5white) enddef ;

def FakeWord(expr RuleWidth, RuleHeight, RuleDepth, RuleThickness) (text RuleColor) =
    fill unitsquare
        xscaled RuleWidth
        yscaled (RuleDepth-RuleThickness/2)
        withcolor RuleColor ;
    fill unitsquare
        xscaled RuleWidth
        yscaled (RuleHeight-RuleDepth-RuleThickness/2)
        shifted (0,RuleDepth+RuleThickness)
        withcolor RuleColor ;
enddef ;

def FakeRule(expr RuleWidth, RuleHeight, RuleDepth, RuleThickness) (text RuleColor) =
    fill unitsquare
        xscaled RuleWidth
        yscaled RuleHeight
        withcolor RuleColor ;
enddef ;