%D \module %D [ file=pack-obj, %D version=1998.01.15, %D title=\CONTEXT\ Packaging Macros, %D subtitle=Objects, %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. % todo, move more to mkiv, get rid of blabelgroup \writestatus{loading}{ConTeXt Packaging Macros / Objects} \unprotect %D \macros %D {setobject,getobject,ifinobject} %D %D Boxes can be considered reuable objects. Unfortunaltely once %D passed to the \DVI\ file, such objects cannot be reused. In %D \PDF\ however, reusing is possible and sometimes even a %D necessity. Therefore, \CONTEXT\ supports reusable objects. %D %D During the \TEX\ processing run, boxes can serve the purpose %D of objects, and the \DVI\ driver module implements objects %D using packed boxes. %D %D The \PDF\ and \PDFTEX\ driver modules implement objects %D using \PDF\ forms. There is no (real) restriction on the %D number of objects there. %D %D The first application of objects in \CONTEXT\ concerned %D \METAPOST\ graphics and fill||in form fields. The first %D application can save lots of bytes, while the latter use is %D more a necessity than byte saving. %D %D \starttyping %D \setobject{class}{name}\somebox{} %D \getobject{class}{name} %D \stoptyping %D %D Here \type{\somebox} can be whatever box specification suits %D \TEX. We save the dimensions of an object, although some %D drivers will do so themselves. This means that when for %D instance using \PDFTEX\ we could save a hash entry plus some %D 20+ memory locations per object by delegating this %D housekeeping to the driver. The current approach permits %D us to keep the box characteristic too. \newif\ifinobject \def\checkobjectreferences {\startnointerference \protectlabels \ifx\usedoutputdriver\currentoutput \doutilities{objectreferences}\jobname\empty\relax\relax \else % different format (will fails on \purenumber) \fi \global\let\checkobjectreferences\relax \stopnointerference} \def\objectplaceholder{NOT YET FLUSHED}% \def\presetobject#1#2% \global added {\blabelgroup \ifcsname\r!object#1::#2\endcsname\else \global\@EA\let\csname\r!object#1::#2\endcsname\objectplaceholder \fi \elabelgroup} \def\dosetobject#1#2#3% \initializepaper this will move to \everyshipout {\initializepaper \blabelgroup \ifcsname\r!object#2::#3\endcsname \elabelgroup \expandafter\gobblefivearguments \else % tzt, overload internal referenced objects to save entries \elabelgroup \expandafter\dodosetobject \fi {#1}{#2}{#3}} \def\resetobject#1#2% {\checkobjectreferences \letbeundefined{\r!object#1::#2}} %D \macros %D {finalizeobjectbox} %D %D This one provides a hook for last minute object box processing %D we need this in \MKIV. \ifx\finalizeobjectbox\undefined \let\finalizeobjectbox\gobbleoneargument \fi %D Somehow there is a rounding error problem in either \PDFTEX\ %D or in viewers, or maybe it is conforming the specs. The next %D variable compensate for it by removing the rather tight %D clip. \def\objectoffset{1cm} % \def\dodosetobject#1#2#3% % {\bgroup % \inobjecttrue % \dowithnextbox{\dododosetobject{#1}{#2}{#3}\egroup}} \def\dodosetobject#1#2#3% {\bgroup \globalpushmacro\crossreferenceobject \objectreferenced \inobjecttrue \dowithnextbox {\globalpopmacro\crossreferenceobject \dododosetobject{#1}{#2}{#3}\egroup}} \def\dododosetobject#1#2#3% {\blabelgroup \dontshowcomposition % rather fuzzy in \setxvalue ... \hbox \scratchdimen\objectoffset \@EA\xdef\csname\r!object#2::#3\endcsname {\noexpand\dohandleobject{#2}{#3}% {\ifhbox\nextbox\hbox\else\vbox\fi}% %{\the\nextboxwd}{\the\nextboxht}{\the\nextboxdp}}% {\number\nextboxwd}{\number\nextboxht}{\number\nextboxdp}% {\number\scratchdimen}}% \expanded % freeze the dimensions since \dostartobject may use \nextbox {\dostartobject {#2}{#3}{\the\nextboxwd}{\the\nextboxht}{\the\nextboxdp}}% \ifcase#1\relax\else \ifdim\objectoffset>\zeropoint \setbox\nextbox\vbox spread 2\scratchdimen {\forgetall \offinterlineskip \vss\hbox spread 2\scratchdimen{\hss\flushnextbox\hss}\vss}% \fi \fi \flushnextbox \dostopobject \elabelgroup} \def\getobject#1#2% {\blabelgroup \let\dohandleobject\dogetobject \csname\r!object#1::#2\endcsname} % \def\dogetobject#1#2#3#4#5#6% % {\initializepaper % \forgetall % \dontshowcomposition % \setbox\scratchbox\vbox % {\doinsertobject{#1}{#2}}% % \setbox\scratchbox#3% % {\vbox to #5\scaledpoint % {\ifdim\ht\scratchbox>#5\scaledpoint % % or \ifdim\wd\scratchbox>#4\scaledpoint % \vss\hbox to #4\scaledpoint{\hss\box\scratchbox\hss}\vss % \else % \vss\box\scratchbox % \fi}}% % \wd\scratchbox#4\scaledpoint % \ht\scratchbox#5\scaledpoint % \dp\scratchbox#6\scaledpoint % \box\scratchbox % \elabelgroup} % \def\dogetobject#1#2#3#4#5#6#7% % {\initializepaper % \forgetall % \dontshowcomposition % \setbox\scratchbox\vbox % {\doinsertobject{#1}{#2}}% % \setbox\scratchbox#3% % {\vbox to #5\scaledpoint % {\ifdim\ht\scratchbox>#5\scaledpoint % % or \ifdim\wd\scratchbox>#4\scaledpoint % \vss\hbox to #4\scaledpoint{\hss\box\scratchbox\hss}\vss % \else % \vss\box\scratchbox % \fi}}% % \scratchdimen#7\scaledpoint % \setbox\nextbox\hbox % {\hskip-\scratchdimen\lower\scratchdimen\flushnextbox}% % \wd\scratchbox#4\scaledpoint % \ht\scratchbox#5\scaledpoint % \dp\scratchbox#6\scaledpoint % \box\scratchbox % \elabelgroup} \def\dogetobject#1#2#3#4#5#6#7% don't change this, should work for dvi & pdf {\initializepaper \forgetall \dontshowcomposition \setbox\scratchbox\vbox {\doinsertobject{#1}{#2}}% \setbox\scratchbox#3% {\vbox to #5\scaledpoint {\ifdim\ht\scratchbox>#5\scaledpoint \vss\hbox to #4\scaledpoint{\hss\box\scratchbox\hss}\vss \else\ifdim\wd\scratchbox>#4\scaledpoint \vss\hbox to #4\scaledpoint{\hss\box\scratchbox\hss}\vss \else %\vss\box\scratchbox \vss\hbox to #4\scaledpoint{\box\scratchbox\hss}% fix Chof \fi\fi}}% \box\scratchbox \elabelgroup} %D If needed one can ask for the dimensions of an object with: %D %D \starttyping %D \getobjectdimensions{class}{name} %D \stoptyping %D %D The results are reported in \type {\objectwidth}, \type %D {\objectheight} and \type {\objectdepth}. % \def\dogetobjectdimensions#1#2#3#4#5#6% % {\def\objectwidth {#4\s!sp}% % \def\objectheight{#5\s!sp}% % \def\objectdepth {#6\s!sp}} \def\dogetobjectdimensions#1#2#3#4#5#6#7% {\def\objectwidth {#4\s!sp}% \def\objectheight{#5\s!sp}% \def\objectdepth {#6\s!sp}% \def\objectmargin{#7\s!sp}} \def\getobjectdimensions#1#2% {\let\dohandleobject\dogetobjectdimensions \let\objectwidth \!!zeropoint \let\objectheight\!!zeropoint \let\objectdepth \!!zeropoint \labelcsname\r!object#1::#2\endcsname} %D Apart from this kind of objects, that have typeset content, %D we can have low level driver specific objects. Both types %D can have references to internal representations, hidden for %D the user. We keep track of such references by means of a %D dedicated cross reference mechanism. Normally, objects are %D defined before they are used, but forward referencing %D sometimes occurs. %D %D \starttyping %D \dosetobjectreference {class} {identifier} {reference value} {page} %D \dogetobjectreference {class} {identifier} \csname %D \stoptyping %D %D These commands are to be called by the \type{\startobject}, %D \type{\stopobject} and \type{\insertobject} specials. \def\objectreferenced{\global\chardef\crossreferenceobject\plusone} \def\driverreferenced{\global\chardef\crossreferenceobject\zerocount} \objectreferenced % no undefined test ! ! ! ! (pdftex fails on undefined objects) \def\setobjectreferences {\def\objectreference##1##2##3##4% {\ifundefined{\r!driver##1::##2}% \setxvalue{\r!driver##1::##2}{{##3}{##4}}% \else \showmessage\m!references{31}{[##1 ##2=>##3/##4]}% \fi}} \def\resetobjectreferences {\let\objectreference\gobblefourarguments} \resetobjectreferences \def\doregisterobjectreference#1#2#3% {\checkobjectreferences \blabelgroup \expanded{\writeutilitycommand{\noexpand\objectreference{#1}{#2}{#3}{\noexpand\realfolio}}}% \setxvalue{\r!driver#1::#2}{{#3}{\noexpand\realfolio}}% \elabelgroup} \def\dooverloadobjectreference#1#2#3% {\checkobjectreferences \blabelgroup \setxvalue{\r!driver#1::#2}{{#3}{\noexpand\realfolio}}% \elabelgroup} \def\dosetobjectreference {\ifcase\crossreferenceobject \objectreferenced \expandafter\dooverloadobjectreference \else \expandafter\doregisterobjectreference \fi} \def\dosetdriverreference {\driverreferenced\dosetobjectreference} \def\defaultobjectreference#1#2{0} % driver dependent \def\defaultobjectpage #1#2{\realfolio} \def\dogetobjectreference {\dodogetobjectreference\firstoftwoarguments\defaultobjectreference} \def\dogetobjectreferencepage{\dodogetobjectreference\secondoftwoarguments\defaultobjectpage} \def\dodogetobjectreference#1#2#3#4#5% {\checkobjectreferences \blabelgroup \ifundefined{\r!driver#3::#4}% \showmessage\m!references{30}{[#3 #4=>#3/#4]}% \xdef#5{#2{#3}{#4}}% \else \xdef#5{\@EAEAEA#1\csname\r!driver#3::#4\endcsname}% \fi \elabelgroup} \def\setobject {\driverreferenced\dosetobject1} \def\settightobject{\driverreferenced\dosetobject0} %D \macros %D {doifobjectfoundelse,doifobjectreferencefoundelse} %D %D To prevent redundant definition of objects, one can use %D the next tests: %D %D \starttyping %D \doifobjectfoundelse{class}{object}{do then}{do else} %D \doifobjectreferencefoundelse{class}{object}{do then}{do else} %D \stoptyping \def\doifobjectfoundelse#1#2% {\blabelgroup \ifcsname\r!object#1::#2\endcsname \elabelgroup \expandafter\firstoftwoarguments \else \elabelgroup \expandafter\secondoftwoarguments \fi} \def\doifobjectreferencefoundelse#1#2% {\checkobjectreferences \blabelgroup \ifcsname\r!driver#1::#2\endcsname \elabelgroup \expandafter\firstoftwoarguments \else \elabelgroup \expandafter\secondoftwoarguments \fi} %D \macros %D {doifobjectssupportedelse} %D %D Starting with reuse of graphics, we will implement object %D reuse when possible. To enable mechanisms to determine %D what method to use, we provide: %D %D \starttyping %D \doifobjectssupportedelse{true action}{false action} %D \stoptyping %D %D As we can see, currently objects depend on the special %D driver. \newif\ifobjectssupported \objectssupportedtrue \def\doifobjectssupportedelse {\ifobjectssupported \@EA\doifspecialavailableelse\@EA\doinsertobject \else \@EA\secondoftwoarguments \fi} %D There is a conceptual problem here. Objects are not possible %D in \DVI, unless faked like in \type {spec-dvi}. This means %D that we must be careful in loading special drivers that do %D support objects while we still want to be able to use the %D \DVI\ output. \protect \endinput