U. Windl
U. Windl

Reputation: 4325

How can I collect PostScript operations at runtime to be executed later?

In some code that is plotting data, I'm iterating over the samples and I'm trying to connect the data with curves while creating labels (lines plus text) on the fly. So I'm creating two unrelated paths in parallel. Both elements use different graphics attributes and transformed coordinate systems, so I'm using gsave ... grestore at lot, probably creating inefficient code.

My idea was to collect the instructions for drawing one of these two paths, and then execute them once the other patch has been drawn.

Possibly cvx can help, but I wonder how to prevent operators being executed while adding them to an array (I'm expecting [ moveto ] to pop two elements from the stack before ] is executed). Will [ /moveto ] do the trick?

And the other problem is that collecting the array of operations is difficult when I need the operand stack for drawing the other path.

For example a part of the labeling code (ugly, because still being worked on) looks like this:

            gsave
                currentpoint translate la rotate
                0 rlineto
                %% add a tick mark if it's far enough from the last one (or if it is important)
                mlx x mly y distance lw 2 mul gt
                m lm gt or
                { %if
                    /mlx x def
                    /mly y def
                    currentpoint
                    lw setlinewidth     % label len
                    stroke
                    (Helvetica) findfont fs scalefont setfont
                    moveto              % label
                    180 rotate
                    dup stringwidth pop neg fs 3 div sub fs -2.5 div
                    rmoveto
                    %% add a text label if it looks like there is room (or if it is important)
                    tlx x tly y distance fs 1.2 mul gt
                    m lm gt or
                    { %ifelse
                        show
                        /tlx x def
                        /tly y def
                    }
                    { pop } ifelse
                    /lm m def
                } { pop }
                ifelse
            grestore

Upvotes: 1

Views: 1537

Answers (1)

luser droog
luser droog

Reputation: 19504

For the first part, /moveto cvx will give you an executable name which won't execute right away, but it will execute later if you put it into an executable array and exec it. If you just do /moveto then the name is a literal name and it won't execute later with exec.

For the other part, collecting pieces into an array while still using the stack for execution, one simple way is to place a mark on the stack and roll everything behind the mark to deal with it later. Eg.

mark

%... do stuff with stack

1 2 3 counttomark 1 add 3 roll  % save 3 numbers behind mark

%... do stuff with stack

cleartomark                  % discard working area
count array astore           % make array from stack contents

Upvotes: 1

Related Questions