attr-ini.tex / last modification: 2008-09-23 14:19
%D \module
%D   [       file=attr-ini,
%D        version=2007.06.06,
%D          title=\CONTEXT\ Attribute Macros,
%D       subtitle=Initialization,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright=PRAGMA-ADE]
%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 Attribute Macros / initialization}

%D Although it's still somewhat experimental, here we introduce code
%D related to attributes.

\unprotect

\registerctxluafile{attr-ini}{1.001}

\newcount\attdefcounter

% \def\newattribute#1%
%   {\global\advance\attdefcounter\plusone
%    \global\attributedef#1\attdefcounter
%    \ctxlua{attributes.define("\strippedcsname#1",\number\attdefcounter)}}

% \newattribute\statusattribute
% \newattribute\colorattribute
% \newattribute\skipattribute
% \newattribute\penaltyattribute

\newtoks \attributesresetlist

\def\defineattribute[#1]% alternatively we can let lua do the housekeeping
  {\global\advance\attdefcounter\plusone
          \expandafter        \xdef\csname :attr:#1\endcsname{\number\attdefcounter}%
   \global\expandafter\attributedef\csname @attr@#1\endcsname        \attdefcounter
   \writestatus\m!systems{defining attribute #1 with number \the\attdefcounter}%
   \appendetoks\csname @attr@#1\endcsname\minusone\to\attributesresetlist
   \ctxlua{attributes.define("#1",\number\attdefcounter)}}

% expandable so we can \edef them for speed

\def\dosetattribute#1#2{\csname @attr@#1\endcsname#2\relax}
\def\doresetattribute#1{\csname @attr@#1\endcsname\minusone}
\def\dogetattribute  #1{\number\csname @attr@#1\endcsname}
\def\dogetattributeid#1{\csname :attr:#1\endcsname}

\let\dompattribute\gobbletwoarguments

\defineattribute[mark]
% \defineattribute[status] % used ? maybe combine with
\defineattribute[state]
\defineattribute[trigger] % feature inheritance
\defineattribute[skip]
\defineattribute[penalty]

\startruntimectxluacode
    nodes.trigger = \dogetattributeid{trigger}
\stopruntimectxluacode

% \defineattribute[ignore]
%
% \edef\startignorecontent{\dosetattribute{ignore}\plusone}
% \edef\stopignorecontent {\doresetattribute{ignore}}
%
% \startruntimectxluacode
%     nodes.ignore = \dogetattributeid{ignore}
% \stopruntimectxluacode

% \dosetattribute{status}{1}

% temp here / will be indirect ! just for testing

\defineattribute[colormodel]
\defineattribute[color]

% todo: no need for 'color' argument, we can set that once at startup; currently
% a bit inconsistent

% 1=off  2=gray  3=spot  4=rgb  5=cmyk  6=cmy % only 1/2/4/5 are supported
%
% We could combine this in one attribute but this is not faster and also
% less flexible because sometimes we want to freeze the attribute bit.
%
% Watch out: real color support will be implemented later.

\newcount\currentcolormodel

\def\setcolormodel#1%
  {\currentcolormodel\ctxlua{tex.print(colors.setmodel('colormodel','#1'))}%
   \dosetattribute{colormodel}{\the\currentcolormodel}}

\setcolormodel{all}

\appendtoks
    \setcolormodel{all}% redundant?
\to \everyjob

\def\registerrgbcolor   #1#2#3#4{\ctxlua{colors.register('color','#1','rgb' ,#2,#3,#4)}}
\def\registercmykcolor#1#2#3#4#5{\ctxlua{colors.register('color','#1','cmyk',#2,#3,#4,#5)}}
\def\registergraycolor      #1#2{\ctxlua{colors.register('color','#1','gray',#2)}}

% transparency

\defineattribute[transparency]

\def\registertransparency#1#2#3%
  {\setevalue{(ts:#1)}{\dosetattribute{transparency}{\ctxlua{tex.print(transparencies.register(#2,#3))}}}}

\def\sometransparencyswitch#1{\csname(ts:#1)\endcsname}

\def\sometransparencyswitch
  {\ctxlua{transparencies.enabled=true}%
   \gdef\sometransparencyswitch##1{\csname(ts:##1)\endcsname}%
   \sometransparencyswitch}

% \registertransparency {one} {1} {.5}
% \registertransparency {two} {1} {.6}

% overprint

\defineattribute[overprint]

\def\registeroverprint#1#2%
  {\setevalue{(os:#1)}{\dosetattribute{overprint}{\ctxlua{tex.print(overprints.register('#2'))}}}}

\def\dotriggeroverprint
  {\initializePDFoverprint % temp here, to be tested in la code (states.collect)
   \ctxlua{overprints.enabled=true}%
   \gdef\dotriggeroverprint##1{\csname(os:##1)\endcsname}%
   \dotriggeroverprint}

\registeroverprint{knockout} {knockout}
\registeroverprint{overprint}{overprint}

% negative

\defineattribute[negative]

\def\registernegative#1#2%
  {\setevalue{(ns:#1)}{\dosetattribute{negative}{\ctxlua{tex.print(negatives.register('#2'))}}}}

\def\dotriggernegative
  {\initializePDFnegative % temp here, to be tested in la code (states.collect)
   \ctxlua{negatives.enabled=true}%
   \gdef\dotriggernegative##1{\csname(ns:##1)\endcsname}%
   \dotriggernegative}

\registernegative{positive}{positive}
\registernegative{negative}{negative}

% effect

\defineattribute[effect]

\def\registereffect#1#2#3% #2=stretch #3=rulethickness
  {\setxvalue{(es:#1:#2:\number\dimexpr#3\relax)}%
     {\dosetattribute{effect}{\ctxlua{tex.print(effects.register('#1',#2,\number\dimexpr#3\relax))}}}}

\def\dotriggereffect
  {\ctxlua{effects.enabled=true}%
   \gdef\dotriggereffect##1##2##3%
     {\ifcsname(es:##1:##2:\number\dimexpr##3\relax)\endcsname\else\registereffect{##1}{##2}{##3}\fi
      \csname(es:##1:##2:\number\dimexpr##3\relax)\endcsname}%
   \dotriggereffect}

% \registereffect{normal}
% \registereffect{inner}
% \registereffect{outer}
% \registereffect{both}
% \registereffect{hidden}

% viewerlayers

\defineattribute[viewerlayer]

\def\registerviewerlayer#1#2%
  {\setevalue{(vl:#1)}{\dosetattribute{viewerlayer}{\ctxlua{tex.print(viewerlayers.register('#2'))}}}}

\setevalue{(vl:)}{\doresetattribute{viewerlayer}}

\def\dotriggerviewerlayer
  {\ctxlua{viewerlayers.enabled=true}%
   \gdef\dotriggerviewerlayer##1{\csname(vl:##1)\endcsname}%
   \dotriggerviewerlayer}

% ugly solution for backend handling

% \def\shipout
%   {%\writestatus{SHIPOUT}{CALLED AT PAGE \realfolio}%
%    \dowithnextbox
%      {\ctxlua{callbacks.push('hpack_filter',nodes.process_page)}%
%      %\writestatus{SHIPOUT}{START PACKAGING}%
%       \setbox\nextbox\hbox{\box\nextbox}%
%      %\writestatus{SHIPOUT}{STOP PACKAGING}%
%       \ctxlua{callbacks.pop('hpack_filter')}%
%       \primitive\shipout\box\nextbox}}

% \def\shipout
%   {\dowithnextbox
%      {\ctxlua{nodes.process_page(tex.box[\number\nextbox])}%
%       \primitive\shipout\box\nextbox}}

% Objects are processed indepently \unknown\ actually we may need a proper callback.

\newbox\finalizedshipoutbox

\def\finalizeobjectbox#1{\ctxlua{nodes.process_page(tex.box[\number#1])}}

\def\finalizeshipoutbox#1% % hack till we have access to pdf backend
  {\global\setbox\finalizedshipoutbox\hbox{#1}%
   \finalizeobjectbox\finalizedshipoutbox
   \hbox{\ctxlua{states.flush()}\box\finalizedshipoutbox}}

\let\normalshipout\shipout

% tricky stuff:

\newcount\attributeboxcount

\edef\startinheritattributes{\dosetattribute  {trigger}{1}}
\edef\stopinheritattributes {\doresetattribute{trigger}}

\def\doattributedcopy  {\afterassignment\dodoattributedcopy\attributeboxcount}
\def\doattributedbox   {\afterassignment\dodoattributedbox \attributeboxcount}

\def\dodoattributedcopy
  {\startinheritattributes
   \ifvbox\attributeboxcount
     \vbox{\unvcopy\attributeboxcount}%
   \else
     \hbox{\unhcopy\attributeboxcount}%
   \fi
   \stopinheritattributes}

\def\dodoattributedbox
  {\startinheritattributes
   \ifvbox\attributeboxcount
     \vbox{\unvbox\attributeboxcount}%
   \else
     \hbox{\unhbox\attributeboxcount}%
   \fi
   \stopinheritattributes}

\def\enableattributeinheritance
  {\ctxlua{nodes.triggering=true}%
   \let\attributedcopy\doattributedcopy
   \let\attributedbox \doattributedbox}

\def\disableattributeinheritance
  {\ctxlua{nodes.triggering=false}%
   \let\attributedcopy\copy
   \let\attributedbox \box}

\disableattributeinheritance

% \enableattributeinheritance % will become default

\protect \endinput

% test case
%
% {\green \hbox to \hsize{\leaders\hrule  \hfill a}\par}
% {\red   \hbox to \hsize{\leaders\hbox{x}\hfill a}\par}