ilteris kaplan blog

Archive of blog posts since 2005

April 5, 2008

Wiki

Buffered Lines

#wiki

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