[comp.sys.mac.programmer] Thin lines on Laser

mj@chyde.uwasa.fi (Matti Jakobsson TKO) (10/11/89)

I have tried to produce thin lines on the LaserWriter from a program
in LightSpeed Pascal. When I use the smallest pen (1,1) the figure
is all right on the screen but the lines are too thick on Laser. 

The explanation to this is that the PenSize procedure in QuickDraw 
accepts only integer parameters, (1,1) is the smallest. This
is then converted to PostScript, producing something like

1,1 pen.

In postscript the pen can be much smaller than that. (0.01,0.01) gives
you a nice thin line. 

I have used CMD-f to create the Postcript file and the edited the pen
size using MS-Word and the PostScript style.
The line drawings that I can draw this way are 
ok, but it would be nice to be able to do that from the program.

Any suggestions???

Matti Jakobsson, Univ of Vaasa, Finland, mj@chyde.uwasa.fi

CXT105@PSUVM.BITNET (Christopher Tate) (10/12/89)

Ok, I know of two different ways to do this, each with its own strengths:

1)    You can manually set the reduce/enlarge field in the Style record to be
      something like 25% (the minimum), then pretend that the page is four
      time larger than it really is.  When the print driver scales the page
      based on this info, it actually reduces EVERYTHING, including the pen
      dimensions.  This is the easy way to do it, but your users may set the
      reduce/enlarge back up to 100% and throw you off, depending on how you
      do it.  Also, the user no longer gets any control over how big they
      want their document to print.  (NOTE:  this is the way that the
      program "Diatom" produces fine-line laser output.)

2)    You can use direct PostScript commands to draw the image, using the
      BeginPostScript and TextIsPostScript PicComments.  Any following text
      sent through DrawText will be treated as literal PS code, and the
      printer will attempt to draw it.  So, you can use a command like
      ".02 setlinewidth" to specify a 2/100 of a point pen size, then draw
      the image using "lineto" commands, etc.

      The biggest problem with this method is that drawing images that are
      more complex that simple line figures is nearly impossible using only
      direct PostScript.  Also, you have to figure out a way to construct the
      command strings for DrawString.  The main advantage is that you get
      precise control over the output resolution.  I have a program that draws
      figures using "0 setlinewidth", which gives device-minimum lines.
      If your figures are simple enough that you can figure out the PS drawing
      commands for them directly, and use those to construct the image, then
      you may want to consider using this method.  If your images use Mac-
      type figures, such as patterned fills, etc., then you probably want to
      stick to the first method I described.

The reason that changing the pen size using PenSize doesn't work the way you
want it to is that a) it accepts only integer values, and b) the default
coordinate system for the LaserWriter uses 1-point (1/72 inch) units.  In my
program (mentioned above), the coarseness of resolution imposed by this pen
size caused visible streaking, due to round-off error in the integer math I
was doing (I used integers for speed).  I fixed this by saying ".25 .25 scale"
to reduce the user coordinate system by 4 times, then drawing everything 4
times larger.  This gave much better addressible resolution (over 280 dpi),
and still let me use integers for coordinate specification.  Once again, this
method only works if you are using direct PostScript for your drawing.

I haven't tinkered much with a hybrid of direct PostScript and printer driver
interpretation of regular Mac QuickDraw commands; there may be a way to set
up the pen size and coordinate system to give you the resolution you want,
then drop out of direct PS mode to draw your image using QuickDraw.  Has
anyone else out there worked anything out along these lines?

That's about all I know about this stuff.  If you like, I can send you some
Turbo Pascal source for method 2), but some things would have to be changed,
most notably all the times I concatenated strings.  I haven't used LSP enough
to know how to do that....

-------
Christopher Tate                           | Vengeance (noun):
                                           |  Eye for eye, tooth for tooth;
  Bitnet: cxt105@psuvm                     |  a fair, satisfying, and rapid
  Uucp:   ...!psuvax1!psuvm.bitnet!cxt105  |  way to a sightless, toothless
  Internet: cxt105@psuvm.psu.edu           |  world.

lsr@Apple.COM (Larry Rosenstein) (10/12/89)

See Tech Note 175.  It describes the picture comment you can use to scale 
the pen size for printing on the LaserWriter.

Larry Rosenstein, Apple Computer, Inc.
Object Specialist

Internet: lsr@Apple.com   UUCP: {nsc, sun}!apple!lsr
AppleLink: Rosenstein1

ba0k+@andrew.cmu.edu (Brian Patrick Arnold) (10/12/89)

Hello Everyone,

Since I received plenty of response to a similar question several months
ago, I figure I can suggest using the QuickDraw PicComment #182 a.k.a.
"SetLineWidth" described in Tech Note #175.  This is a way of accessing
PostScript's SetLineWidth operator which enables thin line or
"fractional" line drawing to a LaserWriter or other PostScript device
without resorting to PostScript directly.  If anyone would like a code
example, send me mail.

- Brian

dowdy@apple.com (Tom Dowdy) (10/13/89)

I've watched lots of interesting postings on peoples theories on how
to make this work, but I haven't yet seen what I consider the best
answer.

In article <UZB_yoW00UzxQ1R4wY@andrew.cmu.edu> ba0k+@andrew.cmu.edu (Brian 
Patrick Arnold) writes:
>  [ Recommends use of : ]
> "SetLineWidth" described in Tech Note #175.  

This is a correct way to get thin lines from a LaserWriter.  Note that 
this PicComment is only currently interpreted on the LaserWriter and you 
gain nothing on other printers. 

BUT:
There is a way to get thin lines and device positioning from *all* printer 
drivers.  This is to use the PrGeneral calls GetRslData and SetRsl, as 
documented in Tech Note 128.  When you make these calls, your app is said 
to be "imaging at device resolution."

This means that within your print record you will see the page expressed 
in terms of the resolution that you specified.  This means that you can 
then place/draw objects within the coordinate space of the device, rather 
than the coordinate space of 72 dpi, which is what normally happens.

The reason this approach is better is that owners of LaserWriter SCs, 
DeskWriters (and this is a growing number), ImageWriter LQs, and even 
lowly ImageWriters will be able to draw things to best possible output for 
their device.  Everyone is happy!  And you didn't have to write any 
PostScript, or mess with the Enlarge/Reduce box in the dialog, or even use 
PicComments.

Please note that you do not need to use these calls if you application is 
simply trying to get "smooth looking circles" from the LaserWriter.  The 
drivers take care of that for you.  You only need to make this call if you 
need to draw lines at device resolution, or you need to be able to place 
dots or objects within the coordinate space of the device.

If you'd like to make these calls, please refer to the Tech Note for
information on when/how to call GetRslData and SetRsl.  Those of you
with Volume V of Inside Mac can also find the information there in the
chapter on the Printing Manager, the information looks the same, although
in general I tend check the Tech Notes first because they are updated more
often.

 Tom Dowdy                 Internet:  dowdy@apple.COM
 Apple Computer MS:27AJ    UUCP:      {sun,voder,amdahl,decwrl}!apple!dowdy
 20525 Mariani Ave         AppleLink: DOWDY1
 Cupertino, CA 95014       
 "The 'Ooh-Ah' Bird is so called because it lays square eggs."

casseres@apple.com (David Casseres) (10/13/89)

As others have said, you can get lines thinner than 1 point (1/72") by 
using the comment described in Tech Note 175.  This is the simplest way, 
if you know that you're printing on a PostScript printer.

A more general way is to use the PrGeneral commands to find out what 
drawing resolution the printer will support, then set the resolution and 
draw at, say 300 dots/inch on a LaserWriter or 216 dots/inch on an 
ImageWriter LQ.  Then if you set the pen width to 1x1 with QuickDraw, you 
will get a line 1/300" or 1/216" thick, as the case may be.

The PrGeneral call is described in a Tech Note, but I don't have the 
number on hand at this moment.

David Casseres

Exclaimer:  Hey!

oster@dewey.soe.berkeley.edu (David Phillip Oster) (10/13/89)

Some caveats to the posting of others on this subject:
1.) You don't always want 1-device pixel wide lines. On a 2000dpi
phototypesetter, 1-device pixel wide lines are not visible to the naked
eye. You shouldn't blindly use the device's best resolution, but pick the
resolution closest to what you really want.  (There is a great story about
Mandelbrot making this exact mistake: He thought he was printing a page of
fractals, but the output appeared to be blank, slightly grayish paper.
The fractals _were_ there, you just needed a disecting microscope to see
them.)

2.) The tech notes on SetLineWidth are un-clear on this point: after you
get through drawing fine lines, you should reset the postscript pen size.
The way to do this is not calling.  SetLineWidth with a handle pointing to
(1,1), as the tech note would have you believe, but by calling it with a
handle pointing to the inverse of the previous conversion. i.e., (1,4)
cancels (4,1).  This is consistent with the way postscript tends to work,
in addition to being what actually happens, according to my experiments.
SetLineWidth (1,1) is a no-op.

--David Oster, master of the ad hoc odd hack.
Arpa: oster@dewey.soe.berkeley.edu
Uucp: {uwvax,decvax}!ucbvax!oster%dewey.soe.berkeley.edu