April 5, 2008
WikiBuffered Lines
Buffered Lines
Step by Step
There are couple of important things in this code. First of all, we are using two ports and using them interchangeably! GWorldPtr is an offscreen graphics world that we create for our buffer and we do our calculations there and then copy it to an onscreen port and display this. If we look at the global variables:
WindowPtr ourWindow;
Rect windRect;
GWorldPtr ourBuffer;
we will see that we are declaring ourBuffer. This is going to be the area we are going to draw our pixels.
Another new thing is in initialization function we add two more lines:
SetRect(&windRect,0,0,640,480);
error =NewGWorld(&ourBuffer, 1, &windRect, nil, nil,0 );
// creating our offscreen buffer
// if we put 32 instead of 1, it will create 32 bit truecolor buffer.
if (error != noErr ) ExitToShell();
This makes sure we create our offscreen buffer before everything. Another difference between hello lines and this code is, in the doEventLoop we are calling DrawToBuffer and copyToWindow functions instead of drawLines function. Let’s bring up the DrawToBuffer function :
void DrawToBuffer(void) {
// this is where we actually draw our geometry
long y;
Point mousepoint;
count ++ ; // increment the global variable count by 1
count = count % 10; // in lingo : count = count mod 10 , (if its greater than 9 it goes down to 0)
GetMouse(&mousepoint); // put the mouse position into a point variable
SetGWorld(ourBuffer,nil); // set our buffer as the "port" for future drawing , if we don't do this the default will be to draw directly to our window which will create a flicker.
EraseRect(&windRect); // erasing(to white) the content of our buffer which removes the previous drawings
for( y=1;y<mousepoint.v;y++){
int randX = ourRandom(-mousepoint.h,mousepoint.h);
int randY = ourRandom(-mousepoint.h,mousepoint.h);;
MoveTo(mousepoint.h,mousepoint.v); // Move the position of the "pen" this does not leave any mark
LineTo(mousepoint.h+randX,mousepoint.v+randY);
}
}
Here we are declaring two important variables. One is y which is going to be the holder for our for loop. mousepoint is a pointer which we will assign to mouse locations in the next few lines. GetMouse(&mousepoint). We should set our buffer as the port for drawing. Else the drawing will be on the recent port that has been declared. We are clearing the contents of the buffer next line. Our drawing routine is in the for loop. It is getting values instantly and continously in this for loop through the help of random functions we have created next:
int ourRandom( int min, int max ) {// method that returns a random number between min and max
return( (Random()+32768) /((32768*2/) (max-min)))+ min;
}
And then there is another major function which we will copy our contents from our buffer to the window.
void CopyToWindow (void){ // copy all our buffer to the window, completely replacing everything that was there
Rect sourceRect,destRect;
SetPortWindowPort(ourWindow);
GetPortBounds( GetWindowPort(ourWindow), &destRect );
GetPortBounds( ourBuffer, &sourceRect );
CopyBits( GetPortBitMapForCopyBits( ourBuffer ), GetPortBitMapForCopyBits(GetWindowPort(ourWindow)), &sourceRect, &destRect, srcCopy, NULL );
// copy buffer from this first argument to the second argument.
}
Source Code
void Initialize(void); // function prototypes
void DrawLine( void );
void doEventLoop( void );
void DrawToBuffer(void);
void CopyToWindow (void);
void ourLine(int left,int top,int right ,int bottom);
void ourRect(int left,int top,int right ,int bottom);
void ourFramedRect(int left,int top,int right ,int bottom);
void ourOval(int left,int top,int right ,int bottom);
void ourFramedOval(int left,int top,int right ,int bottom);
int ourRandom( int min, int max );
//globals
WindowPtr ourWindow;
Rect windRect;
GWorldPtr ourBuffer;
int count=0;
void DrawToBuffer(void)
// this is where the interesting stuff happens, this is where we actually draw our geometry
{
long y;
Point mousepoint;
count ++ ; // increment the global variable count by 1
count = count % 10; // in lingo : count = count mod 10 , (if its greater than 9 it goes down to 0)
GetMouse(&mousepoint); // put the mouse position into a point variable
SetGWorld(ourBuffer,nil);* set our buffer as the "port" for future drawing , if we don't do this * the default will be to draw directly to our window which will create a flicker.
EraseRect(&windRect); // erasing(to white) the content of our buffer which removes the previous drawings
for( y=1;y<mousepoint.v;y++){
int randX = ourRandom(-mousepoint.h,mousepoint.h);
int randY = ourRandom(-mousepoint.h,mousepoint.h);;
MoveTo(mousepoint.h,mousepoint.v); // Move the position of the "pen" this does not leave any mark
LineTo(mousepoint.h+randX,mousepoint.v+randY);
}
}
void CopyToWindow (void){ // copy all our buffer to the window, completely replaceing
// everything that was there
Rect sourceRect,destRect;
SetPortWindowPort(ourWindow);
GetPortBounds( GetWindowPort(ourWindow), &destRect );
GetPortBounds( ourBuffer, &sourceRect );
CopyBits( GetPortBitMapForCopyBits( ourBuffer ), GetPortBitMapForCopyBits(GetWindowPort(ourWindow)),
&sourceRect, &destRect, srcCopy, NULL );
// copy buffer from this first argument to the second argument.
}
void main( void )
{
Initialize();
doEventLoop();
}
void Initialize(void){
OSErr error;
SetRect(&windRect,100,100,740,580);
InitCursor();
ourWindow = NewCWindow( 0L, &windRect, "\pBuffered Lines", true, noGrowDocProc,(WindowPtr)-1L, true, 0L );
if ( ourWindow == nil ) ExitToShell();
ShowWindow( ourWindow );
SetPortWindowPort( ourWindow );
SetRect(&windRect,0,0,640,480);
error =NewGWorld(&ourBuffer, 1, &windRect, nil, nil,0 ); // creating our offscreen buffer
// if we put 32 instead of 1, it will create 32 bit truecolor buffer.
if (error != noErr ) ExitToShell();
}
/*************** The Event Loop ***************/
void doEventLoop()
{
EventRecord anEvent;
WindowPtr evtWind;
short clickArea;
Rect screenRect;
Point thePoint;
for (;;) // repeat forever
{
if (WaitNextEvent( everyEvent, &anEvent, 0, nil ))
{
if (anEvent.what == mouseDown)
{
clickArea = FindWindow( anEvent.where, &evtWind );
if (clickArea == inDrag)
{
GetRegionBounds( GetGrayRgn(), &screenRect );
DragWindow( evtWind, anEvent.where, &screenRect );
}
else if (clickArea == inContent)
{
if (evtWind != FrontWindow())
SelectWindow( evtWind );
else
{
thePoint = anEvent.where;
GlobalToLocal( &thePoint );
//Handle click in window content here
}
}
else if (clickArea == inGoAway)
if (TrackGoAway( evtWind, anEvent.where ))
return;
}
}
DrawToBuffer(); // after checking for various events we call our drawing finctions
CopyToWindow();
}
}
void ourLine(int left,int top,int right ,int bottom){ // method for drawing lines arguments are left, top, right , bottom
MoveTo(left,top); // move the pen to the starting position of the line
LineTo(right,bottom); // draw line to the position specified in the current port
}
void ourRect(int left,int top,int right ,int bottom){ // method for drawing filled rectangles, arguments are left, top, right , bottom
Rect theRect;
long temp;
if (left > right) {temp = left; left = right ; right = temp;} // making sure that the left is smaller than right and bottom biger than top
if (top > bottom) {temp = top; top = bottom ; bottom = temp;} // otherwise it will not draw.
SetRect(&theRect,left,top,right,bottom); // seting a Rect variable to hold the coordinates of the rectangle
PaintRect(&theRect); // painting the rectangle to the current port
}
void ourFramedRect(int left,int top,int right ,int bottom){ // method for drawing hollow rectangles, arguments are left, top, right , bottom
Rect theRect;
long temp;
if (left > right) {temp = left; left = right ; right = temp;} // same as ourRect() only calls FrameRect() instead of PaintRect
if (top > bottom) {temp = top; top = bottom ; bottom = temp;}
SetRect(&theRect,left,top,right,bottom);
FrameRect(&theRect);
}
void ourOval(int left,int top,int right ,int bottom){ //method for drawing filled ovals, arguments are left, top, right , bottom
Rect theRect;
long temp;
if (left > right) {temp = left; left = right ; right = temp;}
if (top > bottom) {temp = top; top = bottom ; bottom = temp;} // same as ourRect() only calls PaintOval() instead of PaintRect
SetRect(&theRect,left,top,right,bottom);
PaintOval(&theRect);
}
void ourFramedOval(int left,int top,int right ,int bottom){ // method for drawing hollow ovals, arguments are left, top, right , bottom
Rect theRect;
long temp;
if (left > right) {temp = left; left = right ; right = temp;}
if (top > bottom) {temp = top; top = bottom ; bottom = temp;} // same as ourRect() only calls FrameOval() instead of PaintRect
SetRect(&theRect,left,top,right,bottom);
FrameOval(&theRect);
}
int ourRandom( int min, int max ){ // method that returns a random number between min and max
return( (Random()+32768) /((32768*2/) (max-min)))+ min;
}
Continue Reading
Back to Archive