[comp.sys.next] A simple question or two

patl@athena.mit.edu (Patrick J. LoPresti) (04/12/91)

I want to draw a line across a View so that black pixels along the line
become white and white pixels along the line become black.  In other
words, I want an XOR transfer mode for my pen.  I don't care what
happens to shades of gray.

I have waded through both NeXT and Adobe documentation, but have found
no way to do this.  The closest I have seen is the NX_XOR compositing
option, but that relies on transparency, and the image in my View is
entirely opaque.

What if I want to move a bitmap onto the screen with an XOR transfer
mode?  How about AND?  Does the NeXT paradigm support such Mac-like
things?

Second Question:  Someone posted a while ago that the assembly
instruction "trap #2" flushes the 68040 instruction (data?) cache on the
NeXT.  Where is this documented?  What do the other traps do?

Please respond by Email,
Pat
 "Questions are a burden to others; answers a prison for oneself."

garth@cs.swarthmore.edu (Garth Snyder) (04/13/91)

patl@athena.mit.edu (Patrick J. LoPresti) writes:

> I want to draw a line across a View so that black pixels along the line
> become white and white pixels along the line become black.  In other
> words, I want an XOR transfer mode for my pen.  I don't care what
> happens to shades of gray.

Operations of this sort are difficult to perform in PostScript.  You
pretty much have to read the bitmap and process the data yourself.

In simple cases you can do this without actually messing with the bits
directly.  For example, to process a rectangular region, you can use
readimage to pick up the bits, set the PostScript transfer function to
invert (or whatever operation you want) the grays, and re-image the
rectangle.

Below is a wrap that will do just that.  I don't think it's fully
debugged, so you will probably have to play around with it to make it
work.  It expects you to have previously set up a gstate object with
the inverted transfer function; this is a performance optimization
needed because executing the settransfer operator takes quite a long
time (on the order of half a second).

This still doesn't get you the ability to XOR along a line or path,
but you can probably work that with an offscreen drawing area and some
extra compositing operations.

If anyone has come up with a better solution to this problem, I would
love to hear about it.

defineps PSInvertRect(float x, y, width, height; userobject xorGstate)
    gsave
	x y width height matrix sizeimage % pxwd pxhi bps matrix multi ncolor
	pop pop {} % pxwd pxhi bps matrix {}
	4 index 3 index 8 exch div div .5 add round cvi 10 mul
	% pxwd pxhi bps matrix {} #bytes/scan * 10
	string % pxwd pxhi bps matrix {} scanstring
	mark 
	    x y width height {dup length string copy counttomark 1 roll} 
	    7 -1 roll 
	    % pxwd pxhi bps matrix {} mark [ x y width height proc string 
	    false readimage 
	    % pxwide pxhigh bps matrix {} mark strings...
	    counttomark 6 add -5 roll 
	    % mark strings pxwide pxhigh bps matrix {}
	    xorGstate setgstate
	    image
	pop 
   grestore
endps

--
Garth Snyder         |  UUCP: {bpa,liberty}!swatsun!garth
Swarthmore College   |   NET: garth@cs.swarthmore.edu
500 College Avenue   |  DOD#: 0085
Swarthmore, PA 19081 | QUOTE: "Quidquid latine dictum sit, altum viditur"

aozer@next.com (Ali Ozer) (04/13/91)

In article <1991Apr11.212629.25773@athena.mit.edu> Patrick J. LoPresti writes:
>I want to draw a line across a View so that black pixels along the line
>become white and white pixels along the line become black.  In other
>words, I want an XOR transfer mode for my pen.  I don't care what
>happens to shades of gray.

Do you really want to do this or do you want to highlight or frame an
area in your view?

If it's the former, ie, your app really requires that you reverse the
pixels in an area, then PostScript doesn't provide a way: In the
PostScript model you cannot do drawing based on the pixels which have
already been painted. Pixels which are drawn always replace the pixels
under them.  Thus you cannot draw in XOR mode (or any other mode where
the color of the pixels would end up being dependent on the pixels that
are already there).

This leaves redrawing your image as one way to get it to show up
differently.  You could get the exact effect you want (black->white,
white->black) by redrawing the view with the appropriate "negate"
transfer function. (For instance, {1.0 exch sub}. See settransfer.)

Another way to invert an image is to take advantage of some of the
NeXTstep extensions to Display PostScript. These provide ways to read pixels
back from windows (readimage or initData:fromRect: in NXBitmapImageRep),
and ways to composite areas of pixels together.  As you discovered, the XOR 
mode can be used by drawing your image in an offscreen window (using 
transparency for white, say), and then using compositerect to invert it 
and then compositing it to your on-screen window.

Coming back to the original question: If what you wanted to do was to
highlight or frame an area of your view, then using an XOR-based
inversion might not be the best idea.  XORing is often used as a means
of highlighting because it's easy, cheap, and reversible.  However, it
seldom makes visual sense (especially with color images based on palettes).

Depending on the situation, there are different ways of highlighting
an item: sometimes you want to redraw it brighter or darker, sometimes
you want to change one or more colors, sometimes you want to change
the background, sometimes you want to draw a box or little knobbies around it,
etc. NeXTstep provides the "highlight" composite operator, which is used to
highlight monochrome text (by reversing the white & the light gray,
which makes the background change color). It's also useful in some
other cases, like highlighting the standard grayscale buttons used in
NeXTstep. In other situations, you can simply do whatever drawing you
need to do to highlight the area, then redraw the area when to
unhighlight. If redrawing it is too slow, then cache the image and
composite from the cache to refresh.

This might seem like overkill, but it makes the interface cleaner and
highlighting and selections more intuitive and visually appealing
to the end user.

Ali, Ali_Ozer@NeXT.com