[comp.windows.x] XSetFunction with GXxor on Sun3

xw@infko.UUCP (Randolf Werner (X11 Admin)) (02/17/91)

I want to use Xor Drawing Mode for inverting my drawings in a window. Therefore
I used XSetFunction with function "GXxor". This works fine on Data General
Aviion 200 but doesn't work on Sun3 Machines. In the source of "texx" I found
a hint that Sun3 has problems with GXand and GXor. Is there a patch or 
workaround for this problem ?

Thanks in advance

	Randolf Werner
-- 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Randolf Werner (X11 Admin) FB Informatik, Uni Koblenz,          xw@infko.UUCP
Rheinau 3-4, D-5400 Koblenz, Germany           ...!uunet!mcsun!unido!infko!xw 

mouse@lightning.mcrcim.mcgill.EDU (02/18/91)

> I want to use Xor Drawing Mode for inverting my drawings in a window.
> Therefore I used XSetFunction with function "GXxor".  This works fine
> on Data General Aviion 200 but doesn't work on Sun3 Machines.  In the
> source of "texx" I found a hint that Sun3 has problems with GXand and
> GXor.  Is there a patch or workaround for this problem ?

I have seen nothing to indicate any problem with "unusual" GC functions
on Sun-3s.  "Problems" using GXxor, GXand, etc, usually turn out to be
misunderstandings by the application programmer of just what a function
of GXxor (for example) asks for.

To put it briefly: if you set the function to GXxor, you also need to
set the foreground to the XOR of your foreground and background colors.
(If you are using calls like XDrawImageString or XCopyPlane that use
the background color, you also need to set it - to 0.)

Why is this?  Because the GC function is applied to pixel values.

Let's suppose you have two "monochrome" servers.  Suppose one server
uses 0 for black and 1 for white.  Then, on this server, you need to
draw in white (ie, with the foreground color of the GC set to the value
you got when you asked for the "white" pixel value, which is 1) for
GXxor to have any effect, because XORing pixels with 0 doesn't do much.
But on the other server, which uses 1 for black and 0 for white, you
need to draw in black, for the same reason.

Of course, what you really need to do is to draw in color 1, whichever
that happens to be.

But now let's consider a color server.  Let's keep things simple by
assuming the application isn't interested in lots of funky colors; it
just has a foreground color and a background color.

Now let's suppose that the foreground color is 0 and the background
color is 1.  (Perhaps these are "white" and "black"; perhaps they were
allocated from command-line arguments specifying colors.  Perhaps they
came from somewhere else; it doesn't matter.)  As before, you need to
draw with a foreground color of 1.  If we switch 0 and 1, the same is
true.  This is all just as it was on the "monochrome" server.

But now let's suppose the foreground color is 18 and the background
color is 254.  (In binary, 00010010 and 11111110.  I shall use binary
heavily, because it makes it much easier to see XORs happening.)  Now,
what value should we draw with?  Well, suppose there's a pixel on the
screen that's currently a background pixel, so it has value 00010010.
What must we XOR that with in order to get a foreground pixel, value
11111110?  Well, we need 00010010 ^ 11111110, which is 11101100, or
236.  Similarly, to convert a foreground pixel into a background pixel,
the same value is needed.

What goes wrong if we try using the foreground or background color?
Let's try it.  Suppose we use the foreground color, 11111110.	Then, a
background pixel, 00010010, becomes 00010010 ^ 11111110 = 11101100.  A
foreground pixel will become 00000000.  In both cases, the resulting
color is not the color we want; indeed, it's neither of the cells whose
contents we know.  It may happen to land in an unoccupied cell of the
colormap; it may happen to use some other client's cell.

Of course, if we are particularly lucky (or unlucky, depending on how
you look at it), the numbers may happen to be such that the result is
one of "our" colors.  This happens often enough to be very confusing.

Thus, when using GXxor, you should set your foreground color to the XOR
of your "foreground" pixel value and your "background" pixel value.
When using GXand, GXor, and similar functions, you usually need to take
care to make sure the pixel values are such that the result is useful.
Setting this up is not always easy, and in the case of a server that
doesn't offer dynamic visuals, may be impossible; on such servers, you
will have to resort to other methods to get your effect.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

john@acorn.co.uk (John Bowler) (02/26/91)

In article <9102180503.AA22046@lightning.McRCIM.McGill.EDU> mouse@lightning.mcrcim.mcgill.EDU writes:
[ clear and useful explanation of the common problem with GXxor ]
>
>Thus, when using GXxor, you should set your foreground color to the XOR
>of your "foreground" pixel value and your "background" pixel value.

<<Skip the following if you had trouble with der Mouse's explanation;
  this will just confuse things more>>

Alternatively set the foreground ``colour'' (ie pixel value) to ~0
(that's the *pixel value* with all bits set, not the screen white
pixel!) and set the raster op to GXinvert.  The foreground colour
doesn't matter.

On a well written server this will be handled precisely as GXxor+~0
plane mask+foreground, but on some servers which support a hardware
bit mask or which spot raster ops with no source pixel involvement
it may be more efficient.  On the other hand, on some servers with
special case optimisation of GXxor it may be significantly less
efficient :-(.

In general using GXclear, GXset and GXinvert with a plane mask may be
easier to understand than using GXand, GXor and GXxor with a suitably
synthesised foreground pixel value.

John Bowler (jbowler@acorn.co.uk)