1

EDIT This question was edited and made more precise.

Background

This is a question related to my other one. In a desperate effort made to avoid some of tcolorbox pitfalls described there, I have decided to create my own frame drawing code, inspired by this great answer. Its major advantage over other solutions is that is does not interrupt the normal flow of the text, but rather draws everything in the background, using TikZ's overlay, remember picture functionality. It works well both with footnotes and with stretchable vertical glue (as opposed to tcolorbox, as described here).

Question

I need help with specifying the dimension of the frame's vertical margin and padding (meaning analogous to CSS).

Consider the following objects:

  1. the bottom edge of the horizontal box preceding the frame,
  2. the top edge of the frame (controlled by the position of \tikzmark),
  3. the top edge of the first horizontal box inside the frame,
  4. the bottom edge of the last horizontal box inside the frame,
  5. the bottom edge of the frame (controlled by the position of \tikzmark),
  6. the top edge of the horizontal box coming right after the frame.

I would like to set the amount of space between (1) and (2) precisely to \marginTop, between (2) and (3) to \paddingTop, and similarly between (4) and (5) to \paddingBottom, and finally between (5) and (6) precisely to \marginBottom.

All of the macros above are defied in my code, they provide some glue values.

enter image description here

Given my code (below), this amounts to placing two \tikzmarks in appropriate places, by modifying the code of the environment tikzBgFrame. How to do that? I tried numerous approaches, combining \par, \vskip, \vspace commands in various way, but did not obtain satisfying results.

Additionally, I would be grateful for any feedback how to improve and organise my code better.

Illustration

of how the frames currently look like in a document enter image description here

Code

\documentclass{report}
\usepackage[utf8]{inputenc}
\usepackage{lipsum}
% \usepackage{lua-visual-debug} % only with luaTeX
\flushbottom
\setlength{\skip\footins}{10pt}

% --------------------------- % % START of frame drawing code % % --------------------------- % \usepackage{tikz} \usetikzlibrary{tikzmark,calc} \usepackage{tikzpagenodes} \usepackage{xassoccnt} \usepackage{bophook} \usepackage{xcolor} \usepackage{ifthen}

% Colours \definecolor{my-purple-very-light}{HTML}{f1ebf7} \definecolor{my-purple}{HTML}{6700CE}

% Dimensions \newcommand{\marginTop}{10pt} \newcommand{\marginBottom}{10pt} \newcommand{\marginFootnote}{10pt} % how to set this to \skip\footins? \newcommand{\paddingHorizontal}{10pt} \newcommand{\paddingTop}{5pt} \newcommand{\paddingBottom}{5pt}

% Auxiliary ifs -- how to get rid of them? \newif\ifHasBegin \newif\ifHasEnd

% Get the "real" number of a page \newcounter{realpage} \DeclareAssociatedCounters{page}{realpage} \AtBeginDocument{% \stepcounter{realpage} }

% Count frames \newcounter{tikzbgframecounter} \setcounter{tikzbgframecounter}{0} \def\frametofinish{0}

% Redefine footnote to contain a tikzmark \let\oldfootnoterule\footnoterule \def\footnoterule{\tikzmark{footnotemark\therealpage}\oldfootnoterule}

% Things to do at begin of every page \AtBeginPage{% \setupAnchors% Add tikzmarks for the north west, and for the south east corners of the broken frames, taking footnotes into account \drawContinuedFrame% Draw continued broken frame, if there is one }

\newcommand{\setupAnchors}{ \begin{tikzpicture}[remember picture, overlay] \tikzmark{frameNorthWestPage\therealpage}{([xshift=-\paddingHorizontal,yshift=\paddingTop]current page text area.north west)} \coordinate (tmp1) at ([xshift=\paddingHorizontal,yshift=-\paddingBottom]current page text area.south east);

    \iftikzmarkoncurrentpage{footnotemark\therealpage}% footnotes appear on this page
        \coordinate (tmp2) at ([yshift=-\paddingBottom+\marginFootnote]pic cs:footnotemark\therealpage);
        \tikzmark{frameSouthEastPage\therealpage}{(tmp2 -| tmp1)}
    \else
        \tikzmark{frameSouthEastPage\therealpage}{(tmp1)}
    \fi
\end{tikzpicture}

}

% Frame types enum \newcommand{\frameUnbroken}{0} \newcommand{\frameFirst}{1} \newcommand{\frameMiddle}{2} \newcommand{\frameLast}{3}

% Draw a rectangle with a thick line on the left \newcommand{\drawTikzBgFrame}[3][]{ \fill[my-purple-very-light,opacity=0.5] (#2) rectangle (#3); \draw[my-purple, thick] ({#2}) -- ({#2} |- {#3}); }

% Draw the rectangle in an appropriate place, depending on the situation \newcommand{\drawTikzBgFramePart}[2][\frameUnbroken]{% \begin{tikzpicture}[remember picture, overlay] \ifthenelse{#1=\frameUnbroken}{ % the frame is not broken, draw everything \drawTikzBgFrame {{pic cs:frameNorthWestPage\therealpage} |- {pic cs:frame#2begin}} {{pic cs:frame#2end} -| {pic cs:frameSouthEastPage\therealpage}} }{} \ifthenelse{#1=\frameFirst}{ % draw the first part of a broken frame \drawTikzBgFrame {{pic cs:frameNorthWestPage\therealpage} |- {pic cs:frame#2begin}} {pic cs:frameSouthEastPage\therealpage} }{} \ifthenelse{#1=\frameMiddle}{ % draw the middle part of a broken frame \drawTikzBgFrame {pic cs:frameNorthWestPage\therealpage} {pic cs:frameSouthEastPage\therealpage} }{} \ifthenelse{#1=\frameLast}{ % draw the final part of a broken frame \drawTikzBgFrame {pic cs:frameNorthWestPage\therealpage} {{pic cs:frame#2end} -| {pic cs:frameSouthEastPage\therealpage}} }{} \end{tikzpicture}% }

% Main part - an environment for placing frames \newenvironment{tikzBgFrame}[1][]{{% \parskip=0pt% \par\stepcounter{tikzbgframecounter}% \strut\tikzmark{frame\thetikzbgframecounter begin}\par% \iftikzmarkoncurrentpage{frame\thetikzbgframecounter end}{% \drawTikzBgFramePart[\frameUnbroken]{\thetikzbgframecounter}% }\else{% \drawTikzBgFramePart[\frameFirst]{\thetikzbgframecounter}% \gdef\frametofinish{\thetikzbgframecounter}% schedule drawing of subsequent parts, handled in \drawContinuedFrame }\fi% \ignorespaces% }}{{% \parskip=0pt% \par\strut\tikzmark{frame\thetikzbgframecounter end}\par% \ignorespacesafterend}}

% Check whether some frame needs to be continued, draw them in the background \newcommand{\drawContinuedFrame}{ \ifthenelse{\not\equal{\frametofinish}{0}}{ \iftikzmarkoncurrentpage{frame\frametofinish begin}\HasBegintrue\else\HasBeginfalse\fi \iftikzmarkoncurrentpage{frame\frametofinish end}\HasEndtrue\else\HasEndfalse\fi \ifthenelse{\boolean{HasBegin}}{}{ \ifthenelse{\not\boolean{HasEnd}}{ \drawTikzBgFramePart[\frameMiddle]{\frametofinish} }{ \drawTikzBgFramePart[\frameLast]{\frametofinish} \gdef\frametofinish{0} % frame has ended, stop drawing on subsequent pages } } }{} }

% ------------------------- % % END of frame drawing code % % ------------------------- %

% Frame drawing test follows \begin{document} \newcommand{\object}{\par\noindent\tikz[]{\draw (0,0) rectangle (\textwidth-0.4pt,3); \node at (\textwidth/2,1.5) {Content}}\par}

\section{Introduction}

% \ifthenelse{\equal{\token}{\token}}{true}{false}

\lipsum[1]

\begin{tikzBgFrame} \lipsum[1-2][1-5] \end{tikzBgFrame} \begin{tikzBgFrame} Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus eleifend mauris vitae consectetur\footnote{This is a footnote.} dapibus. Curabitur sollicitudin quam eget convallis rutrum. Pellentesque pulvinar augue \object \smallskip \object \medskip \object \medskip \object \medskip

\lipsum[5]

Another footnote is referenced here\footnote{This is another footnote\dots}, and here\footnote{\dots and the third one.} too. \lipsum[6]

\medskip \object \medskip \object \medskip \object \medskip \object \end{tikzBgFrame}

\end{document}

Link to Overleaf (source and preview)

link

Radek
  • 163
  • 3
    I would suggest to ask a one particular question (that can be read, tried, and resolved with not too much effort) at a time. – muzimuzhi Z Feb 07 '22 at 02:08
  • 1
    you are adding lots of white space from ends of lines, you probably want to % those. the answer to question 4 is the value of \skip\footins is accessed as \skip\footins (I don't understand the question:-) \ifdim\skip\footins=3pt something \else something else \fi – David Carlisle Feb 07 '22 at 08:13
  • 1
    where is my comment about the compilation errors? – Ulrike Fischer Feb 07 '22 at 13:28
  • @UlrikeFischer compilation errors? I do not get any (compiling with LuaTeX). – Radek Feb 08 '22 at 16:12
  • @muzimuzhiZ I have limited the scope of my question and improved the readability of the code. – Radek Feb 08 '22 at 16:13
  • Delete the aux-file and try again. – Ulrike Fischer Feb 08 '22 at 16:13
  • @DavidCarlisle , thank you for your comment. I removed the white space and updated the question. When asking about \skip\footins, I meant that I would like to write [yshift=\skip\footins] in TikZ coordinate computations, but it does not work. – Radek Feb 08 '22 at 16:15
  • @UlrikeFischer Compiled in a new directory, containing only main.tex file. Output written on main.pdf (3 pages, 56064 bytes). Transcript written on main.log., exit code 0. I am using TeX Live 2021, but it also compiles on Overleaf: https://www.overleaf.com/project/61ffcb5033f4f2f8239cf336 – Radek Feb 08 '22 at 16:25
  • Your macros are still adding white space, there is no need to add % after a command name (where you added %) but for example \stepcounter{realpage}SPACE and \newcommand{\setupAnchors}{SPACE, \end{tikzpicture}SPACE, \newcommand{\drawTikzBgFrame}[3][]{SPACE, \ifthenelse{#1=\frameFirst}{SPACE% draw – David Carlisle Feb 08 '22 at 16:29
  • @DavidCarlisle Thank you, I will edit the code in a bit. In your last two examples, is the lack of % a problem too? These fragments are placed inside the TikZ picture, I thought spaces are OK there. – Radek Feb 08 '22 at 16:41
  • Yes quite possibly the space tokens don't produce visible space I didn't check them all carefully, ie where the macros are called, but in a question asking about space in the output, commenting on spurious space tokens in tehinput is usually a good guess – David Carlisle Feb 08 '22 at 16:47

0 Answers0