├── ArrowDrawing.jpeg ├── ESCursors-screenshot.png ├── ESCursors.h ├── ESCursors.m ├── License.txt └── Readme.markdown /ArrowDrawing.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssp/ESCursors/3ff10db7dd9d84cd638d1723cd6f7c9852df5f58/ArrowDrawing.jpeg -------------------------------------------------------------------------------- /ESCursors-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssp/ESCursors/3ff10db7dd9d84cd638d1723cd6f7c9852df5f58/ESCursors-screenshot.png -------------------------------------------------------------------------------- /ESCursors.h: -------------------------------------------------------------------------------- 1 | /* 2 | ESCursors.h 3 | 4 | Copyright 2008-2017 Sven-S. Porst, earthlingsoft: https://earthlingsoft.net/ssp/ 5 | Some rights reserved: https://opensource.org/licenses/mit 6 | Available at: https://github.com/ssp/ESCursors 7 | 8 | v1 (2008-07-27) Initial release. 9 | 10 | ******************************************************************** 11 | 12 | ESCursors provides a wide variety of arrow cursors. 13 | 14 | In particular it provides rotated versions of cursors which NSCursor 15 | does not provide. 16 | 17 | Try out our Symmetries application, available at 18 | http://earthlingsoft.net/Symmetries to see those cursors in action. 19 | 20 | For each cursor type there is a class method providing the cursor 21 | which calls a helper method that creates the Bézier path for the 22 | shape, draws it at the right size in black with a white border, 23 | rotated and scaled to the desired size and returns it as an NSCursor. 24 | */ 25 | 26 | #import 27 | 28 | 29 | @interface ESCursors : NSObject { 30 | } 31 | 32 | 33 | #pragma mark CURVED CURSORS 34 | 35 | /* 36 | CURVED CURSORS 37 | 38 | A cross shaped cursor whose horizontal stroke is slightly curved to the bottom. 39 | The options specify which of the arrows should exist, not all of them should be NO. 40 | 41 | The arrow heads in these cursors overlap which gives the right look at small size but looks bad at huge sizes. 42 | 43 | The third variant with an 'underlay' lets you pass an image that is drawn beneath the cursor image. 44 | */ 45 | 46 | + (NSBezierPath *) curvedCursorBezierPathWithRightArrow:(BOOL) rightArrow 47 | upArrow:(BOOL) upArrow 48 | leftArrow:(BOOL) leftArrow 49 | downArrow:(BOOL) downArrow 50 | forAngle:(CGFloat) angle; 51 | 52 | + (NSCursor *) curvedCursorWithRightArrow:(BOOL) rightArrow 53 | upArrow:(BOOL) upArrow 54 | leftArrow:(BOOL) leftArrow 55 | downArrow:(BOOL) downArrow 56 | forAngle:(CGFloat) angle 57 | size:(CGFloat) size; 58 | 59 | + (NSCursor *) curvedCursorWithRightArrow:(BOOL) rightArrow 60 | upArrow:(BOOL) upArrow 61 | leftArrow:(BOOL) leftArrow 62 | downArrow:(BOOL) downArrow 63 | forAngle:(CGFloat) angle 64 | size:(CGFloat) size 65 | underlay:(NSImage*) underlay; 66 | 67 | 68 | 69 | #pragma mark STRAIGHT CURSORS 70 | 71 | /* 72 | STRAIGHT CURSORS 73 | 74 | cross shaped 75 | threePronged (oriented like an upside-down T) 76 | right angle shaped (oriented like an L) 77 | straight line shaped (horizontal) 78 | semi-straight line shaped (horizontal, shorter and with a bar at the left end) 79 | */ 80 | 81 | + (NSBezierPath *) crossCursorBezierPathForAngle: (CGFloat) angle; 82 | + (NSCursor *) crossCursorForAngle: (CGFloat) angle withSize: (CGFloat) size; 83 | 84 | + (NSBezierPath *) threeProngedCursorBezierPathForAngle: (CGFloat) angle; 85 | + (NSCursor *) threeProngedCursorForAngle: (CGFloat) angle withSize: (CGFloat) size; 86 | 87 | + (NSBezierPath *) angleCursorBezierPathForAngle: (CGFloat) angle; 88 | + (NSCursor *) angleCursorForAngle: (CGFloat) angle withSize: (CGFloat) size; 89 | 90 | + (NSBezierPath *) straightCursorBezierPathForAngle: (CGFloat) angle; 91 | + (NSCursor *) straightCursorForAngle: (CGFloat) angle withSize: (CGFloat) size; 92 | 93 | + (NSBezierPath *) halfStraightCursorBezierPathForAngle: (CGFloat) angle; 94 | + (NSCursor *) halfStraightCursorForAngle: (CGFloat) angle withSize: (CGFloat) size; 95 | 96 | 97 | 98 | 99 | #pragma mark HELPER METHODS 100 | 101 | /* 102 | HELPER METHODS 103 | 104 | to do the actual drawing. 105 | */ 106 | + (NSCursor *) cursorForBezierPath:(NSBezierPath *) path 107 | withRotation:(CGFloat) angle 108 | andSize:(CGFloat) size; 109 | 110 | + (NSCursor *) cursorForBezierPath:(NSBezierPath *) path 111 | withRotation:(CGFloat) angle 112 | size:(CGFloat) size 113 | andUnderlay:(NSImage *) underlay; 114 | 115 | @end 116 | -------------------------------------------------------------------------------- /ESCursors.m: -------------------------------------------------------------------------------- 1 | // ESCursors.h 2 | // 3 | // Copyright 2008-2017 Sven-S. Porst, earthlingsoft: https://earthlingsoft.net/ssp/ 4 | // Some rights reserved: https://opensource.org/licenses/mit 5 | // Available at: https://github.com/ssp/ESCursors 6 | 7 | #import "ESCursors.h" 8 | 9 | #define ARROWSIZE 0.525 10 | #define LINETHICKNESS 0.18 11 | 12 | 13 | @implementation ESCursors 14 | 15 | #pragma mark CURVED CURSORS 16 | 17 | 18 | + (NSBezierPath *) curvedCursorBezierPathWithRightArrow:(BOOL) rightArrow upArrow:(BOOL) upArrow leftArrow:(BOOL) leftArrow downArrow: (BOOL) downArrow forAngle: (CGFloat) angle { 19 | const CGFloat handleFraction = 1.0 / 8.0; 20 | const CGFloat phi = M_PI / 20.0; 21 | NSAffineTransform * rotate = [NSAffineTransform transform]; 22 | [rotate rotateByRadians:-phi]; 23 | NSAffineTransform * rotate2 = [NSAffineTransform transform]; 24 | [rotate2 rotateByRadians:-2.0 * phi]; 25 | NSPoint pt; 26 | 27 | // left / right end points 28 | const NSPoint p1 = NSMakePoint(1.0, - sin(phi)); 29 | const NSPoint p20 = NSMakePoint(-p1.x, p1.y); 30 | 31 | // left / right arrow top corner 32 | pt = [rotate transformPoint: NSMakePoint(-ARROWSIZE, ARROWSIZE)]; 33 | const NSPoint p2 = NSMakePoint(p1.x + pt.x, p1.y + pt.y); 34 | const NSPoint p19 = NSMakePoint(-p2.x, p2.y); 35 | const NSPoint p38 = NSMakePoint(p1.x - pt.y, p1.y + pt.x); 36 | const NSPoint p21 = NSMakePoint(-p38.x, p38.y); 37 | 38 | // left/ right arrow bottom corner 39 | pt = [rotate transformPoint: NSMakePoint(0.0, -(ARROWSIZE - LINETHICKNESS))]; 40 | const NSPoint p3 = NSMakePoint(p2.x + pt.x, p2.y + pt.y); 41 | const NSPoint p18 = NSMakePoint(-p3.x, p3.y); 42 | const NSPoint p37 = NSMakePoint(p38.x - pt.x, p38.y - pt.y); 43 | const NSPoint p22 = NSMakePoint(-p37.x, p37.y); 44 | 45 | // start handles for Bezier path 46 | pt = [rotate2 transformPoint: NSMakePoint(-handleFraction, 0.0)]; 47 | const NSPoint p4 = NSMakePoint(p3.x + pt.x * 1.1, p3.y + pt.y * 1.1); 48 | const NSPoint p17 = NSMakePoint(-p4.x, p4.y); 49 | const NSPoint p36 = NSMakePoint(p37.x + pt.x * 0.9, p37.y + pt.y * 0.9); 50 | const NSPoint p23 = NSMakePoint(-p36.x, p36.y); 51 | 52 | // off centre arrive point for Bezier path 53 | const CGFloat theta = asin(LINETHICKNESS); 54 | CGFloat correction = (1 - cos(theta)); 55 | const NSPoint p7 = NSMakePoint(LINETHICKNESS, LINETHICKNESS - correction); 56 | const NSPoint p14 = NSMakePoint(-LINETHICKNESS, p7.y); 57 | const NSPoint p33 = NSMakePoint(LINETHICKNESS, - LINETHICKNESS - correction); 58 | const NSPoint p26 = NSMakePoint(-LINETHICKNESS, p33.y); 59 | 60 | // off centre arrive handles for Bezier path 61 | correction = 0.0; 62 | const NSPoint p5 = NSMakePoint(p7.x + 0.9 * handleFraction, p7.y - correction); 63 | const NSPoint p16 = NSMakePoint(- p5.x, p5.y); 64 | const NSPoint p35 = NSMakePoint(p33.x + 0.81 * handleFraction, p33.y - correction); 65 | const NSPoint p24 = NSMakePoint(-p35.x, p35.y); 66 | 67 | // central points and handles for Bezier path 68 | const NSPoint p8 = NSMakePoint(0.0, LINETHICKNESS); 69 | const NSPoint p27 = NSMakePoint(0.0, -LINETHICKNESS); 70 | const NSPoint p6 = NSMakePoint(handleFraction, LINETHICKNESS); 71 | const NSPoint p15 = NSMakePoint(-handleFraction, LINETHICKNESS); 72 | const NSPoint p34 = NSMakePoint(handleFraction, LINETHICKNESS); 73 | const NSPoint p25 = NSMakePoint(-handleFraction, LINETHICKNESS); 74 | 75 | // up arrow 76 | NSPoint upArrowPoints [6]; 77 | upArrowPoints[0] = NSMakePoint(LINETHICKNESS, 1.0 - ARROWSIZE); 78 | upArrowPoints[1] = NSMakePoint(ARROWSIZE, 1.0 - ARROWSIZE); 79 | upArrowPoints[2] = NSMakePoint(0.0, 1.0); 80 | upArrowPoints[3] = NSMakePoint(- ARROWSIZE, 1.0 - ARROWSIZE); 81 | upArrowPoints[4] = NSMakePoint(-LINETHICKNESS, 1.0 - ARROWSIZE); 82 | upArrowPoints[5] = p14; 83 | 84 | // down arrow 85 | NSPoint downArrowPoints [6]; 86 | downArrowPoints[0] = NSMakePoint(-LINETHICKNESS, -1.0 + ARROWSIZE); 87 | downArrowPoints[1] = NSMakePoint(-ARROWSIZE, -1.0 + ARROWSIZE); 88 | downArrowPoints[2] = NSMakePoint(0.0, -1.0); 89 | downArrowPoints[3] = NSMakePoint(ARROWSIZE, -1.0 + ARROWSIZE); 90 | downArrowPoints[4] = NSMakePoint(LINETHICKNESS, -1.0 + ARROWSIZE); 91 | downArrowPoints[5] = p33; 92 | 93 | // now draw the paths 94 | NSBezierPath * bP = [NSBezierPath bezierPath]; 95 | 96 | if (rightArrow) { 97 | [bP moveToPoint:p1]; 98 | [bP lineToPoint:p2]; 99 | [bP lineToPoint:p3]; 100 | if (upArrow || !leftArrow) { 101 | // we are not drawing the long curve 102 | [bP curveToPoint:p7 controlPoint1:p4 controlPoint2:p5]; 103 | } 104 | else { 105 | // we are going all the way to the left 106 | [bP curveToPoint:p8 controlPoint1:p4 controlPoint2:p6]; 107 | [bP curveToPoint:p18 controlPoint1:p15 controlPoint2:p17]; 108 | } 109 | } 110 | else { 111 | // there is no right arrow, begin at p7 112 | [bP moveToPoint:p7]; 113 | } 114 | 115 | if (upArrow) { 116 | // we are at p7 now, draw the arrow 117 | [bP appendBezierPathWithPoints:upArrowPoints count:6]; 118 | } 119 | else if (!upArrow && (!rightArrow || ! leftArrow) && !(rightArrow && leftArrow)) { 120 | // just move on in a straight line 121 | [bP lineToPoint:p14]; 122 | } 123 | // we already covered the !upArrow && leftArrow situation above 124 | 125 | 126 | if (leftArrow) { 127 | if (upArrow || (!upArrow && !rightArrow)) { 128 | // we are at p14 and draw line to the the left arrow 129 | [bP curveToPoint:p18 controlPoint1:p16 controlPoint2:p17]; 130 | } 131 | 132 | // We're at p18 now and draw the arrow tip itself 133 | [bP lineToPoint:p19]; 134 | [bP lineToPoint:p20]; 135 | [bP lineToPoint:p21]; 136 | [bP lineToPoint:p22]; 137 | 138 | if (downArrow || !rightArrow) { 139 | // we need to go to p26 140 | [bP curveToPoint:p26 controlPoint1:p23 controlPoint2:p24]; 141 | } 142 | else { 143 | // we need to stroke all the way to the right arrow 144 | [bP curveToPoint:p27 controlPoint1:p23 controlPoint2:p25]; 145 | [bP curveToPoint:p37 controlPoint1:p34 controlPoint2:p36]; 146 | } 147 | 148 | } 149 | 150 | 151 | if (downArrow) { 152 | // we are at p26 (if leftArrow) or p14 (if !leftArrow) now, insert the arrow 153 | [bP appendBezierPathWithPoints:downArrowPoints count:6]; 154 | } 155 | else { 156 | if (leftArrow) { 157 | if (!rightArrow) { 158 | // we are at p26, move to p33 159 | [bP lineToPoint:p33]; 160 | } 161 | } 162 | else { 163 | // we are at p14, stroke to p33 164 | [bP lineToPoint:p26]; 165 | [bP lineToPoint:p33]; 166 | } 167 | } 168 | 169 | if (rightArrow) { 170 | if (! (leftArrow && !downArrow)) { 171 | // we are at p33, curve to p37 172 | [bP curveToPoint:p37 controlPoint1:p35 controlPoint2:p36]; 173 | } 174 | // finishing stroke 175 | [bP lineToPoint:p38]; 176 | } 177 | // if !rightArrow we started at p7 178 | 179 | // close path to get the missing stroke 180 | [bP closePath]; 181 | 182 | return bP; 183 | } 184 | 185 | 186 | 187 | + (NSCursor *) curvedCursorWithRightArrow:(BOOL) rightArrow upArrow:(BOOL) upArrow leftArrow:(BOOL) leftArrow downArrow: (BOOL) downArrow forAngle: (CGFloat) angle size: (CGFloat) size { 188 | NSBezierPath * bP = [ESCursors curvedCursorBezierPathWithRightArrow:rightArrow upArrow:upArrow leftArrow:leftArrow downArrow:downArrow forAngle: angle]; 189 | 190 | return [ESCursors cursorForBezierPath:bP withRotation: angle andSize: size]; 191 | } 192 | 193 | 194 | + (NSCursor *) curvedCursorWithRightArrow:(BOOL) rightArrow upArrow:(BOOL) upArrow leftArrow:(BOOL) leftArrow downArrow: (BOOL) downArrow forAngle: (CGFloat) angle size: (CGFloat) size underlay:(NSImage*) underlay { 195 | NSBezierPath * bP = [ESCursors curvedCursorBezierPathWithRightArrow:rightArrow upArrow:upArrow leftArrow:leftArrow downArrow:downArrow forAngle: angle]; 196 | 197 | return [ESCursors cursorForBezierPath:bP withRotation: angle size: size andUnderlay: underlay]; 198 | } 199 | 200 | 201 | 202 | 203 | #pragma mark CROSSED CURSORS 204 | 205 | + (NSBezierPath *) crossCursorBezierPathForAngle: (CGFloat) angle { 206 | NSPoint pointArray[6]; 207 | pointArray[0] = NSMakePoint(1.0 - ARROWSIZE, ARROWSIZE); 208 | pointArray[1] = NSMakePoint(1.0 - ARROWSIZE, LINETHICKNESS); 209 | pointArray[2] = NSMakePoint(LINETHICKNESS, LINETHICKNESS); 210 | pointArray[3] = NSMakePoint(LINETHICKNESS, 1.0 - ARROWSIZE); 211 | pointArray[4] = NSMakePoint(ARROWSIZE, 1.0 - ARROWSIZE); 212 | pointArray[5] = NSMakePoint(0.0, 1.0); 213 | 214 | NSBezierPath * bP = [NSBezierPath bezierPath]; 215 | [bP moveToPoint:NSMakePoint(1.0, 0.0)]; 216 | 217 | NSAffineTransform * aT = [NSAffineTransform transform]; 218 | [aT rotateByDegrees:-90.0]; 219 | 220 | for (NSUInteger i=0; i<4; i++) { 221 | [bP appendBezierPathWithPoints:pointArray count:6]; 222 | [bP transformUsingAffineTransform:aT]; 223 | } 224 | 225 | [bP closePath]; 226 | 227 | return bP; 228 | } 229 | 230 | 231 | 232 | + (NSCursor *) crossCursorForAngle: (CGFloat) angle withSize: (CGFloat) size { 233 | NSBezierPath * bP = [ESCursors crossCursorBezierPathForAngle: angle]; 234 | 235 | return [ESCursors cursorForBezierPath:bP withRotation: angle andSize: size]; 236 | } 237 | 238 | 239 | 240 | 241 | #pragma mark THREE PRONGED CURSORS 242 | 243 | 244 | + (NSBezierPath *) threeProngedCursorBezierPathForAngle: (CGFloat) angle { 245 | NSPoint pointArray[17]; 246 | pointArray[0] = NSMakePoint(1.0 - ARROWSIZE, ARROWSIZE); 247 | pointArray[1] = NSMakePoint(1.0 - ARROWSIZE, LINETHICKNESS); 248 | pointArray[2] = NSMakePoint(LINETHICKNESS, LINETHICKNESS); 249 | pointArray[3] = NSMakePoint(LINETHICKNESS, 1.0 - ARROWSIZE); 250 | pointArray[4] = NSMakePoint(ARROWSIZE, 1.0 - ARROWSIZE); 251 | pointArray[5] = NSMakePoint(0.0, 1.0); 252 | pointArray[6] = NSMakePoint(- ARROWSIZE, 1.0 - ARROWSIZE); 253 | pointArray[7] = NSMakePoint(- LINETHICKNESS, 1.0 - ARROWSIZE); 254 | pointArray[8] = NSMakePoint(- LINETHICKNESS, LINETHICKNESS); 255 | pointArray[9] = NSMakePoint(-1.0 + ARROWSIZE, LINETHICKNESS); 256 | pointArray[10] = NSMakePoint(-1.0 + ARROWSIZE, ARROWSIZE); 257 | pointArray[11] = NSMakePoint(-1.0 , 0.0); 258 | pointArray[12] = NSMakePoint(- ARROWSIZE, - ARROWSIZE); 259 | pointArray[13] = NSMakePoint(- ARROWSIZE, - LINETHICKNESS); 260 | pointArray[14] = NSMakePoint(1.0 - ARROWSIZE, - LINETHICKNESS); 261 | pointArray[15] = NSMakePoint(1.0 - ARROWSIZE, - ARROWSIZE); 262 | pointArray[16] = NSMakePoint(1.0, 0.0); 263 | 264 | NSBezierPath * bP = [NSBezierPath bezierPath]; 265 | 266 | [bP appendBezierPathWithPoints:pointArray count:17]; 267 | [bP closePath]; 268 | 269 | return bP; 270 | } 271 | 272 | 273 | 274 | + (NSCursor *) threeProngedCursorForAngle: (CGFloat) angle withSize: (CGFloat) size { 275 | NSBezierPath * bP = [ESCursors threeProngedCursorBezierPathForAngle: angle]; 276 | 277 | return [ESCursors cursorForBezierPath: bP withRotation: angle andSize: size]; 278 | } 279 | 280 | 281 | 282 | 283 | #pragma mark ANGLE CURSORS 284 | 285 | 286 | + (NSBezierPath *) angleCursorBezierPathForAngle: (CGFloat) angle { 287 | NSPoint pointArray[12]; 288 | pointArray[0] = NSMakePoint(1.0 - ARROWSIZE, ARROWSIZE); 289 | pointArray[1] = NSMakePoint(1.0 - ARROWSIZE, LINETHICKNESS); 290 | pointArray[2] = NSMakePoint(LINETHICKNESS, LINETHICKNESS); 291 | pointArray[3] = NSMakePoint(LINETHICKNESS, 1.0 - ARROWSIZE); 292 | pointArray[4] = NSMakePoint(ARROWSIZE, 1.0 - ARROWSIZE); 293 | pointArray[5] = NSMakePoint(0.0, 1.0); 294 | pointArray[6] = NSMakePoint(- ARROWSIZE, 1.0 - ARROWSIZE); 295 | pointArray[7] = NSMakePoint(- LINETHICKNESS, 1.0 - ARROWSIZE); 296 | pointArray[8] = NSMakePoint(- LINETHICKNESS, -LINETHICKNESS); 297 | pointArray[9] = NSMakePoint(1.0 - ARROWSIZE, - LINETHICKNESS); 298 | pointArray[10] = NSMakePoint(1.0 - ARROWSIZE, - ARROWSIZE); 299 | pointArray[11] = NSMakePoint(1.0, 0.0); 300 | 301 | NSBezierPath * bP = [NSBezierPath bezierPath]; 302 | 303 | [bP appendBezierPathWithPoints:pointArray count:12]; 304 | [bP closePath]; 305 | 306 | return bP; 307 | } 308 | 309 | 310 | 311 | + (NSCursor *) angleCursorForAngle: (CGFloat) angle withSize: (CGFloat) size { 312 | NSBezierPath * bP = [ESCursors angleCursorBezierPathForAngle: angle]; 313 | 314 | return [ESCursors cursorForBezierPath: bP withRotation: angle andSize: size]; 315 | } 316 | 317 | 318 | 319 | #pragma mark STRAIGHT CURSORS 320 | 321 | + (NSBezierPath *) straightCursorBezierPathForAngle: (CGFloat) angle { 322 | NSPoint pointArray[5]; 323 | pointArray[0] = NSMakePoint(1.0 - ARROWSIZE, ARROWSIZE); 324 | pointArray[1] = NSMakePoint(1.0 - ARROWSIZE, LINETHICKNESS); 325 | pointArray[2] = NSMakePoint(-1.0 + ARROWSIZE, LINETHICKNESS); 326 | pointArray[3] = NSMakePoint(-1.0 + ARROWSIZE, ARROWSIZE); 327 | pointArray[4] = NSMakePoint(-1.0, 0.0); 328 | 329 | NSBezierPath * bP = [NSBezierPath bezierPath]; 330 | [bP moveToPoint:NSMakePoint(1.0, 0.0)]; 331 | 332 | NSAffineTransform * aT = [NSAffineTransform transform]; 333 | [aT rotateByDegrees:180.0]; 334 | 335 | [bP appendBezierPathWithPoints:pointArray count:5]; 336 | [bP transformUsingAffineTransform:aT]; 337 | [bP appendBezierPathWithPoints:pointArray count:5]; 338 | [bP closePath]; 339 | 340 | return bP; 341 | } 342 | 343 | 344 | 345 | + (NSCursor *) straightCursorForAngle: (CGFloat) angle withSize: (CGFloat) size { 346 | NSBezierPath * bP = [ESCursors straightCursorBezierPathForAngle: angle]; 347 | 348 | return [ESCursors cursorForBezierPath: bP withRotation: angle andSize: size]; 349 | } 350 | 351 | 352 | 353 | 354 | + (NSBezierPath *) halfStraightCursorBezierPathForAngle: (CGFloat) angle { 355 | NSPoint pointArray[10]; 356 | pointArray[0] = NSMakePoint(1.0 - ARROWSIZE, ARROWSIZE); 357 | pointArray[1] = NSMakePoint(1.0 - ARROWSIZE, LINETHICKNESS); 358 | pointArray[2] = NSMakePoint(-0.2 * LINETHICKNESS, LINETHICKNESS); 359 | pointArray[3] = NSMakePoint(-0.2 * LINETHICKNESS, 1.0); 360 | pointArray[4] = NSMakePoint(- 2.5 * LINETHICKNESS, 1.0); 361 | pointArray[5] = NSMakePoint(- 2.5 * LINETHICKNESS, -1.0); 362 | pointArray[6] = NSMakePoint(-0.2 * LINETHICKNESS, - 1.0); 363 | pointArray[7] = NSMakePoint(-0.2 * LINETHICKNESS, - LINETHICKNESS); 364 | pointArray[8] = NSMakePoint(1.0 - ARROWSIZE, - LINETHICKNESS); 365 | pointArray[9] = NSMakePoint(1.0 - ARROWSIZE, - ARROWSIZE); 366 | 367 | NSBezierPath * bP = [NSBezierPath bezierPath]; 368 | [bP moveToPoint:NSMakePoint(1.0, 0.0)]; 369 | 370 | [bP appendBezierPathWithPoints:pointArray count:10]; 371 | [bP closePath]; 372 | 373 | return bP; 374 | } 375 | 376 | 377 | 378 | + (NSCursor *) halfStraightCursorForAngle: (CGFloat) angle withSize: (CGFloat) size { 379 | NSBezierPath * bP = [ESCursors halfStraightCursorBezierPathForAngle: angle]; 380 | 381 | return [ESCursors cursorForBezierPath: bP withRotation: angle andSize: size]; 382 | } 383 | 384 | 385 | 386 | #pragma mark HELPER METHODS 387 | 388 | #define OUTLINEWIDTH 1.0 389 | 390 | + (NSCursor *) cursorForBezierPath: (NSBezierPath *) bP withRotation: (CGFloat) angle andSize: (CGFloat) size { 391 | return [ESCursors cursorForBezierPath: bP withRotation: angle size: size andUnderlay:nil]; 392 | } 393 | 394 | 395 | + (NSCursor *) cursorForBezierPath: (NSBezierPath *) bP withRotation: (CGFloat) angle size: (CGFloat) size andUnderlay:(NSImage *) underlay { 396 | // NSLog(@"Redrawing cursor"); 397 | const CGFloat s = size * sqrt(2.0); 398 | 399 | NSAffineTransform * aT = [NSAffineTransform transform]; 400 | [aT rotateByRadians:angle]; 401 | [aT scaleBy:size / 2.0 ]; 402 | [bP transformUsingAffineTransform:aT]; 403 | 404 | aT = [NSAffineTransform transform]; 405 | [aT translateXBy: s/2.0 + 0.65 yBy: s/2.0 + 0.65]; 406 | [bP transformUsingAffineTransform:aT]; 407 | 408 | NSImage * image = [[NSImage alloc] initWithSize:NSMakeSize(s, s)]; 409 | [image lockFocus]; 410 | if (underlay) { 411 | [underlay drawAtPoint:NSMakePoint(s/2.0 - underlay.size.width / 2.0 + 0.65, s/2.0 - underlay.size.height/2.0 + 0.65) 412 | fromRect:NSZeroRect 413 | operation:NSCompositeCopy 414 | fraction:1.0]; 415 | } 416 | [[NSColor blackColor] set]; 417 | [bP fill]; 418 | [[NSColor whiteColor] set]; 419 | bP.lineWidth = 1.0; 420 | [bP stroke]; 421 | [image unlockFocus]; 422 | 423 | NSCursor * theCursor = [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint(s/2.0, s/2.0)]; 424 | 425 | #if __has_feature(objc_arc) 426 | #else 427 | [image release]; 428 | [theCursor autorelease]; 429 | #endif 430 | 431 | return theCursor; 432 | } 433 | 434 | 435 | @end 436 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2017 Sven-S. Porst 2 | 3 | The MIT License (MIT) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /Readme.markdown: -------------------------------------------------------------------------------- 1 | # ESCursors 2 | ESCursors is a Cocoa class with a number of methods returning a wide variety of cursor graphics. 3 | 4 | The cursors are arrow cursors with one, two, three or four arrows at the size and rotation of your choice. If desired, one of the axes of the cursor can be curved. 5 | 6 | ![Screenshots of cursor shapes drawn by ESCursors](https://raw.githubusercontent.com/ssp/ESCursors/master/ESCursors-screenshot.png) 7 | 8 | Try out earthlingsoft’s [Symmetries](https://earthlingsoft.net/Symmetries/) application to see them in action. 9 | 10 | MIT Licensed, use it via [CocoaPods](http://cocoadocs.org/docsets/ESCursors/). --------------------------------------------------------------------------------