Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Understanding the stack and data 1

Status
Not open for further replies.

flash3433

Programmer
Mar 16, 2004
18
I used to think I was fairly intelligent.

A very small question, but after poring over the PS Language Manual and a helpful book "Thinking in Postscript" I still do not get it.

Question: After executing a simple
Code:
 35 50 moveto (words) show
I want to draw a line of certain length and width in a certain location RELATIVE to where the last words printed.

Of course, there is no currentpoint. How do I retrieve the x y coordinates of where the last printing stopped and use them to locate my line with rmoveto's?

Thanks.
 
Hello. There is a current point. And the currentpoint is exactly where it should be. You can think of it as being after the last character in the string processed by "show". The "s" in your example. It's a little more complex than that, having to do with glyphs and all of their little offsets and font BBoxes... but that's not really relevant in most cases.

Add "currentpoint pstack" to your code, and you'll see two numbers: 50.0 (your 'Y' value), plus a value that depends on your currentfont, etc. The 'X' value.

The "stringwidth" operator measures how far your currentpoint would travel in the currentfont, given a string, in two dimensions: x, y. In western languages, y doesn't change, so you often see:

Code:
(some string) dup stringwidth pop

to measure a string, and leave it and it's "width" on the stack.

You can use the currentpoint implicitly with rmoveto and rlineto. Say you wanted to show a string and then underline it. This is a first attempt:

Code:
35 50 moveto (words) dup show 
stringwidth pop neg 0 rlineto stroke

The key is to duplicate your string so you can measure it, use stringwidth to determine "distance travelled", and use rlineto with the current point left by "show".

That isn't good enough, because it draws the line at the exact same baseline as your string, whereas you really want it a bit lower. Keep in mind that "show" does indeed update the current point in the graphics state, and that the "currentpoint" operator can put those numbers on the operand stack for you to use. So let's update our code to move our "underline" down two points:

Code:
35 50 moveto (words) dup show
currentpoint 4 sub moveto
stringwidth pop neg 0 rlineto stroke




Thomas D. Greer
Providing PostScript & PDF
Training, Development & Consulting
 
Just a small correction. I said the code would move the underling "down two points" but my code actually moves it down 4 pts with "4 sub".

Thomas D. Greer
Providing PostScript & PDF
Training, Development & Consulting
 
I have gotten one line to print, just where I want it. But when I try to print the second line I get a "nocurrentpoint" error.
Code:
( ) dup show
13 setlinewidth .7 setgray
 currentpoint
-68 -13 rmoveto dup dup
73 0 rlineto stroke
currentpoint
30 0 rmoveto
76 0 rlineto stroke
I use the empty "dup show" because the text just before it is formatted by JustText and I cannot stick a "dup" in before it "shows".

I've tried the same thing after printing the first line, but that doesn't seem to work in finding a currentpoint for the second line. As you can see, I've tried "dup dup" 'ing which must be a PS sin.

Why doesn't the second currentpoint work?
 
Because your "stroke" consumes it.

Here's how "stroke" works: it paints a line centered over the current path. Then it erases the path with an implicit call to "newpath". Once you've painted a path, in other words, you no longer have a path.

The current path starts at currentpoint, and then follows you around as you use path operators, such as moveto, rmoveto, lineto, rlineto, arcto, curveto, etc.

But as soon as you stroke or fill the path, the path, poof! is gone.

It isn't clear to me what your code is trying to do, so I don't know how to "fix" it.

If you want to use the ORIGINAL CURRENTPOINT coordinates twice, then immediately follow your first currentpoint with "2 copy". That will leave the values on the stack for when you want to use them again.

If you want to reuse a path you've drawn... for example, to draw a circle, fill the circle yellow and then outline it with a black line (fill the path, then stroke the same path), you 1st create your path, then peform a "gsave" to save the graphics state (including the path), do your fill (which clears the path). Next, "grestore" to go back to the saved graphic state (your path is now back!), and stroke.

Back to your code, why a 13 point line? A line that big isn't a line, it's a rectangle! You might look at the rectangle operators: rectstroke, rectfill.



Thomas D. Greer
Providing PostScript & PDF
Training, Development & Consulting
 
It's a filled line/rectangle with light text over it.

Is there a reason why a rectangle is better than a thick line?

The "gsave grestore" worked just great.

Sad to say, that I should have thought of myself.
 
Rectangle vs. Line... no clear winner, I suppose. Lines are affected by the current graphics state (linecap, linewidth, mitre limit). But if you are protecting the graphics state with gsave/grestore, it's up to you.



Thomas D. Greer
Providing PostScript & PDF
Training, Development & Consulting
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top