/*	MiscHitPath.m

	Copyright 1996 Uwe Hoffmann.

	This notice may not be removed from this source code.
	The use and distribution of this software is governed by the
	terms of the MiscKit license agreement.  Refer to the license
	document included with the MiscKit distribution for the terms.

	Version 2 (August 1996)
*/

#import <Foundation/Foundation.h>
#import <AppKit/dpsOpenStep.h>

#import "MiscHitPath.h"
#import "Miscuserpath.h"

@implementation MiscHitPath
/*"MiscHitPath is a subclass of MiscUserPath and manages a user path representing a square, the %{hit detection square}.
Instances of MiscHitPath are used for hit detection of an MiscUserPath instance 
(for example when a #mouseDown: event occured in a drawing view).
A hit detection is made by sending an instance of MiscHitPath the message #hit:path: with the hit operation and the user path
to be detected as arguments. The message returns YES if the hit path and the user path intersect.
For example the #mouseDown: method of a view first moves the hit path to the point where the mouseDown event occured with the
message #moveTo:, if the view is scaled scales the hit path with #scaleWith: to reflect the original square width and then sends #hit:path:. 


An MiscHitPath instance minimizes the communication with the window server by first checking if the bounding rectangles of the
user path and the hit path intersect and only if they do sends the two paths with one of the operators %{dps_inufill,
dps_inueofill or dps_inustroke} to the window server."*/

 
- initWithWidth:(float)width
/*"Initializes a newly allocated instance of MiscHitPath with the width width of the hit detection square.
This is the designated initializer of this class"*/
{  
   [super initCountParams:8 countOps:4];
   [self resetFill];
   [self moveto:0 :0];
   [self rlineto:0 :0];
   [self rlineto:0 :0];
   [self rlineto:0 :0];
   [self closepath];
   hitWidth = width;
   return self;
}

- init
{
	return [self initWithWidth:4.0];
}
   
- (void)moveTo:(NSPoint)p
/*"Moves the receiver to point p. The point p will be in the middle of the hit detection square."*/
{
   	bbox[0] = floor(p.x - hitWidth / 2);
   	bbox[1] = floor(p.y - hitWidth / 2);
   	bbox[2] = ceil(p.x + hitWidth / 2);
   	bbox[3] = ceil(p.y + hitWidth / 2);
   	params[0] = p.x - hitWidth / 2;
   	params[1] = p.y - hitWidth / 2;
   	params[3] = hitWidth;
   	params[4] = hitWidth;
   	params[7] = - hitWidth;
}

- (BOOL)hit:(int)op path:(MiscUserPath *)aPath
/*"Performs a hit detection on path aPath. Returns YES if the path of the receiver and aPath intersect.
op should be one of %{dps_inufill, dps_inueofill or dps_inustroke}."*/
{
   	int hit = NO;

	if(NSIntersectsRect([self bounds], [aPath bounds])){
		switch(op){
			case dps_inufill: 
   				MiscPSWHitFill(bboxParams,lengthParams + 4,bboxOps,lengthOps + 2,
   				[aPath bboxParams],[aPath lengthParams] + 4,[aPath bboxOps], [aPath lengthOps] + 2,&hit);
				break;
			case dps_inustroke:
				MiscPSWHitStroke(bboxParams,lengthParams + 4,bboxOps,lengthOps + 2,
   				[aPath bboxParams],[aPath lengthParams] + 4,[aPath bboxOps], [aPath lengthOps] + 2,&hit);
				break;
			case dps_inueofill:
				MiscPSWHitEOFill(bboxParams,lengthParams + 4,bboxOps,lengthOps + 2,
   				[aPath bboxParams],[aPath lengthParams] + 4,[aPath bboxOps], [aPath lengthOps] + 2,&hit);
				break;
			default:
				break;
		}
	}
   	return (BOOL)hit;
}

- (void)scaleWith:(float)aScale
/*"Scales the hit path with aScale. The middle of the hit detection square stays the same."*/
{
	NSPoint p;
	
	p.x = bbox[0] + (bbox[2] - bbox[0]) / 2;
	p.y = bbox[1] + (bbox[3] - bbox[1]) / 2;
   	hitWidth *= aScale;
   	bbox[0] = floor(p.x - hitWidth / 2);
   	bbox[1] = floor(p.y - hitWidth / 2);
   	bbox[2] = ceil(p.x + hitWidth / 2);
   	bbox[3] = ceil(p.y + hitWidth / 2);
   	params[0] = p.x - hitWidth / 2;
   	params[1] = p.y - hitWidth / 2;
   	params[3] = hitWidth;
   	params[4] = hitWidth;
   	params[7] = - hitWidth;
}

- (float)width
/*"Returns the width of the hit detection square."*/
{
	return hitWidth;
}

- (void)setWidth:(float)width
/*"Sets the width of the hit detection square to width. The middle of the hit detection square stays the same."*/
{
	NSPoint p;
	
	p.x = bbox[0] + (bbox[2] - bbox[0]) / 2;
	p.y = bbox[1] + (bbox[3] - bbox[1]) / 2;
	hitWidth = width;
	bbox[0] = floor(p.x - hitWidth / 2);
   	bbox[1] = floor(p.y - hitWidth / 2);
   	bbox[2] = ceil(p.x + hitWidth / 2);
   	bbox[3] = ceil(p.y + hitWidth / 2);
   	params[0] = p.x - hitWidth / 2;
   	params[1] = p.y - hitWidth / 2;
   	params[3] = hitWidth;
   	params[4] = hitWidth;
   	params[7] = - hitWidth;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
   	[super encodeWithCoder:coder];
   	[coder encodeValueOfObjCType:"i" at:&hitWidth];
}

- initWithCoder:(NSCoder *)coder
{
   	self = [super initWithCoder:coder];
   	[coder decodeValueOfObjCType:"i" at:&hitWidth];
   	return self;
}
             
@end
