diff options
Diffstat (limited to 'tex/context/base/mkiv/anch-pos.mkiv')
-rw-r--r-- | tex/context/base/mkiv/anch-pos.mkiv | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/anch-pos.mkiv b/tex/context/base/mkiv/anch-pos.mkiv new file mode 100644 index 000000000..5d9c2fd34 --- /dev/null +++ b/tex/context/base/mkiv/anch-pos.mkiv @@ -0,0 +1,459 @@ +%D \module +%D [ file=anch-pos, % was core-pos +%D version=1999.08.01, +%D title=\CONTEXT\ Anchoring Macros, +%D subtitle=Positioning 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 mreadme.pdf for +%C details. + +\writestatus{loading}{ConTeXt Anchoring Macros / Positioning} + +%D In \MKIV\ there was already a different housekeeping model for positions quite +%D early, but starting in 2012 more dramatic changes started to happen, especially +%D in relation to background graphics. It will probably take some time to settle. + +\registerctxluafile{anch-pos}{1.001} + +\unprotect + +%D The first application of positional information was embedded graphics. Since we +%D are interacting with text, it made sense to take the current line height and +%D depth into account too. This is why we have position macros for simple positions +%D and one boxes. +%D +%D \starttyping +%D \dosetposition {identifier} +%D \dosetpositionwhd {identifier} {width} {height} {depth} +%D \dosetpositionplus {identifier} {width} {height} {depth} {list} +%D \stoptyping + +\def\dosaveposition #1#2#3#4{\clf_dosaveposition {#1}#2 #3 #4\relax} +\def\dosavepositionwhd #1#2#3#4#5#6#7{\clf_dosavepositionwhd {#1}#2 #3 #4 #5 #6 #7\relax} +\def\dosavepositionplus#1#2#3#4#5#6#7#8{\clf_dosavepositionplus{#1}#2 #3 #4 #5 #6 #7{#8}} + +\def\dosetposition #1{\clf_dosetposition {#1}} % {} expands +\def\dosetpositionwhd #1#2#3#4{\clf_dosetpositionwhd {#1}#2 #3 #4\relax} +\def\dosetpositionplus#1#2#3#4#5{\clf_dosetpositionplus {#1}#2 #3 #4{#5}} +\def\dosetpositionbox #1#2{\clf_dosetpositionbox {#1}#2\relax} +\def\dosetpositionstrut #1{\clf_dosetpositionstrut{#1}} + +\newbox\b_anch_position +\newif \ifpositioning % sort of public + +%D Sometimes we want to trick the position handler a bit: + +\def\replacepospxywhd#1#2#3#4#5#6#7% when used we can better make a helper + {\clf_replacepospxywhd{#1}#2 #3 #4 #5 #6 #7\relax} + +%D \macros +%D {MPp, MPx, MPy, MPw, MPh, MPd, MPxy, MPll, MPlr, MPur, MPul, MPpos, MPanchor} +%D +%D Access to the positional information is provided by macros with short names +%S that are clearly meant for \METAPOST\ but nowadays also used for other purposes. + +\def\MPp #1{\clf_MPp {#1}} +\def\MPr #1{\clf_MPr {#1}} +\def\MPc #1{\clf_MPc {#1}} +\def\MPn #1{\clf_MPn {#1}} +\def\MPx #1{\clf_MPx {#1}} +\def\MPy #1{\clf_MPy {#1}} +\def\MPw #1{\clf_MPw {#1}} +\def\MPh #1{\clf_MPh {#1}} +\def\MPd #1{\clf_MPd {#1}} +\def\MPxy #1{\clf_MPxy {#1}} +\def\MPll #1{\clf_MPll {#1}} +\def\MPlr #1{\clf_MPlr {#1}} +\def\MPur #1{\clf_MPur {#1}} +\def\MPul #1{\clf_MPul {#1}} +\def\MPpos #1{\clf_MPpos {#1}} +\def\MPls #1{\clf_MPls {#1}} +\def\MPrs #1{\clf_MPrs {#1}} +\def\MPpardata#1{\clf_MPpardata{#1}} +\def\MPxywhd #1{\clf_MPxywhd {#1}} +\def\MPposset #1{\clf_MPposset {#1}} + +\let\MPpage \MPp +\let\MPregion \MPr +\let\MPcolumn \MPc +\let\MPparagraph\MPn + +\let\MPanchor \MPpos % overloaded locally when needed +\let\MPleftskip \MPls % compatible feature +\let\MPrightkip \MPrs % compatible feature + +%D \macros +%D {MPplus, MPrest, MPv, MPvv} +%D +%D Since we will probably keep on extending, we provide a general extension +%D macro. The plus alternative takes an extra argument, denoting what additional +%D parameter to pick up. So, the third extra is fetched with, +%D +%D \starttyping +%D \MPplus{identifier}{3}{default} +%D \stoptyping +%D +%D All extras (comma separated) are fetched with: +%D +%D \starttyping +%D \MPrest{identifier} +%D \stoptyping +%D +%D The extra parameters are not treated. + +\def\MPplus#1#2#3{\clf_MPplus{#1}#2{#3}} \let\MPv \MPplus +\def\MPrest #1#2{\clf_MPrest{#1}{#2}} \let\MPvv\MPrest + +%D There are two low level positioning macros. Both store the position as well +%D as execute an action associated with that position. + +\let\dopositionaction\gobbleoneargument % implemented later + +\def\anch_positions_initialize + {\ifpositioning \else + \global\positioningtrue + \fi} + +\unexpanded\def\setpositiononly + {\iftrialtypesetting + \expandafter\gobbleoneargument + \else + \expandafter\anch_positions_set_only_indeed + \fi} + +\def\anch_positions_set_only_indeed#1% + {\anch_positions_initialize + \edef\currentposition{#1}% + \dosetposition\currentposition} + +\unexpanded\def\setposition + {\iftrialtypesetting + \expandafter\gobbleoneargument + \else + \expandafter\anch_positions_set_indeed + \fi} + +\def\anch_positions_set_indeed#1% + {\anch_positions_initialize + \edef\currentposition{#1}% + \dosetposition\currentposition + \anch_positions_trace_left + \dopositionaction\currentposition} + +\unexpanded\def\setpositiondata + {\iftrialtypesetting + \expandafter\gobblefourarguments + \else + \expandafter\anch_positions_set_data_indeed + \fi} + +\def\anch_positions_set_data_indeed#1#2#3#4% + {\anch_positions_initialize + \hbox + {\edef\currentposition{#1}% + \dosetpositionwhd\currentposition{#2}{#3}{#4}% already \the\dimexpr + \anch_positions_trace_left + \dopositionaction\currentposition + \hss}} + +\unexpanded\def\setpositionbox + {\iftrialtypesetting + \expandafter\anch_positions_set_box_nop + \else + \expandafter\anch_positions_set_box_yes + \fi} + +\def\anch_positions_set_box_nop#1% + {\dowithnextboxcs\flushnextbox} + +\def\anch_positions_set_box_yes#1% + {\dowithnextbox{\anch_positions_set_box_finish{#1}}} + +\def\anch_positions_set_box_finish#1% + {\anch_positions_initialize + \hbox to \wd\nextbox + {\edef\currentposition{#1}% + \dosetpositionbox\currentposition\nextbox + \anch_positions_trace_left + \setbox\b_anch_position\box\nextbox + \dopositionaction\currentposition + \box\b_anch_position + \hss}} + +\unexpanded\def\setpositionstrut + {\iftrialtypesetting + \expandafter\anch_positions_set_strut_nop + \else + \expandafter\anch_positions_set_strut_yes + \fi} + +\def\anch_positions_set_strut_nop#1% + {\strut} + +\def\anch_positions_set_strut_yes#1% + {\anch_positions_initialize + \hbox to \zeropoint + {\edef\currentposition{#1}% + \dosetpositionstrut\currentposition + \anch_positions_trace_left + \dopositionaction\currentposition + \strut + \hss}} + +\unexpanded\def\setpositiondataplus + {\iftrialtypesetting + \expandafter\gobblefivearguments + \else + \expandafter\anch_positions_set_plus_indeed + \fi} + +\def\anch_positions_set_plus_indeed#1#2#3#4#5% + {\anch_positions_initialize + \hbox % just package + {\edef\currentposition{#1}% + \dosetpositionplus\currentposition{#2}{#3}{#4}{#5}% already \the\dimexpr + \anch_positions_trace_right + \dopositionaction\currentposition + \hss}} + +\unexpanded\def\setpositionplus + {\iftrialtypesetting + \expandafter\anch_positions_set_plus_nop + \else + \expandafter\anch_positions_set_plus_yes + \fi} + +\def\anch_positions_set_plus_nop#1#2% + {\dowithnextboxcs\flushnextbox} + +\def\anch_positions_set_plus_yes#1#2% + {\dowithnextbox{\anch_positions_set_plus_yes_finish{#1}{#2}}} + +\def\anch_positions_set_plus_yes_finish#1#2% + {\anch_positions_initialize + \hbox to \nextboxwd + {\edef\currentposition{#1}% + \dosetpositionplus\currentposition{\wd\nextbox}{\ht\nextbox}{\dp\nextbox}{#2}% + \anch_positions_trace_right + \setbox\b_anch_position\flushnextbox + \dopositionaction\currentposition + \box\b_anch_position + \hss}} + +\let\currentposition\s!unknown + +%D A few special ones .. will be cleaned up + +\def\pageanchor {page:\the\realpageno} % for the moment only one pagesize +\def\textanchor {text:\the\realpageno} +\def\regionanchor{region:0} + +\newcount\c_anch_column % will be delegated to lua +\newcount\c_anch_text % will be delegated to lua + +% beware we need to pass \somethingexpanded or { } + +\unexpanded\def\anch_mark_column_box#1% + {\global\advance\c_anch_column\plusone + \clf_markregionboxtagged#1{columnarea:\the\c_anch_column}} % extra height + +\unexpanded\def\anch_mark_region_box + {\iftrialtypesetting + \singleexpandafter\gobbleoneargument + \else\ifpositioning + \doubleexpandafter\anch_mark_region_box_indeed + \else + \doubleexpandafter\gobbleoneargument + \fi\fi} + +\unexpanded\def\anch_mark_region_box_indeed#1% + {\clf_markregionbox#1\relax} + +\unexpanded\def\anch_mark_flow_box#1% will be extended / renamed + {\hbox\bgroup + \global\advance\c_anch_text\plusone + \clf_markregionboxtagged#1{textarea:\the\c_anch_text}% + \box#1% + \egroup} + +\unexpanded\def\anch_mark_tagged_box#1#2% + {\clf_markregionboxtagged#1{#2}} + +\unexpanded\def\anch_mark_flow_only#1% will be extended / renamed + {\global\advance\c_anch_text\plusone + \clf_markregionboxcorrected#1{textarea:\the\c_anch_text}} + +\unexpanded\def\anch_make_page_box#1% maybe like text + {\clf_setregionboxtagged#1{page:\the\realpageno}} + +\unexpanded\def\anch_mark_text_box#1% + {\clf_markregionboxtagged#1{text:\the\realpageno}} % needs an hbox + +%D We can copy a position with: +%D +%D \starttyping +%D \copyposition {to} {from} +%D \stoptyping +%D +%D Again, this is a global operation. + +\unexpanded\def\copyposition#1#2% + {\clf_copyposition{#1}{#2}} + +%D The fact that handling positions is a two pass operation, is one of the +%D reasons why we need to be able to test for existence, using: +%D +%D \starttyping +%D \doifpositionelse {identifier} {found action} {not found action} +%D \stoptyping + +\unexpanded\def\doifposition #1{\clf_doifposition {#1}} +\unexpanded\def\doifelseposition #1{\clf_doifelseposition {#1}} +\unexpanded\def\doifelsepositiononpage#1#2{\clf_doifelsepositiononpage{#1}#2\relax} + +\let\doifpositionelse \doifelseposition +\let\doifpositiononpageelse\doifelsepositiononpage + +%D \macros +%D {xypos} +%D +%D We have several macros available to save positions. Later we will see +%D applications. +%D +%D \starttabulate[|l|l||] +%D \NC \type {\xypos} \NC \NC simple position with no dimensions \NC \NR +%D \NC \type {\hpos} \NC \NC position and characteristics of a \type {\hbox} \NC \NR +%D \NC \type {\vpos} \NC \NC position and characteristics of a \type {\vbox} \NC \NR +%D \NC \type {\bpos} \NC b: \NC begin point in a line \NC \NR +%D \NC \type {\epos} \NC e: \NC end point in a line \NC \NR +%D \stoptabulate +%D +%D Each macro takes an identifier as argument, and the \type {\hpos} and +%D \type {\vpos} also expect box content. + +\let\xypos\setpositiononly + +\unexpanded\def\hpos#1{\dontleavehmode\setpositionbox{#1}\hbox} +\unexpanded\def\vpos#1{\setpositionbox{#1}\vbox} +\unexpanded\def\bpos#1{\dontleavehmode \setpositionstrut{b:#1}\ignorespaces} +\unexpanded\def\epos#1{\removeunwantedspaces\setpositionstrut{e:#1}} + +%D When we want to calculate more complex backgrounds, we need to know what the +%D current indentation scheme is. At the cost of many positions and memory, we +%D can keep track of them. This mechanism is activated automatically based on +%D information collected in the previous pass. + +\newtoks \t_anch_positions_tracers +\newcount\c_anch_positions_paragraph + +\unexpanded\def\tracepositions + {\the\t_anch_positions_tracers} + +\unexpanded\def\enableparpositions % global + {\global\let\registerparoptions\doregisterparoptions + \global\positioningtrue} + +\let\disableparpositions\relax + +\let\registerparoptions\relax + +\unexpanded\def\doregisterparoptions + {\iftrialtypesetting \else + \ifinpagebody \else \ifmmode \else \ifinformula \else + \anch_positions_register_par_options + \fi \fi \fi + \fi} + +\def\anch_positions_register_par_options_normal + {\dontleavehmode\clf_parpos} + +\def\anch_positions_register_par_options_traced + {\anch_positions_register_par_options_normal + \smashedhbox to \zeropoint + {\hss + \startcolor[blue]% + \llap{\infofont\number\c_anch_positions_paragraph}% + \vrule + \s!width 4\onepoint + \s!height2\onepoint + \s!depth 2\onepoint + \stopcolor + \hss}} + +\let\anch_positions_register_par_options\anch_positions_register_par_options_normal + +\appendtoks + \let\anch_positions_register_par_options\anch_positions_register_par_options_traced +\to \t_anch_positions_tracers + +\unexpanded\def\anch_positions_trace#1#2#3% + {\smashedhbox + {#1{\infofont#2#3}% + \kern-\onepoint + \vrule\s!width2\onepoint\s!height\halfapoint\s!depth\halfapoint}} + +\unexpanded\def\anch_positions_trace_left_indeed + {\anch_positions_trace\llap\darkmagenta{\currentposition>}} + +\unexpanded\def\anch_positions_trace_right_indeed + {\anch_positions_trace\rlap\darkcyan{<\currentposition}} + +\let\anch_positions_trace_left \relax +\let\anch_positions_trace_right\relax + +\appendtoks + \let\anch_positions_trace_left \anch_positions_trace_left_indeed + \let\anch_positions_trace_right \anch_positions_trace_right_indeed +\to \t_anch_positions_tracers + +% \appendtoks \registerparoptions \to \everypar + +%D \macros +%D {doifoverlappingelse} +%D +%D A first application of positional information, is to determine if two +%D boxes do overlap: +%D +%D \starttyping +%D \doifoverlappingelse{point a}{point b} +%D {action when overlapping} +%D {action when not overlapping} +%D \stoptyping + +\unexpanded\def\doifelseoverlapping#1#2{\clf_doifelseoverlapping{#1}{#2}} + +\let\doifoverlappingelse\doifelseoverlapping + +%D \macros +%D {doifpositionsonsamepageelse, +%D doifpositionsonthispageelse} +%D +%D Instead of letting the user handle fuzzy expansion, we provide a simple test on +%D positions being on the same page. +%D +%D \starttyping +%D \doifpositionsonsamepageelse{point a}{point b} +%D {action when on same page} +%D {action when not on same page} +%D \doifpositionsonthispageelse{point a}{point b} +%D {action when on this page} +%D {action when not on this page} +%D \stoptyping + +\unexpanded\def\doifelsepositionsonsamepage#1{\clf_doifelsepositionsonsamepage{#1}} +\unexpanded\def\doifelsepositionsonthispage#1{\clf_doifelsepositionsonthispage{#1}} + +\let\doifpositionsonsamepageelse\doifelsepositionsonsamepage +\let\doifpositionsonthispageelse\doifelsepositionsonthispage + +%D Moved here: + +\unexpanded\def\doifelsepositionsused{\clf_doifelsepositionsused} + +\let\doifpositionsusedelse\doifelsepositionsused + +\protect \endinput |