%D \module %D [ file=anch-bck, % moved from anch-pgr (1999.08.01) %D version=2011.12.19, %D title=\CONTEXT\ Anchoring Macros, %D subtitle=Backgrounds, %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 / Backgrounds} %D This module is quite okay but at some point I might add methods %D that use attributes although not too much is to be expected, %D apart from better anchoring. In fact better anchoring can be %D done independent of that. \unprotect % This might be overloaded later on: % \defineoverlay[\v!text-2][\positionoverlay{\v!text-2}] % \defineoverlay[\v!text-1][\positionoverlay{\v!text-1}] % \defineoverlay[\v!text+1][\positionoverlay{\v!text+1}] % \defineoverlay[\v!text+2][\positionoverlay{\v!text+2}] % Paragraph positions: \newcount\c_anch_backgrounds_text_n \def\v_anch_backgrounds_text_current {tbg:0} \def\v_anch_backgrounds_anchor_current_b{b:\v_anch_backgrounds_text_current} \def\v_anch_backgrounds_anchor_current_e{e:\v_anch_backgrounds_text_current} \def\anch_backgrounds_text_initialize_next {\global\advance\c_anch_backgrounds_text_n\plusone \edef\v_anch_backgrounds_text_current{tbg:\number\c_anch_backgrounds_text_n}} % The first position can be used in the middle of a paragraph in which case we're % too late with initializing par positions. Therefore we check if positions are % used at all. % % tricky: we need to catch newly set! otherwise an old run can have positions \unexpanded\def\anch_backgrounds_text_initialize {\doifelsepositionsused\enableparpositions\donothing \glet\anch_backgrounds_text_initialize\relax} \appendtoks \anch_backgrounds_text_initialize \to \everystarttext %D Some MP \newcount\MPparcounter \def\MPself {\MPvar{self}} \def\MPbself {b:\MPvar{self}} \def\MPeself {e:\MPvar{self}} \def\MPparanchor{p:\number\MPparcounter} % \carryoverpar is needed for left/right floats % \definetextbackground[more][state=start,backgroundcolor=red] % location=paragraph % \definetextbackground[test][state=start,backgroundcolor=green] % % \page \placefigure[left]{}{} % % \starttextbackground[test] % \readfile{ward}{}{} % \starttextbackground[more] % \readfile{ward}{}{} % \stoptextbackground % \readfile{ward}{}{} % \stoptextbackground % % \page \placefigure[right]{}{} % % \starttextbackground[test] % \readfile{ward}{}{} % \starttextbackground[more] % \readfile{ward}{}{} % \stoptextbackground % \readfile{ward}{}{} % \stoptextbackground \newcount\c_anch_backgrounds_text_level \installcorenamespace{textbackground} \installcorenamespace{textbackgroundlevel} \installcommandhandler \??textbackground {textbackground} \??textbackground \appendtoks \setuevalue{\currenttextbackground}{\groupedcommand{\starttextbackground[\currenttextbackground]}{\stoptextbackground}}% \setuevalue{\e!start\currenttextbackground}{\starttextbackground[\currenttextbackground]}% \setuevalue{\e!stop \currenttextbackground}{\stoptextbackground}% \to \everydefinetextbackground \newconstant \c_anch_backgrounds_pos_state \newconditional\c_anch_backgrounds_pos_no_shape \def\anch_backgrounds_bpos {\ifconditional\c_anch_backgrounds_pos_no_shape \bposkind\v_anch_backgrounds_text_current\plusthree \else \bposkind\v_anch_backgrounds_text_current\c_anch_backgrounds_pos_state \fi} \def\anch_backgrounds_epos {\ifconditional\c_anch_backgrounds_pos_no_shape \eposkind\v_anch_backgrounds_text_current\plusthree \else \eposkind\v_anch_backgrounds_text_current\c_anch_backgrounds_pos_state \fi} \unexpanded\def\starttextbackground {\begingroup \advance\c_anch_backgrounds_text_level\plusone \dodoubleempty\anch_backgrounds_text_start} \def\anch_backgrounds_text_start[#tag][#settings]% {%\checkpositionoverlays \def\currenttextbackground{#tag}% \anch_backgrounds_text_initialize_next \ifsecondargument \setupcurrenttextbackground[#settings]% \fi \doifelse{\textbackgroundparameter\c!state}\v!start \anch_backgrounds_text_preset_yes \anch_backgrounds_text_preset_nop \anch_backgrounds_text_start_indeed} % ugly hack to register usage \newcount \c_anch_backgrounds_text_count \newcount \c_anch_backgrounds_text_check \newconstant\c_anch_backgrounds_text_state \unexpanded\def\starttextbackground {\begingroup \global\advance\c_anch_backgrounds_text_count\plusone \advance\c_anch_backgrounds_text_level\plusone \dodoubleempty\anch_backgrounds_text_start} \def\anch_backgrounds_text_level_start {\c_anch_backgrounds_text_check\c_anch_backgrounds_text_count} \def\anch_backgrounds_text_level_stop {\c_anch_backgrounds_text_state \ifnum\c_anch_backgrounds_text_count>\c_anch_backgrounds_text_check \plusone \else \zerocount \fi} % todo \backgroundvariable\c!variant % criterium determines when we fall back on text % always is always forcing paragraphs \let\anch_backgrounds_text_start_indeed\relax \let\anch_backgrounds_text_stop_indeed \relax \setvalue{\??textbackgroundlevel\v!text}% {\let\anch_backgrounds_text_start_indeed\anch_backgrounds_text_start_txt \let\anch_backgrounds_text_stop_indeed \anch_backgrounds_text_stop_txt} \setvalue{\??textbackgroundlevel\v!paragraph}% {\ifnum\c_anch_backgrounds_text_level>\textbackgroundparameter\c!criterium\relax \let\anch_backgrounds_text_start_indeed\anch_backgrounds_text_start_txt \let\anch_backgrounds_text_stop_indeed \anch_backgrounds_text_stop_txt \else \let\anch_backgrounds_text_start_indeed\anch_backgrounds_text_start_par \let\anch_backgrounds_text_stop_indeed \anch_backgrounds_text_stop_par \fi} \setvalue{\??textbackgroundlevel\v!always}% {\let\anch_backgrounds_text_start_indeed\anch_backgrounds_text_start_par \let\anch_backgrounds_text_stop_indeed \anch_backgrounds_text_stop_par} \setvalue{\??textbackgroundlevel\v!none}% {\anch_backgrounds_text_preset_nop} \def\anch_backgrounds_text_preset_nop {\let\anch_backgrounds_text_start_indeed\relax \let\anch_backgrounds_text_stop_indeed \relax} \def\anch_backgrounds_text_preset_yes {\anch_backgrounds_text_preset_nop \csname\??textbackgroundlevel\textbackgroundparameter\c!location\endcsname \edef\p_anch_backgrounds_text_frame {\textbackgroundparameter\c!frame}% \edef\p_anch_backgrounds_text_corner {\textbackgroundparameter\c!corner}% \edef\p_anch_backgrounds_text_background{\textbackgroundparameter\c!background}% \ifx\p_anch_backgrounds_text_frame\v!on \ifx\p_anch_backgrounds_text_corner\v!round \let\p_anch_backgrounds_text_frame\!!plustwo \else \let\p_anch_backgrounds_text_frame\!!plusone \fi \else \let\p_anch_backgrounds_text_frame\!!zerocount \fi \ifx\p_anch_backgrounds_text_background\v!color \let\p_anch_backgrounds_text_background\!!plusone \else \let\p_anch_backgrounds_text_background\!!zerocount \fi \startpositionoverlay{\textbackgroundoverlay{\textbackgroundparameter\c!level}}% \anch_backgrounds_text_meta_graphic % gets expanded directly \stoppositionoverlay} \def\anch_backgrounds_text_meta_graphic {\normalexpanded {\setMPpositiongraphicrange % needs to be optimized {\v_anch_backgrounds_anchor_current_b}% {\v_anch_backgrounds_anchor_current_e}% {\textbackgroundparameter\c!method}% {self=\v_anch_backgrounds_text_current, mp=\textbackgroundparameter\c!mp, gridtype=\textbackgroundparameter\c!alternative, filltype=\p_anch_backgrounds_text_background, linetype=\p_anch_backgrounds_text_frame, dashtype=\textbackgroundparameter\c!dash, gridcolor=\textbackgroundparameter\c!framecolor, linecolor=\textbackgroundparameter\c!framecolor, lineoffset=\textbackgroundparameter\c!frameoffset, fillcolor=\textbackgroundparameter\c!backgroundcolor, filloffset=\textbackgroundparameter\c!backgroundoffset, gridwidth=\textbackgroundparameter\c!rulethickness, gridshift=\textbackgroundparameter\c!voffset, linewidth=\textbackgroundparameter\c!rulethickness, lineradius=\textbackgroundparameter\c!radius}}} \unexpanded\def\stoptextbackground {\anch_backgrounds_text_stop_indeed \carryoverpar\endgroup} % why doesn't this work ? \unexpanded\def\starttextbackgroundmanual {\begingroup \c_anch_backgrounds_pos_state\plusone \usetextbackgroundstyleandcolor\c!style\c!color \anch_backgrounds_bpos} \unexpanded\def\stoptextbackgroundmanual {\anch_backgrounds_epos \carryoverpar\endgroup} \def\anch_backgrounds_text_start_txt {\ifvmode \dontleavehmode \fi \begingroup \c_anch_backgrounds_pos_state\plusone \usetextbackgroundstyleandcolor\c!style\c!color \anch_backgrounds_bpos} \def\anch_backgrounds_text_stop_txt {\anch_backgrounds_epos \carryoverpar\endgroup} \newskip\textbackgroundskip % maybe we should have a resetter for such compensation struts \def\anch_backgrounds_reset_attributes {\scratchcounter\attribute\snapmethodattribute \resetallattributes % \attribute\linenumberattribute \attributeunsetvalue \attribute\snapmethodattribute\scratchcounter} \def\anch_backgrounds_text_start_par % beware .. background shapes {\endgraf % new \textbackgroundparameter\c!before \begingroup \c_anch_backgrounds_pos_state\plustwo \begingroup \anch_backgrounds_reset_attributes \noindent \ifgridsnapping \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!topoffset}% \ifdim\textbackgroundskip>\zeropoint \struttedbox % not always ok (e.g. setups) {\hpack{\raise\textbackgroundskip\hpack{\anch_backgrounds_bpos}}}% \else \anch_backgrounds_bpos \fi \else \anch_backgrounds_bpos \fi \endgraf % we need a vertical nobreak - 29/06/2004 \endgroup \nobreak \vskip-\lineheight \nobreak \ifgridsnapping \else \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!topoffset}% \ifdim\textbackgroundskip>\zeropoint \kern\textbackgroundskip\nobreak \fi \fi \dosetleftskipadaption{\textbackgroundparameter\c!leftoffset}% \advance\leftskip\leftskipadaption \dosetleftskipadaption{\textbackgroundparameter\c!rightoffset}% \advance\rightskip\leftskipadaption % new \dosetraggedcommand{\textbackgroundparameter\c!align}% \raggedcommand % \usetextbackgroundstyleandcolor\c!style\c!color \nowhitespace \seteffectivehsize \doinhibitblank % \blank[\v!disable]% new \par} \def\anch_backgrounds_text_stop_par {\par \removelastskip % new \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!bottomoffset}% \ifdim\lastskip>\zeropoint \advance\textbackgroundskip-\lastskip \fi \ifgridsnapping \else \ifdim\textbackgroundskip>\zeropoint \kern\textbackgroundskip\nobreak \fi \fi \nobreak \vskip-\dimexpr\lineheight+\parskip\relax % problem: we loose the hangindent \nobreak \endgroup \begingroup \forgeteverypar % NOT REALLY NEEDED, SAVES HASH/MEM \anch_backgrounds_reset_attributes \nobreak \noindent \strut \hfill \kern\zeropoint % so far \spac_helpers_assign_skip\textbackgroundskip{\textbackgroundparameter\c!bottomoffset}% \ifgridsnapping % experimental, pascal (todo: topoffset in same way) \ifdim\textbackgroundskip>\zeropoint \struttedbox % not always ok (e.g. setups) {\hpack{\lower\textbackgroundskip\hpack{\anch_backgrounds_epos}}}% \else \anch_backgrounds_epos \fi \else \anch_backgrounds_epos \fi \endgraf \carryoverpar\endgroup \endgraf % new \textbackgroundparameter\c!after} \unexpanded\def\checkpositionoverlays % overloads \relax in anch-pgr {\ifproductionrun \enabletextarearegistration \enablehiddenbackground \glet\checkpositionoverlays\relax \fi} % shape handling \definesystemattribute[textbackground][public] % \def\page_prepare_backgrounds#1% % {\clf_collectbackgrounds\realpageno#1\relax} \def\anch_backgrounds_bpos {\ifconditional\c_anch_backgrounds_pos_no_shape \attribute\textbackgroundattribute\attributeunsetvalue \bposkind\v_anch_backgrounds_text_current\plusthree \else\ifnum\c_anch_backgrounds_pos_state=\plusone \bposkind\v_anch_backgrounds_text_current\c_anch_backgrounds_pos_state \clf_registerbackground{\v_anch_backgrounds_text_current}% \else \bposkind\v_anch_backgrounds_text_current\c_anch_backgrounds_pos_state \attribute\textbackgroundattribute\attributeunsetvalue \fi\fi} % plugs into other code \def\strc_floats_wrap_free_region {\global\setbox\floatbox\hpack % we always need to wrap {\ifconditional\c_strc_floats_trace_free \strc_floats_show_free_region \fi \box\floatbox}} \startuseMPgraphic{floatfree} draw_free_region( \the\wd\floatbox, \the\ht\floatbox, \the\dp\floatbox, \the\d_free_offset_left, \the\d_free_offset_right, \the\d_free_offset_top, \the\d_free_offset_bottom ) ; \stopuseMPgraphic \def\strc_floats_show_free_region {\lower\dp\floatbox\hpack to \zeropoint {\useMPgraphic{floatfree}}} \newconditional\c_strc_floats_mark_as_free \newconditional\c_strc_floats_trace_free \newconstant \c_free_offset_kind \newdimen \d_free_offset_left \newdimen \d_free_offset_right \newdimen \d_free_offset_top \newdimen \d_free_offset_bottom \installtextracker{floats.freeregion} {\settrue \c_strc_floats_trace_free} {\setfalse\c_strc_floats_trace_free} \def\strc_floats_mark_as_free#1#2#3#4#5% {\c_free_offset_kind #1% \d_free_offset_left #2% \d_free_offset_right #3% \d_free_offset_top #4% \d_free_offset_bottom#5% \strc_floats_wrap_free_region \anch_mark_tagged_box_free \floatbox \c_free_offset_kind \d_free_offset_left \d_free_offset_right \d_free_offset_top \d_free_offset_bottom} \ifx\strc_floats_mark_pag_as_free\relax \else \writestatus{error}{wrong place for pag_as_free}\wait \fi \ifx\strc_floats_mark_par_as_free\relax \else \writestatus{error}{wrong place for par_as_free}\wait \fi \def\strc_floats_mark_pag_as_free {\ifpositioning \ifconditional\c_strc_floats_mark_as_free \strc_floats_mark_as_free \plusone \zeropoint \zeropoint \d_strc_floats_top \d_strc_floats_bottom \fi \fi} \def\strc_floats_mark_par_as_free {\ifpositioning \ifconditional\c_strc_floats_mark_as_free \ifcase\c_page_sides_float_type \or % backspace \strc_floats_mark_as_free \plustwo \zeropoint \d_page_sides_rightoffset \d_page_sides_topskip \d_page_sides_bottomskip \or % leftedge \strc_floats_mark_as_free \plustwo \zeropoint \d_page_sides_rightoffset \d_page_sides_topskip \d_page_sides_bottomskip \or % leftmargin \strc_floats_mark_as_free \plustwo \zeropoint \d_page_sides_rightoffset \d_page_sides_topskip \d_page_sides_bottomskip \or % leftside \strc_floats_mark_as_free \plustwo \d_page_sides_leftskip % maybe too \d_page_sides_margin \d_page_sides_topskip \d_page_sides_bottomskip \or % rightside \strc_floats_mark_as_free \plusthree \d_page_sides_margin \d_page_sides_rightskip % maybe too \d_page_sides_topskip \d_page_sides_bottomskip \or % rightmargin \strc_floats_mark_as_free \plusthree \d_page_sides_leftoffset \zeropoint \d_page_sides_topskip \d_page_sides_bottomskip \or % rightedge \strc_floats_mark_as_free \plusthree \d_page_sides_leftoffset \zeropoint \d_page_sides_topskip \d_page_sides_bottomskip \or % cutspace \strc_floats_mark_as_free \plusthree \d_page_sides_leftoffset \zeropoint \d_page_sides_topskip \d_page_sides_bottomskip \fi \fi \fi} % so far \setuptextbackground [\c!mp=mpos:region:draw, \c!method=mpos:region, \c!state=\v!start, \c!location=\v!text, \c!leftoffset=\!!zeropoint, % 1em, \c!rightoffset=\textbackgroundparameter\c!leftoffset, \c!topoffset=\!!zeropoint, % \v!medium, \c!bottomoffset=\textbackgroundparameter\c!topoffset, \c!criterium=\plusone, \c!level=-1, \c!alternative=0, \c!align=, \c!dash=0, % to be internationalized \c!background=\v!color, \c!backgroundcolor=lightgray, \c!backgroundoffset=\!!zeropoint, \c!corner=\v!rectangular, \c!radius=.5\bodyfontsize, \c!voffset=\!!zeropoint, \c!frame=\v!on, \c!framecolor=blue, \c!frameoffset=\!!zeropoint, \c!rulethickness=\linewidth] %D The \METAPOST\ connection: % gridtype = 1 => baseline % gridtype = 2 => betweenline \setupMPvariables [mpos:region] [mp=mpos:region:unset, gridtype=0, linetype=1, filltype=1, dashtype=0, % 1 = dashed, 2 = dashed with background gridcolor=red, linecolor=blue, fillcolor=lightgray, filloffset=\!!zeropoint, linewidth=\linewidth, gridwidth=\linewidth, gridshift=\!!zeropoint, lineradius=.5\bodyfontsize, lineoffset=\!!zeropoint, dashtype=1] \startuseMPgraphic{mpos:region:setup} boxgridtype := \MPvar{gridtype} ; boxlinetype := \MPvar{linetype} ; boxfilltype := \MPvar{filltype} ; boxdashtype := \MPvar{dashtype} ; boxfilloffset := \MPvar{filloffset} ; boxlinewidth := \MPvar{linewidth} ; boxgridwidth := \MPvar{gridwidth} ; boxgridshift := \MPvar{gridshift} ; boxlineradius := \MPvar{lineradius} ; boxlineoffset := \MPvar{lineoffset} ; % def boxgridcolor = \MPvar{gridcolor} enddef ; def boxlinecolor = \MPvar{linecolor} enddef ; def boxfillcolor = \MPvar{fillcolor} enddef ; % def boxgridoptions = withcolor boxgridcolor enddef ; def boxlineoptions = withcolor boxlinecolor enddef ; def boxfilloptions = withcolor boxfillcolor enddef ; \stopuseMPgraphic \startuseMPgraphic{mpos:region:extra} % user stuff \stopuseMPgraphic \startuseMPgraphic{mpos:region:anchor} setbounds currentpicture to multibox ; \stopuseMPgraphic \startMPpositiongraphic{mpos:region}{fillcolor,filloffset,linecolor,gridcolor,linewidth,gridwidth,gridshift,lineradius,lineoffset} \includeMPgraphic{mpos:region:setup} ; \includeMPgraphic{mpos:region:extra} ; \MPgetmultipars{\MPvar{self}}{\MPanchorid} ; \includeMPgraphic{\MPvar{mp}} ; \includeMPgraphic{mpos:region:anchor} ; \stopMPpositiongraphic %D For old times sake: \startMPpositiongraphic{mpos:box}{fillcolor,linecolor,linewidth} string tag; tag := "\MPvar{self}" ; path box ; box := positionbox(tag) ; box := box enlarged \MPvar{filloffset} ; fill box withcolor \MPvar{fillcolor} ; draw box withcolor \MPvar{linecolor} withpen pencircle scaled \MPvar{linewidth} ; positioninregion; \stopMPpositiongraphic \startMPpositionmethod{mpos:region} \MPpositiongraphic{mpos:region}{}% \stopMPpositionmethod \startuseMPgraphic{mpos:region:draw} draw_multi_pars \stopuseMPgraphic \startuseMPgraphic{mpos:region:show} show_multi_pars \stopuseMPgraphic \startuseMPgraphic{mpos:region:kind} show_multi_kind \stopuseMPgraphic \startuseMPgraphic{mpos:region:sideline} draw_multi_side \stopuseMPgraphic \startuseMPgraphic{mpos:region:sideline:dashed} draw_multi_side_path dashed evenly ; \stopuseMPgraphic %D As an example we define a grid background: \definetextbackground [\v!grid] [\c!state=\v!stop, \c!location=\v!paragraph, \c!frame=\v!off, \c!framecolor=red, \c!background=, \c!alternative=1] \ifx\basegrid\undefined \else \letvalue\v!grid=\basegrid \fi %D Some examples (that might become modules anch-imp-whatever): \setupMPvariables [mpos:encircle] [fillcolor=lightgray, filloffset=\!!zeropoint, linecolor=blue, lineoffset=5pt, linewidth=1pt] \startMPpositiongraphic{mpos:encircle}{linecolor,fillcolor,linewidth,lineoffset} \MPgetposboxes{\MPvar{self}}{\MPanchorid} if nofposboxes = 1 : posboxes[1] := posboxes[1] enlarged \MPvar{lineoffset} cornered \MPvar{lineoffset} ; fill posboxes[1] withcolor \MPvar{fillcolor} ; draw posboxes[1] withpen pencircle scaled \MPvar{linewidth} withcolor \MPvar{linecolor} ; fi ; \stopMPpositiongraphic \setupMPvariables [mpos:connect] [linecolor=red, lineoffset=.25ex, linewidth=1pt] \startMPpositiongraphic{mpos:connect}{linecolor,lineoffset,linewidth} boxlinewidth := \MPvar{linewidth} ; boxlineoffset := \MPvar{lineoffset} ; def boxlineoptions = withcolor \MPvar{linecolor} enddef ; \MPgetposboxes{\MPvar{from},\MPvar{to}}{\MPanchorid} connect_positions ; \stopMPpositiongraphic \protect \endinput \definetextbackground[underline] [location=text,alternative=1,background=,frame=off] \definetextbackground[overstrike] [location=text,alternative=2,background=,frame=off] \definetextbackground[exlines] [location=text,alternative=3,background=,frame=off] \definetextbackground[strikethrough][location=text,alternative=4,background=,frame=off] \definestartstop [underline] [before={\starttextbackground[underline]}, after=\stoptextbackground] \definestartstop [overstrike] [before={\starttextbackground[overstrike]}, after=\stoptextbackground] \definestartstop [exlines] [before={\starttextbackground[exlines]}, after=\stoptextbackground] \definestartstop [strikethrough] [before={\starttextbackground[strikethrough]}, after=\stoptextbackground] \definetextbackground [sideline] [mp=mpos:region:sideline, location=paragraph, framecolor=red, frameoffset=5mm] \definestartstop [sideline] [before={\starttextbackground[sideline]}, after=\stoptextbackground] \starttext \startunderline \input tufte \stopunderline \blank \startoverstrike \input tufte \stopoverstrike \blank \startexlines \input tufte \stopexlines \blank \startstrikethrough \input tufte \stopstrikethrough \blank \startsideline \input tufte \stopsideline \blank \page \startpositionoverlay{text-1} \setMPpositiongraphic{connect-1-b}{mpos:connect}{from=connect-1-b,to=connect-1-e} \setMPpositiongraphic{connect-1-e}{mpos:connect}{from=connect-1-b,to=connect-1-e} \stoppositionoverlay \startpositionoverlay{text-1} \setMPpositiongraphic{encircle-1}{mpos:encircle}{self=encircle-1} \stoppositionoverlay test \hpos{connect-1-b}{START} \dorecurse{10}{\input ward} \hpos{encircle-1}{\strut HERE} \dorecurse{10}{\input ward} \hpos{connect-1-e}{STOP} test \stoptext