1//
2//  PXEllipseTool.m
3//  Pixen-XCode
4//
5//  Created by Ian Henderson on Wed Mar 10 2004.
6//  Copyright (c) 2004 Open Sword Group. All rights reserved.
7//
8
9#import "PXCanvasController.h"
10#import "PXCanvas.h"
11#import "PXEllipseTool.h"
12#import "PXEllipseToolPropertiesView.h"
13
14
15@implementation PXEllipseTool
16
17- (NSString *)name
18{
19	return NSLocalizedString(@"ELLIPSE_NAME", @"Ellipse Tool");
20}
21
22- actionName
23{
24    return NSLocalizedString(@"ELLIPSE_ACTION", @"Drawing Ellipse");
25}
26
27- init
28{
29	[super init];
30	propertiesView = [[PXEllipseToolPropertiesView alloc] init];
31	return self;
32}
33
34- (void)mouseDownAt:(NSPoint)aPoint fromCanvasController:controller
35{
36    //origin = aPoint;
37    [super mouseDownAt:aPoint fromCanvasController:controller];
38}
39
40- (void)drawPointsAddingToArray:(NSMutableArray *)points ifTracking:(BOOL)tracking withX:(int)x y:(int)y cx:(int)cx cy:(int)cy evenWidth:(BOOL)evenWidth evenHeight:(BOOL)evenHeight borderWidth:(int)borderWidth inCanvas:canvas goingHorizontally:(BOOL)horiz
41{
42    int cWidth;
43    for (cWidth = 0; cWidth < borderWidth; cWidth++) {
44		int dx = x;
45		int dy = y;
46		if (horiz) {
47			dx -= cWidth;
48		} else {
49			dy -= cWidth;
50		}
51		int cxp;
52		int cxn;
53		int cyp;
54		int cyn;
55		cxp = cx-evenWidth;
56		cxn = cx;
57		cyp = cy-evenHeight;
58		cyn = cy;
59		NSPoint p1 = NSMakePoint(cxp+dx, cyp+dy);
60		NSPoint p2 = NSMakePoint(cxp+dx, cyn-dy);
61		NSPoint p3 = NSMakePoint(cxn-dx, cyp+dy);
62		NSPoint p4 = NSMakePoint(cxn-dx, cyn-dy);
63		if (tracking) {
64			[points addObject:NSStringFromPoint(p1)];
65			[points addObject:NSStringFromPoint(p2)];
66			[points addObject:NSStringFromPoint(p3)];
67			[points addObject:NSStringFromPoint(p4)];
68		}
69		[self drawPixelAtPoint:p1 inCanvas:canvas];
70		[self drawPixelAtPoint:p2 inCanvas:canvas];
71		[self drawPixelAtPoint:p3 inCanvas:canvas];
72		[self drawPixelAtPoint:p4 inCanvas:canvas];
73    }
74}
75
76- (NSArray *)plotEllipseInscribedInRect:(NSRect)bound withLineWidth:(int)borderWidth trackingPoints:(BOOL)tracking inCanvas:canvas
77{
78    NSMutableArray *points = [NSMutableArray array];
79    int xRadius = bound.size.width/2, yRadius = bound.size.height/2;
80    if (xRadius < 1) {
81		xRadius = 1;
82    }
83    if (yRadius < 1) {
84		yRadius = 1;
85    }
86    int cx = bound.origin.x + xRadius, cy = bound.origin.y + yRadius;
87    int twoASquared = 2 * xRadius * xRadius;
88    int twoBSquared = 2 * yRadius * yRadius;
89    int x = xRadius;
90    int y = 0;
91    int xChange = yRadius * yRadius * (1 - 2*xRadius);
92    int yChange = xRadius * xRadius;
93    int error = 0;
94    int stoppingX = twoBSquared * xRadius;
95    int stoppingY = 0;
96	BOOL evenWidth = ((float)xRadius == bound.size.width / 2.0f);
97	BOOL evenHeight = ((float)yRadius == bound.size.height / 2.0f);
98    while (stoppingX >= stoppingY) {
99		[self drawPointsAddingToArray:points ifTracking:tracking withX:x y:y cx:cx cy:cy evenWidth:evenWidth evenHeight:evenHeight borderWidth:borderWidth inCanvas:canvas goingHorizontally:YES];
100		y++;
101		stoppingY += twoASquared;
102		error += yChange;
103		yChange += twoASquared;
104		if ((2*error + xChange) > 0) {
105			x--;
106			stoppingX -= twoBSquared;
107			error += xChange;
108			xChange += twoBSquared;
109		}
110    }
111
112    x = 0;
113    y = yRadius;
114    xChange = yRadius * yRadius;
115    yChange = xRadius * xRadius * (1 - 2*yRadius);
116    error = 0;
117    stoppingX = 0;
118    stoppingY = twoASquared * yRadius;
119
120    while (stoppingX <= stoppingY) {
121		[self drawPointsAddingToArray:points ifTracking:tracking withX:x y:y cx:cx cy:cy evenWidth:evenWidth evenHeight:evenHeight borderWidth:borderWidth inCanvas:canvas goingHorizontally:NO];
122		x++;
123		stoppingX += twoBSquared;
124		error += xChange;
125		xChange += twoBSquared;
126		if ((2*error + yChange) > 0) {
127			y--;
128			stoppingY -= twoASquared;
129			error += yChange;
130			yChange += twoASquared;
131		}
132    }
133    return points;
134}
135
136- (void)drawPixelAtPoint:(NSPoint)aPoint withColor:(NSColor *)specialColor inCanvas:aCanvas //should probably be put into PXPencilTool
137{
138    [self drawWithOldColor:[aCanvas
139colorAtPoint:aPoint] newColor:specialColor atPoint:aPoint inLayer:[aCanvas activeLayer] ofCanvas:aCanvas];
140}
141
142- (void)plotFilledEllipseInscribedInRect:(NSRect)bound withLineWidth:(int)borderWidth withFillColor:(NSColor *)fillColor inCanvas:canvas
143{
144    NSArray *points = [self plotEllipseInscribedInRect:(NSRect)bound withLineWidth:borderWidth trackingPoints:YES inCanvas:canvas];
145    NSEnumerator *pointEnumerator = [points objectEnumerator];
146    id start, end;
147    NSPoint startPoint, endPoint;
148    NSColor *prevColor = [[[self color] retain] autorelease];
149	[self setColor:fillColor];
150	while ((start = [pointEnumerator nextObject]) && (end = [pointEnumerator nextObject])) {
151		startPoint = NSPointFromString(start);
152		endPoint = NSPointFromString(end);
153		while ([points containsObject:NSStringFromPoint(startPoint)]) {
154			startPoint.y--;
155		}
156		startPoint.y++;
157		while ([points containsObject:NSStringFromPoint(endPoint)]) {
158			endPoint.y++;
159		}
160		if (startPoint.y > endPoint.y) {
161			[self drawLineFrom:startPoint to:endPoint inCanvas:canvas];
162		}
163	}
164	[self setColor:prevColor];
165}
166
167- (void)plotUnfilledEllipseInscribedInRect:(NSRect)bound withLineWidth:(int)borderWidth inCanvas:canvas
168{
169    [self plotEllipseInscribedInRect:(NSRect)bound withLineWidth:borderWidth trackingPoints:NO inCanvas:canvas];
170}
171
172- (NSRect)getEllipseBoundFromdrawFromPoint:(NSPoint)origin toPoint:(NSPoint)aPoint
173{
174    NSPoint start = origin;
175    NSPoint end = aPoint;
176    if (aPoint.x < start.x)
177    {
178		start.x = aPoint.x + 1;
179		end.x = origin.x + 1;
180    }
181    if (aPoint.y < start.y)
182    {
183		start.y = aPoint.y + 1;
184		end.y = origin.y + 1;
185    }
186	return NSMakeRect(start.x, start.y, end.x - start.x, end.y - start.y);
187}
188
189- (void)finalDrawFromPoint:(NSPoint)origin toPoint:(NSPoint)aPoint inCanvas:canvas
190{
191    NSRect ellipseBound = [self getEllipseBoundFromdrawFromPoint:(NSPoint)origin toPoint:aPoint];
192    if ([propertiesView shouldFill]) {
193		[self plotFilledEllipseInscribedInRect:ellipseBound withLineWidth:[propertiesView borderWidth] withFillColor:([propertiesView shouldUseMainColorForFill]) ? [self color] : [propertiesView fillColor] inCanvas:canvas];
194    } else {
195		[self plotUnfilledEllipseInscribedInRect:ellipseBound withLineWidth:[propertiesView borderWidth] inCanvas:canvas];
196    }
197}
198- (void)drawFromPoint:(NSPoint)origin toPoint:(NSPoint)finalPoint inCanvas:canvas
199{
200    NSRect ellipseBound = [self getEllipseBoundFromdrawFromPoint:(NSPoint)origin toPoint:finalPoint];
201    [self plotUnfilledEllipseInscribedInRect:ellipseBound withLineWidth:[propertiesView borderWidth] inCanvas:canvas];
202}
203@end
204