8

I need to define a macro or do some special action every time a new page is encountered. In some sense I want to "number" tikzpictures but have all the tikzpictures on the same page contain the same number. (It's more complex than this but it is just a simple example)

Basically all I want to do is define a macro at the start of every new page. I'll use that macro to in my tikzpictures to do some special things and they may delete the macro depending on something(which is why I need to set it on each new page so it get's reset each page).

The macro needs to be defined at the start of every new page before any tex in my document is executed.

Basically I want to avoid having to add the macro in the document myself for each new page(which is hard to control and clutters up the thing).

My case: I have several tikspictures scattered throughout my document but some are on the same page.

I want the first one on the page to have special treatment(like put a caption on it). BUT I may add or remove text which may change the ordering and I don't want to have to update the code.

For example,

-New Page
Text
Img1 *
Img2 
-New Page
Img3 *
Text
Img4
Img5
-New Page
Img6 *

Because Img 1 3 and 6 are the first on the page I want to do something to them. BUT I do not want to hard code this because it may easily change(when I add text it may push put some images on a new page, i.e.,

-New Page
Text
Img1 *
-New Page
Img2 
Img3 *
Text
Img4
-New Page
Img5
Img6 *

and notice how * does not correspond to the first image on the page(like I want it). i.e., this is what will happen if you hard code the things I want to do.

Also, Because tex first has to calculate image bbox to determine if it is on the current page or not I need code that will work since my images will depend on if they are the first image on the page or not.

My "Special" action is only horizontally centering the image and so shouldn't effect layout.

The issue stems from

tikzpicture alignment and centering

and I'm trying to streamline and automate the process. I need to apply the master and slave pattern in the way I have describe. The first image on the page should get the master style and the remaining should get the slave BUT not hard coded since it causes the problem I gave above.

(Note how Jake's answer has hard coded master and slave. This causes major problems if you add text which pushes some images on a new page. (since the first image on the page should be master but by hard coded it you could get a slave as the first image)

Uiy
  • 6,132
  • 1
    This is possible but not that simple. If I understand you correctly it's similar to things I did in the past, either with the atbegshi or everypage package. Have a look at the following Qs and As: Installing background and foreground page layers with TikZ (both the question and answers), http://tex.stackexchange.com/a/19481/2975, http://tex.stackexchange.com/a/21522/2975 and http://tex.stackexchange.com/a/24279/2975. – Martin Scharrer Apr 03 '12 at 16:16
  • This seems possible. However, you need to be more specific in your needs, since the current general description makes any generic solution (or answer) useless. For example, the first "simple example" has a definite answer, but you mention that things are "more complex." – Werner Apr 03 '12 at 16:17
  • I also started to transform my above linked code into two packages, which however aren't finished yet. Just in case they or their code is useful for you: https://bitbucket.org/martin_scharrer/tikzpagelayers and https://bitbucket.org/martin_scharrer/tikzpagenodes. However, there are some issues with transparencies and maybe pattern which I didn't fixed yet. – Martin Scharrer Apr 03 '12 at 16:20
  • @Werner Well, If you read what I said I gave the general case and a specific instance of that general case. Sure there are many ways to do things but as I said, I want to simply declare a new macro per new page at the top of it. If you give me the way to do that efficiently I should be able to take it from there. – Uiy Apr 03 '12 at 16:52
  • @MartinScharrer I'm not sure if that is what I want. The two packages, at a glance, seems to do things only after layout has already been calculated. I'll edit my response with a better example of my specific case. – Uiy Apr 03 '12 at 16:56
  • 3
    What you ask for can't be done exactly in tex as macro expansion happens long before pagination, it is quite easy, especially if producing big things like pictures or tables for macros to produce enough material to fill more than one page so the output routine cuts then in to pages later, and the macros have no knowledge of the final page at the time they are expanded. It is possible to take a best guess (based on the value of \thepage) and detect when it is wrong and adjust in a later run. see for example footnpag.sty which resets the footnote counter each page, so has exactly this problem. – David Carlisle Apr 03 '12 at 17:08
  • are your picture floats? If they are LaTex knows at the time it inserts the float whether that is the first float of that type on the page, so in that case you could modify the float code to re-box the first float and add additional text or horizontal positioning. This would then not need the 2 pass solution. – David Carlisle Apr 03 '12 at 17:15
  • @DavidCarlisle No, they are not floats BUT what I want to adjust should not effect layout in any way to cause problems. It will just shift the images slightly to the left or right. So it is sort of like the footnpag except I do need to adjust the position of things before hand(which the footnpag may not do). i.e, tex can do it's thing but I need to someway modify the position of things after tex does it's processing. But this would need to be done in tex rather than some post processor. – Uiy Apr 03 '12 at 21:32

2 Answers2

10

You still need to do it in two passes.

Consider a single long paragraph that takes a page or two. all macros in the paragraph are fully expanded before line breaking is considered, and only after line breaks are decided the output routine is triggered to consider page breaking.

The page breaking never affects the line breaking decisions, and the line breaker never affects the macro expansion. So no part of the macro expansion can be affected by the page breaking.

What you can do is get each picture to do a \label{uniquelabel} then it can (on a later run of latex) inspect \pageref{uniquelable} and \pageref{the-label-of-previous-figure} to see if you are the first on the page.

so in the example below, the first example on every page gets a modified formatting saying "first on page"

enter image description here

\documentclass{article}
\textheight15\baselineskip
\newcounter{pcount}
\makeatletter
\newenvironment{test}{%
\refstepcounter{pcount}%
\par\bigskip
\edef\this{\expandafter\expandafter\expandafter\@secondoftwo\csname r@x:\thepcount\endcsname\@empty}%
\ifx\this\@empty
\typeout{first pass}%
\def\format{}%
\else
\advance\c@pcount\m@ne
\edef\prev{\expandafter\expandafter\expandafter\@secondoftwo\csname r@x:\thepcount\endcsname\@empty}%
\advance\c@pcount\@ne
\ifx\prev\this
\def\format{}%
\else
\def\format{first on page! }%
\fi
\fi
\begin{tabular}{|l|}\hline \format test:\label{x:\thepcount} \thepcount\\\hline}
{\\\hline\end{tabular}
\bigskip}
\makeatother

\begin{document}

test

\begin{test}one\\two\end{test}
\begin{test}aaa\\bbb\\ccc\end{test}
\begin{test}aaa\\bbb\\ccc\end{test}

more text

\begin{test}red\\green\\blue\end{test}
\begin{test}1\\2\\2\\4\end{test}

more text

\begin{test}black\\white\\\end{test}
\begin{test}a\\b\\c\\d\end{test}

\end{document}
David Carlisle
  • 757,742
  • Ok, I'll have to spend a little time trying to determine exactly how the code works but I might be able to get it to work in my code. Is it possible to wrap this in a sort of "2ndpasspagecounter" and "2ndpasspageindexcounter" macros? The first would create a page counter that is expanded on the 2nd pass and the second would create an index counter per page(which would reset every new page)... basically your pcount. Essentially I would like to wrap the complexities since it would be too much work to apply this to each image. Obviously you can do it as an environment like you have. – Uiy Apr 03 '12 at 23:36
  • But I'm thinking of simply having to call \2ndpasspagecounter would return the page number(but after the fact). \2ndpasspageindexcounter would return the index into the page... possibly every time it is called it is simply incremented except when a new page is create it would reset. (so it would be as simple as checking if a new page has been created and then reset the internal counter) – Uiy Apr 03 '12 at 23:39
  • Your comment is not very clear, but if I understand you correctly that is not how TeX works. You can increment a page counter in the output routine as each page is shipped out, but that can not (with any reliability) affect the macro expansion that happens on that page, as as I explained the macros are expanded (and counters are set/reset/compared) long before that. – David Carlisle Apr 03 '12 at 23:57
  • since it would be too much work to apply this to each image There is just a single command (the first bit of the environment definition) that needs to be added to whatever macro is making your images, it is hard to see how you could have less than that? As shown in my example there is no cumbersome code within the document. – David Carlisle Apr 04 '12 at 00:00
  • ok, I guess I was confused. I had to run your code twice to get the correct output. I guess I was confused by what you meant by two pass. Usually "two pass" means the internal "algorithm" or code runs over the code twice but it seems in tex it actually requires the user to run twice. – Uiy Apr 04 '12 at 03:43
  • As far as the "work". Using an environment isn't necessarily a bad thing BUT I am doing this is lua and sometimes it can be a pain to mix tex and lua macros(simply because I want to not have a bunch of files and like to define all my tex macros that lua uses in a lua file(which I have already had problems with because of catcodes) – Uiy Apr 04 '12 at 03:45
  • Look at the code, the only reason it's an environment is because I used a tabular in the example. an environment foo is just two definitions of \oo and \endfoo and in this case \endtest is {\\\hline\end{tabular} I hope it should be clear that none of the code relating to tabular in either the begin or end part is related to the page testing, just an artifact of the example. – David Carlisle Apr 04 '12 at 08:17
  • Yes, that is why I was thinking I could use simple macros. But ultimately I have to figure out how to use it in my own typesetting. – Uiy Apr 04 '12 at 10:00
  • 3
    That's why we always ask people to supply a MWE (which you have objected to in the past) If there had been an example, I'd have added the page reset to that, but as there was not, I had to make up an example and you have to extract the page reset code from that example. That's the way it goes... – David Carlisle Apr 04 '12 at 10:23
  • Anyways, I appreciate your answer and I'll just have to work on it over the next few days to get it the way I want. Oh, and say you went to a site that provided solutions to problems... MWE would be interpreted as the minimal file required for the solution(i.e., something small and concise). Basically "example code" that you typically see. It is minimal, working, and an example. If I provide an "MWE" here, to me, it is not working because it doesn't solve my problem.... that is simply how I interpret MWE. – Uiy Apr 04 '12 at 13:15
  • 1
    @Uiy If anything is unclear, please visit TeX Meta for questions and discussions about the site. Please do not do this in comments to TeX questions or answers. It is offtopic here. So I ask you please delete your comments here. Feel free to post a summary or follow-up questions on TeX Meta. I will clean up the other offtopic comments then. edit: offtopic/meta comments removed after 2 further days – Stefan Kottwitz Apr 05 '12 at 10:07
4

Here is a plain TeX solution. I don't know if it will help you understand David Carlisle's code.

I still use LaTeX's document environment to test the code, but this is irrelevant.

\documentclass{article}

\newcount\uiycount
\newwrite\uiyout
\def\uiycar#1#2\nil{#1}
\def\uiyenv#1{%
  \global\advance\uiycount by1
  \def\currtag{\number\uiycount\number\count0}%
  \par\bigskip
  \def\proclaim{}%
  \immediate\write\uiyout{%
    \noexpand\expandafter\gdef\noexpand\csname
    uiy-\currtag\noexpand\endcsname{\the\count0}%
  }%
  \expandafter\expandafter\expandafter
  \ifx\expandafter\uiycar\csname uiy-\currtag\endcsname\nil\relax
    \typeout{first pass; please rerun.}%
  \else
    \edef\curr{\csname uiy-\currtag\endcsname}%
    \advance\uiycount by-1
    \edef\prev{\csname uiy-\currtag\endcsname}%
    \advance\uiycount by1
    \ifx\prev\curr\else
      \def\proclaim{first on page! }%
    \fi
  \fi
  #1\relax
}
\def\enduiyenv#1{#1\relax}
\openin\uiyout=\jobname.uiy
\ifeof\uiyout\else
  \input\jobname.uiy
\fi
\immediate\openout\uiyout=\jobname.uiy

% Tests
\begin{document}

Testing \ldots

% You can define \startstuff to be anything you want, or just use
% the stuff being defined in \startstuff directly as argument of
% \uiyenv (see example below):
\def\startstuff{%
  \begin{tabular}{|l|}\hline
  \proclaim test: \number\uiycount\\\hline
}
% Similarly, you can define \endstuff to be anything you want, or just use
% the stuff being defined in \endstuff directly as argument of
% \enduiyenv:
\def\endstuff{%
  \\\hline\end{tabular}\bigskip
}

\uiyenv\startstuff one\\two\enduiyenv\endstuff

\uiyenv{%
  \begin{tabular}{|l|}\hline
  \proclaim test: \number\uiycount\\\hline
}
aaa\\bbb\\ccc
\enduiyenv{%
  \\\hline\end{tabular}\bigskip
}

\uiyenv\startstuff aaa\\bbb\\ccc\enduiyenv\endstuff

\newpage
Next text \ldots

\uiyenv\startstuff red\\green\\blue\enduiyenv\endstuff
\uiyenv\startstuff 1\\2\\2\\4\enduiyenv\endstuff

\newpage
More text \ldots

\uiyenv\startstuff black\\white\\\enduiyenv\endstuff

\newpage
\uiyenv\startstuff a\\b\\c\\d\enduiyenv\endstuff

\end{document}
Ahmed Musa
  • 11,742