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.