This is CompositeView.m in view mode; [Download] [Up]
// CompositeView implements a view with three horizontal, equal-sized areas. // The left-most area is the "source," the middle area is the "destination," // and the right-most area is the "result." CompositeView assures that the // contents of the result area is always generated by compositing the other // two areas using the compositing mode set in the setOperator: method. // It is also possible to change the contents, color, and alpha of the // source and destination areas; see the methods setSourceGray:, // setSourceAlpha:, etc. // CompositeView written by Bruce Blumberg and Ali Ozer, NeXT Developer Support #import "CompositeView.h" #import <appkit/Bitmap.h> #import <appkit/Control.h> #import <appkit/Matrix.h> #import <appkit/Window.h> #import <dpsclient/wraps.h> @implementation CompositeView // The possible draw modes for the source. // In this version, only TRIANGLE is implemented. #define TRIANGLE 0 #define CIRCLE 1 #define DIAMOND 2 #define HEART 3 #define FLOWER 4 // newFrame creates the view, initializes the rectangles that define the // three areas described above, and creates the bitmaps used for rendering the // source and destination bitmaps. +newFrame:(const NXRect *)tF { // Create the view self = [super newFrame:tF]; // EXERCISE: Make rectangles for source, destination and result. // You'll need to initialize the three rectangles (sRect, dRect, rRect) // so that they define the three areas in the view where the source, // destination, and result images will appear... // Create bitmap for source image. Bitmaps are flipped by default; // make sure we make ours not-flipped. source = [Bitmap newSize:sRect.size.width :sRect.size.height type:NX_UNIQUEBITMAP]; [source setFlip:NO]; // EXERCISE: Now create bitmap for the destination image... // Set the default operator and source picture. Also set default // gray and alpha values. You will of course have to make sure // the sliders in your Interface Builder window have the same values. // (This is a problem; can you see a way to fix it?) operator = NX_COPY; sourcePicture = TRIANGLE; sourceGray = 0.333; // dark gray destGray = 0.666; // light gray sourceAlpha = 1.0; // opaque destAlpha = 1.0; // opaque // Create the bitmap images using the initial values set above [self drawSource]; [self drawDestination]; return self; } // drawSource creates the source image in the source bitmap. Note that // drawSource does not render in the view; it renders in the bitmap only. -drawSource { [source lockFocus]; PScompositerect (0.0, 0.0, sRect.size.width, sRect.size.height, NX_CLEAR); PSsetgray(sourceGray); PSsetalpha(sourceAlpha); PSnewpath(); switch (sourcePicture) { case TRIANGLE: PSmoveto (0.0, 0.0); PSlineto (0.0, sRect.size.height); PSlineto (sRect.size.width, sRect.size.height); break; // // EXERCISE: Add code to draw the other images (defined above). // You might want to use the demo programs Draw and/or Yap if the idea // of hacking PostScript doesn't appeal to you. // default: break; } PSclosepath(); PSfill(); [source unlockFocus]; return self; } // drawDestination creates the destination image in the destination bitmap. // Like drawSource, drawDestination only draws in the bitmap, not the view. -drawDestination { // EXERCISE: drawDestination needs to be written; it draws the destination // image in the destination bitmap. This method is very similar to // drawSource, except it needs to draw a triangle oriented differently. // drawDestination also does not need to draw the other images (just // a triangle is enough). return self; } // setSourcePicture allows setting the picture to be drawn in the source // bitmap. Buttons connected to this method should have tags that are // set to the various possible pictures (see the "#define"s, above). // // After setting the sourcePicture instance variable, setSourcePicture redraws // the bitmap and updates the view to reflect the new configuration. // EXERCISE: Make setSourcePicture do what the comment above says it should do. // Of course, the harder problem is actually creating the different pictures. -setSourcePicture:(id)ctl { return self; } // The following four methods set the color parameters and update // the source or destination bitmaps and the view to reflect the change. // // EXERCISE: You will need to fill in the methods to set the alpha // values for the source and the destination. (They'll probably look very // similar to the following two...) -setSourceGray:(id)ctl { sourceGray = [ctl floatValue]; [self drawSource]; [self display]; return self; } -setDestGray:(id)ctl { destGray = [ctl floatValue]; [self drawDestination]; [self display]; return self; } - setSourceAlpha:(id)ctl { return self; } - setDestAlpha:(id)ctl { return self; } // The operator method returns the operator currently in use. -(int)operator {return operator;} // setOperator sets the operator to be used in the compositing operations // and updates the view to reflect the change. Note that setOperator needs // to be connected to a row of buttons. -setOperator:(id)sender { switch ([sender selectedRow]) { case 0: operator = NX_COPY; break; case 1: operator = NX_CLEAR; break; case 2: operator = NX_SOVER; break; case 3: operator = NX_DOVER; break; case 4: operator = NX_SIN; break; case 5: operator = NX_DIN; break; case 6: operator = NX_SOUT; break; case 7: operator = NX_DOUT; break; case 8: operator = NX_SATOP; break; case 9: operator = NX_DATOP; break; case 10: operator = NX_XOR; break; case 11: operator = NX_PLUSD; break; case 12: operator = NX_PLUSL; break; default: break; } [self display]; return self; } // drawSelf:: simply redisplays the contents of the view. The source and // destination rectangles are updated from the bitmaps while the result // rectangle is created by compositing the two bitmaps. -drawSelf:(NXRect *)r :(int) count { // Erase the whole view NXEraseRect(&bounds); // Draw the source bitmap and then frame it with black [source composite:NX_COPY toPoint:&sRect.origin]; PSsetgray(NX_BLACK); NXFrameRect(&sRect); // Draw the destination bitmap and frame it with black [destination composite:NX_COPY toPoint:&dRect.origin]; PSsetgray(NX_BLACK); NXFrameRect(&dRect); // And now create the destination image and frame it with black as well [destination composite:NX_COPY toPoint:&rRect.origin]; [source composite:operator toPoint:&rRect.origin]; PSsetgray(NX_BLACK); NXFrameRect(&rRect); return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.