This is UserPath.m in view mode; [Download] [Up]
/* * UserPath.m by Bruce Blumberg, NeXT Computer, Inc. * * You may freely copy,distribute and re-use the code in this example. NeXT * disclaims any warranty of any kind, expressed or implied, as to its fitness * for any particular purpose * */ #import "UserPath.h" #import <mach/mach_init.h> #import <appkit/graphics.h> #import <appkit/errors.h> #import <math.h> #import <libc.h> static NXZone *upZone = NULL; NXZone *userPathZone() { if (!upZone) upZone = NXCreateZone(vm_page_size, vm_page_size, 1); return upZone; } @implementation UserPath - init { [super init]; max = 32; points = (float *)NXZoneMalloc(userPathZone(), sizeof(float) * max); ops = (char *)NXZoneMalloc(userPathZone(), (2 + (max / 2)) * sizeof(char)); ping = NO; return self; } - free { free(points); free(ops); return [super free]; } - grow { max *= 2; points = (float *)NXZoneRealloc(userPathZone(), points, sizeof(float) * max); ops = (char *)NXZoneRealloc(userPathZone(), ops, (2 + (max / 2)) * sizeof(char)); return self; } - begin:(BOOL)cache { numberOfPoints = numberOfOps = 0; cp.x = cp.y = 0; bbox[0] = bbox[1] = 1.0e6; bbox[2] = bbox[3] = -1.0e6; if (cache) ops[numberOfOps++] = dps_ucache; ops[numberOfOps++] = dps_setbbox; opForUserPath = 0; return self; } - end:(int)op { opForUserPath = op; return self; } - debug:(BOOL)shouldPing { ping = shouldPing; return; } - (int)send /* * Call this to send the path down to the server. If ping==YES (set via * debug:), the function will send an NXPing() after the Path. In any event, * code is bracketed by a NX_DURING ... NX_HANDLER construct which will try to * catch postscript errors. If ping==NO (the default) it is unlikely to catch * errors, with ping==YES it will. Whether you can recover or not is another * matter. sendUserPath returns 0 on success and -1 on failure. If no previous * endUserPath: has been sent, will return -2 and will not send the path to the * server. */ { NXHandler exception; exception.code = 0; if (opForUserPath != 0) { NX_DURING DPSDoUserPath( points, numberOfPoints, dps_float, ops, numberOfOps, bbox, opForUserPath); if (ping) NXPing(); NX_HANDLER exception = NXLocalHandler; NX_ENDHANDLER if (exception.code) { NXReportError(&exception); if (exception.code == dps_err_ps) { return -1; } } else { return 0; } } return -1; } - checkBBox:(float)x :(float)y /* Checks if bounding box needs to be enlarged based on x and y */ { if (x < bbox[0]) bbox[0] = x; if (y < bbox[1]) bbox[1] = y; if (x > bbox[2]) bbox[2] = x; if (y > bbox[3]) bbox[3] = y; return self; } - addPts:(NXPoint *)p /* adds x and y to user path. Updates bounding box as necessary */ { if (!((numberOfPoints + 2) < max)) [self grow]; points[numberOfPoints++] = p->x; points[numberOfPoints++] = p->y; [self checkBBox:p->x :p->y]; return self; } - addOp:(int)op /* * adds operator to user path. Operator should be one of the following: * dps_moveto, dps_rmoveto, dps_lineto, dps_rlineto, dps_curveto, * dps_rcurveto, dps_arc, dps_arcn, dps_arct, dps_closepath. */ { ops[numberOfOps++] = op; return self; } - addOp:(int)op point:(NXPoint *)p /* * adds operator and x and y to user path. Operator should be one of the * operators above */ { if (!((numberOfPoints + 2) < max)) [self grow]; ops[numberOfOps++] = op; points[numberOfPoints++] = p->x; points[numberOfPoints++] = p->y; [self checkBBox:p->x :p->y]; return self; } - addOp:(int)op :(float)x :(float)y /* * adds operator and x and y to user path. Operator should be one of the * operators above */ { if (!((numberOfPoints + 2) < max)) [self grow]; ops[numberOfOps++] = op; points[numberOfPoints++] = x; points[numberOfPoints++] = y; [self checkBBox:x :y]; return self; } - moveTo:(float)x :(float)y /* * adds <x y moveto> to user path and updates bounding box */ { [self addOp: dps_moveto :x :y]; cp.x = x; cp.y = y; return self; } - moveTo:(NXPoint *)p /* * adds <x y moveto> to user path and updates bounding box */ { [self addOp: dps_moveto point:p]; cp.x = p->x; cp.y = p->y; return self; } - rmoveTo:(float)x :(float)y /* * adds <x y rmoveto> to user path and updates bounding box */ { if (!((numberOfPoints + 2) < max)) [self grow]; ops[numberOfOps++] = dps_rmoveto; points[numberOfPoints++] = x; points[numberOfPoints++] = y; cp.x += x; cp.y += y; [self checkBBox:x :y]; return self; } - rmoveTo:(NXPoint *)p /* * adds <x y rmoveto> to user path and updates bounding box */ { if (!((numberOfPoints + 2) < max)) [self grow]; ops[numberOfOps++] = dps_rmoveto; points[numberOfPoints++] = p->x; points[numberOfPoints++] = p->y; cp.x += p->x; cp.y += p->y; [self checkBBox:p->x :p->y]; return self; } - lineTo:(float)x :(float)y /* * adds <x y lineto> to user path and updates bounding box */ { [self addOp:dps_lineto :x :y]; cp.x = x; cp.y = y; return self; } - lineTo:(NXPoint *)p /* * adds <x y lineto> to user path and updates bounding box */ { [self addOp:dps_lineto point:p]; cp.x = p->x; cp.y = p->y; return self; } - rlineTo:(float)x :(float)y /* * adds <x y rlineto> to user path and updates bounding box */ { if (!((numberOfPoints + 2) < max)) [self grow]; ops[numberOfOps++] = dps_rlineto; points[numberOfPoints++] = x; points[numberOfPoints++] = y; cp.x += x; cp.y += y; [self checkBBox:x :y]; return; } - rlineTo:(NXPoint *)p /* * adds <x y rlineto> to user path and updates bounding box */ { if (!((numberOfPoints + 2) < max)) [self grow]; ops[numberOfOps++] = dps_rlineto; points[numberOfPoints++] = p->x; points[numberOfPoints++] = p->y; cp.x += p->x; cp.y += p->y; [self checkBBox:p->x :p->y]; return self; } - curveTo:(float)x1 :(float)y1 :(float)x2 :(float)y2 :(float)x3 :(float)y3 /* * adds <x1 y1 x2 y2 curveto> to user path and updates bounding box */ { [self addPts:x1 :y1]; [self addPts:x2 :y2]; [self addOp:dps_curveto :x3 :y3]; cp.x = x3; cp.y = y3; return self; } - rcurveTo:(float)x1 :(float)y1 :(float)x2 :(float)y2 :(float)x3 :(float)y3 /* * adds <x1 y1 x2 y2 rcurveto> to user path and updates bounding box */ { if (!((numberOfPoints + 6) < max)) [self grow]; ops[numberOfOps++] = dps_rcurveto; points[numberOfPoints++] = x1; points[numberOfPoints++] = y1; points[numberOfPoints++] = x2; points[numberOfPoints++] = y2; points[numberOfPoints++] = x3; points[numberOfPoints++] = y3; [self checkBBox:(cp.x + x1) :(cp.y + y1)]; [self checkBBox:(cp.x + x2) :(cp.y + y2)]; [self checkBBox:(cp.x + x3) :(cp.y + y3)]; cp.x = x3; cp.y = y3; return self; } - arc:(float)x :(float)y :(float)r :(float)ang1 :(float)ang2 /* * adds <x y r ang1 ang2 arc> to user path and updates bounding box */ { if (!((numberOfPoints + 5) < max)) [self grow]; ops[numberOfOps++] = dps_arc; points[numberOfPoints++] = x; points[numberOfPoints++] = y; points[numberOfPoints++] = r; points[numberOfPoints++] = ang1; points[numberOfPoints++] = ang2; [self checkBBox:(x + r) :(y + r)]; [self checkBBox:(x - r) :(y - r)]; cp.x = x + cos(ang2 / 57.3) * r; cp.y = y + sin(ang2 / 57.3) * r; return self; } - arcn:(float)x :(float)y :(float)r :(float)ang1 :(float)ang2 /* * adds <x y r ang1 ang2 arcn> to user path and updates bounding box */ { if (!((numberOfPoints + 5) < max)) [self grow]; ops[numberOfOps++] = dps_arcn; points[numberOfPoints++] = x; points[numberOfPoints++] = y; points[numberOfPoints++] = r; points[numberOfPoints++] = ang1; points[numberOfPoints++] = ang2; [self checkBBox:(x + r) :(y + r)]; [self checkBBox:(x - r) :(y - r)]; cp.x = x + cos(ang2 / 57.3) * r; cp.y = y + sin(ang2 / 57.3) * r; return self; } - arct:(float)x1 :(float)y1 :(float)x2 :(float)y2 :(float)r /* * adds <x1 y1 x2 y2 r arct> to user path and updates bounding box */ { if (!((numberOfPoints + 5) < max)) [self grow]; ops[numberOfOps++] = dps_arcn; points[numberOfPoints++] = x1; points[numberOfPoints++] = y1; points[numberOfPoints++] = x2; points[numberOfPoints++] = y2; points[numberOfPoints++] = r; [self checkBBox:x1 :y1]; [self checkBBox:x2 :y2]; cp.x = x2; cp.y = y2; return self; } - close /* * adds <closepath> to user path and updates bounding box */ { ops[numberOfOps++] = dps_closepath; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.