1// 2// PRCurvesPath.m 3// PRICE 4// 5// Created by Riccardo Mottola on Thu 11 August 2011. 6// Copyright 2011-2014 Riccardo Mottola. All rights reserved. 7// 8// This application is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 9// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 10 11#import "PRCurvesPath.h" 12#import <AppKit/NSColor.h> 13 14@implementation PRCurvesPath 15 16- (id)init 17{ 18 self = [super init]; 19 if(self) 20 { 21 isEditing = YES; 22 } 23 return self; 24} 25 26-(void)stroke 27{ 28 unsigned i; 29 30 [super stroke]; 31 32 if (isEditing) 33 for (i = 0; i < [self elementCount]; i++) 34 { 35 NSPoint cp[3]; 36 NSBezierPathElement pe; 37 NSRect cpRect; 38 39 pe = [self elementAtIndex: i associatedPoints: cp]; 40 41 if (pe == NSMoveToBezierPathElement) 42 { 43 [[NSColor purpleColor] set]; 44 cpRect = NSMakeRect(cp[0].x - 1, cp[0].y - 1, 4, 4); 45 [NSBezierPath fillRect: cpRect]; 46 } 47 else if (pe == NSCurveToBezierPathElement) 48 { 49 [[NSColor orangeColor] set]; 50 cpRect = NSMakeRect(cp[0].x - 1, cp[0].y - 1, 4, 4); 51 [NSBezierPath fillRect: cpRect]; 52 [[NSColor orangeColor] set]; 53 cpRect = NSMakeRect(cp[1].x - 1, cp[1].y - 1, 4, 4); 54 [NSBezierPath fillRect: cpRect]; 55 [[NSColor purpleColor] set]; 56 cpRect = NSMakeRect(cp[2].x - 1, cp[2].y - 1, 4, 4); 57 [NSBezierPath fillRect: cpRect]; 58 } 59 60 } 61 62} 63 64-(BOOL)isEditing; 65{ 66 return isEditing; 67} 68 69-(void)setIsEditing: (BOOL)flag 70{ 71 isEditing = flag; 72} 73 74-(NSPoint)blackPoint 75{ 76 NSPoint cp[3]; 77 NSPoint p; 78 NSBezierPathElement pe; 79 80 pe = [self elementAtIndex: 0 associatedPoints: cp]; 81 p = cp[0]; 82 NSLog(@"calculated black point: %f", p.x); 83 // ATTENTION: this is really true only for the simple S curve 84 return p; 85} 86 87-(NSPoint)whitePoint 88{ 89 NSPoint cp[3]; 90 NSPoint p; 91 NSBezierPathElement pe; 92 93 pe = [self elementAtIndex:[self elementCount]-1 associatedPoints: cp]; 94 p = NSZeroPoint; 95 if (pe == NSMoveToBezierPathElement) 96 p = cp[0]; 97 else if (pe == NSLineToBezierPathElement) 98 p = cp[0]; 99 else if (pe == NSCurveToBezierPathElement) 100 p = cp[2]; 101 102 NSLog(@"calculated white point: %f", p.x); 103 return p; 104} 105 106-(NSArray *)values 107{ 108 NSBezierPath *tp; 109 NSBezierPath *fp; 110 unsigned i, j; 111 NSPoint *yVals; 112 unsigned valsCount; 113 NSMutableArray *f; 114 unsigned minX, maxX; 115 float lastY; 116 117 118 tp = [NSBezierPath bezierPath]; 119 [tp appendBezierPath:(NSBezierPath *)self]; 120 [tp setFlatness: 1.0]; 121 fp = [tp bezierPathByFlatteningPath]; 122 123 valsCount = [fp elementCount]; 124 yVals = calloc(valsCount, sizeof(NSPoint)); 125 if (yVals == NULL) 126 return nil; 127 128 f = [[NSMutableArray alloc] initWithCapacity: UCHAR_MAX]; 129 for (i = 0; i < valsCount; i++) 130 { 131 NSBezierPathElement pe; 132 NSPoint cp[3]; 133 134 pe = [fp elementAtIndex: i associatedPoints: cp]; 135 136 yVals[i] = cp[0]; 137 } 138 139 minX = floor(yVals[0].x); 140 maxX = floor(yVals[valsCount].x); 141 142 for (i = 0; i < minX; i++) 143 [f addObject: [NSNumber numberWithFloat: yVals[0].y]]; 144 145 146 for (j = 0; j < valsCount; j++) 147 { 148 unsigned k, l; 149 float y1, y2; 150 151 /* find estimation interval (k) and begin/end values y1 y2 */ 152 y1 = yVals[j].y; 153 154 l = i; 155 k = i; 156 157 if (j+1 < valsCount) 158 { 159 while (k < floor(yVals[j+1].x)) 160 k++; 161 y2 = yVals[j+1].y; 162 } 163 else 164 { 165 y2 = y1; 166 k++; 167 } 168 169// NSLog(@"%d block %d-%d, y1-y2 %f-%f", j, l, k, y1, y2); 170 for (; i < k; i++) 171 { 172 float a; 173 174 a = (float)(i-l)/(k-l); 175// NSLog(@"a: %f", a); 176 [f addObject: [NSNumber numberWithFloat: (y1 + (y2-y1)*a)]]; 177 } 178 } 179 180 lastY = [[f objectAtIndex: [f count]-1] floatValue]; 181 182 for (; i <= UCHAR_MAX; i++) 183 [f addObject: [NSNumber numberWithFloat: lastY]]; 184 185 free(yVals); 186 187 return f; 188} 189 190-(void)move: (NSPoint)p1 toPoint:(NSPoint)p2 191{ 192 unsigned i; 193 NSLog (@"move %f %f %f %f", p1.x, p1.y, p2.x, p2.y); 194 for (i = 0; i < [self elementCount]; i++) 195 { 196 NSPoint cp[3]; 197 NSBezierPathElement pe; 198 NSRect cpRect; 199 200 pe = [self elementAtIndex: i associatedPoints: cp]; 201 if (pe == NSMoveToBezierPathElement) 202 { 203 cpRect = NSMakeRect(cp[0].x - 1, cp[0].y - 1, 4, 4); 204 if (NSPointInRect(p1, cpRect)) 205 { 206 cp[0] = p2; 207 } 208 } 209 else if (pe == NSCurveToBezierPathElement) 210 { 211 cpRect = NSMakeRect(cp[0].x - 1, cp[0].y - 1, 4, 4); 212 if(NSPointInRect(p1, cpRect)) 213 cp[0] = p2; 214 cpRect = NSMakeRect(cp[1].x - 1, cp[1].y - 1, 4, 4); 215 if (NSPointInRect(p1, cpRect)) 216 cp[1] = p2; 217 cpRect = NSMakeRect(cp[2].x - 1, cp[2].y - 1, 4, 4); 218 if(NSPointInRect(p1, cpRect)) 219 cp[2] = p2; 220 } 221 [self setAssociatedPoints:cp atIndex:i]; 222 } 223} 224 225-(BOOL)pointOnControlHandle:(NSPoint)p; 226{ 227 unsigned i; 228 BOOL hit; 229 230 hit = NO; 231 for (i = 0; i < [self elementCount]; i++) 232 { 233 NSPoint cp[3]; 234 NSBezierPathElement pe; 235 NSRect cpRect; 236 237 pe = [self elementAtIndex: i associatedPoints: cp]; 238 239 if (pe == NSMoveToBezierPathElement) 240 { 241 cpRect = NSMakeRect(cp[0].x - 1, cp[0].y - 1, 4, 4); 242 hit |= NSPointInRect(p, cpRect); 243 } 244 else if (pe == NSCurveToBezierPathElement) 245 { 246 cpRect = NSMakeRect(cp[0].x - 1, cp[0].y - 1, 4, 4); 247 hit |= NSPointInRect(p, cpRect); 248 cpRect = NSMakeRect(cp[1].x - 1, cp[1].y - 1, 4, 4); 249 hit |= NSPointInRect(p, cpRect); 250 cpRect = NSMakeRect(cp[2].x - 1, cp[2].y - 1, 4, 4); 251 hit |= NSPointInRect(p, cpRect); 252 } 253 } 254 return hit; 255} 256 257 258@end 259