[comp.lang.postscript] setgray within the scope of a BuildChar

cramer@optilink.UUCP (Clayton Cramer) (08/11/89)

I'm defining a character set, and I need to draw a reverse video circle.
Unfortunately, to quote the Red Book, "The use of setgray after a 
setcachedevice operation within the scope of a BuildChar procedure
is not permitted (an undefined error results)."

Here's what I'm trying to do.  Does anyone have an alternate suggestion?

    bsmiley {
      newpath
      300 300 300 0 360 arc
      closepath fill
      300 300 150 210 330 arc 1 setgray 1 setlinecap 100 setlinewidth stroke
      200 400 70 0 360 arc closepath fill
      400 400 70 0 360 arc closepath fill} def

-- 
Clayton E. Cramer {pyramid,pixar,tekbspa}!optilink!cramer
A pacifist who calls the police isn't one; hired violence is still violence.
----------------------------------------------------------------------------
Disclaimer?  You must be kidding!  No company would hold opinions like mine!

amanda@intercon.uu.net (Amanda Walker) (08/11/89)

In article <2072@optilink.UUCP>, cramer@optilink.UUCP (Clayton Cramer) writes:
> Unfortunately, to quote the Red Book, "The use of setgray after a 
> setcachedevice operation within the scope of a BuildChar procedure
> is not permitted (an undefined error results)."
> 
> Does anyone have an alternate suggestion?

Two approaches come to mind:

 - make the shape into one path and use "eofill" on it.

 - don't use setcachedevice for that particular character.

I'd try the first one, since that way the character will act like a
"stencil" the way it's supposed to if you do any kind of special
effects.

--
Amanda Walker
InterCon Systems Corporation
--
amanda@intercon.uu.net    |    ...!uunet!intercon!amanda
--
"It can hardly be a coincidence that no language on earth has ever
produced the expression 'As pretty as an airport'"
    --Douglas Adams, _The_Long_

geof@apolling (Geof Cooper) (08/17/89)

In article <2072@optilink.UUCP> cramer@optilink.UUCP (Clayton Cramer)
writes:
  > I'm defining a character set, and I need to draw a reverse
video circle.
  > 
  > bsmiley { 
  > newpath
  > 300 300 300 0 360 arc closepath fill
  > 300 300 150 210 330 arc 1 setgray 1 setlinecap 100 setlinewidth stroke
  > 200 400 70 0 360 arc closepath fill
  > 400 400 70 0 360 arc closepath fill } def
  
You can achieve the effect you want to tracing the (multiple contour)
outline of the object you want and then executing one FILL or EOFILL
command.  Either fill technique will work, but I find that EOFILL is
easier to hand-design with, since you don't have to pay attention to
the direction of contours.  Recall that under EOFILL, you can tell
whether a point is part of the region to be filled or not by counting
if the number of contours around it is odd.  Hence, a circle with a
circle inside it turns into a ring-band.

The principle inconvenience of doing this is that the ARC and ARCN
operators make implicit use of the current point, so you have to
compute the starting point of the arc manually and do a "moveto" to it
before calling ARC.  This "polar moveto" is an obvious primitive if
you do a lot of stuff like this -- I just did the code out here.

Here is my attempt:

/bsimley {
    % outer circle
    newpath
    300 300 300 0 360 arc closepath
    % This part would make it a non-reversed smiley
    %600 300 moveto
    %300 300 280 0 360 arc closepath

    % mouth: Can make this more efficient by pre-computing
    %        the trig computations.
    % Upper lip
    300 175 210 cos mul add
    350 175 210 sin mul add moveto
    300 350 175 210 330 arc
    % right corner - draw 180-degree arc between upper & lower lips.
    currentpoint exch
    37.5 330 cos mul add exch
    37.5 330 sin mul add
    37.5 150 330 arcn
    % lower lip = same arc 75 units down, going the other way.
    300 350 250 330 210 arcn 
    % left corner
    currentpoint exch
    37.5 210 cos mul sub exch
    37.5 210 sin mul sub
    37.5 210 30 arcn
    closepath

    % 270 = 200 + 70*cos(0), 400 = 400 + 70*sin(0).
    270 400 moveto
    200 400 70 0 360 arc closepath

    470 400 moveto
    400 400 70 0 360 arc closepath

    eofill
} bind def