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