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_init.h> #import <appkit/graphics.h> #import <appkit/errors.h> #import <math.h> #import <libc.h> static NXZone *upZone = NULL; NXZone *userPathZone() /* Creates a unique zone for use by all user paths */ { if (!upZone) { upZone = NXCreateZone(vm_page_size, vm_page_size, 1); } return upZone; } UserPath *newUserPath() /* Creates a new User Path in the zone returned by userPathZone */ { UserPath *up; up = (UserPath *)NXZoneMalloc(userPathZone(), sizeof(UserPath)); up->max = 32; up->points = (float *)NXZoneMalloc(userPathZone(), sizeof(float) * up->max); up->ops = (char *)NXZoneMalloc(userPathZone(), (2 + (up->max / 2)) * sizeof(char)); up->ping = NO; return up; } void freeUserPath(UserPath *up) /* Frees User Path and its associated buffers */ { free(up->points); free(up->ops); free(up); return; } void growUserPath(UserPath *up) /* * grows the associated buffers as necessary. buffer size doubles on each * call. You never need to call grow directly as it is called as needed by the * methods and functions which add elements into the buffer */ { /* double the size of the internal buffers */ up->max *= 2; up->points = (float *)NXZoneRealloc(userPathZone(), up->points, sizeof(float) * up->max); up->ops = (char *)NXZoneRealloc(userPathZone(), up->ops, (2 + (up->max / 2)) * sizeof(char)); return; } void beginUserPath(UserPath *up, BOOL cache) /* * Call this to start generating a user path. The cache argument specifies if * you want the user path cached at the server (i.e. dps_ucache). In either * case, the UserPath object will automatically calculate the bounding box for * the path and add the dps_setbbox operator. */ { up->numberOfPoints = up->numberOfOps = 0; up->cp.x = up->cp.y = 0; up->bbox[0] = up->bbox[1] = 1.0e6; up->bbox[2] = up->bbox[3] = -1.0e6; if (cache) { up->ops[up->numberOfOps++] = dps_ucache; } up->ops[up->numberOfOps++] = dps_setbbox; up->opForUserPath = 0; return; } void endUserPath(UserPath *up, int op) /* * Call this to stop filling the path. Note this does not send the userpath to * the server -- use sendUserPath. The op argument should be one of the * following: * dps_uappend, dps_ufill ,dps_ueofill, dps_ustroke, dps_ustrokepath, * dps_inufill, dps_inueofill, dps_inustroke, dps_def, dps_put. * These are defined in <dpsclient/dpsNext.h. */ { up->opForUserPath = op; return; } void UPdebug(UserPath *up, BOOL shouldPing) /* * Sets ping to YES so that after each time a user path is sent down to the * window server, an NXPing() is sent after. The purpose is to catch PostScript * errors that may be generated by the user path. sendUserPath brackets the * download and the NXPing() in an NX_DURING... NX_HANDLER construct. Normally * ping is NO. */ { up->ping = shouldPing; return; } int sendUserPath(UserPath *up) /* * 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 (up->opForUserPath != 0) { NX_DURING DPSDoUserPath(up->points, up->numberOfPoints, dps_float, up->ops, up->numberOfOps, up->bbox, up->opForUserPath); if (up->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; } void checkBoundingBox(UserPath *up, float x, float y) /* Checks if bounding box needs to be enlarged based on x and y */ { if (x < up->bbox[0]) { up->bbox[0] = x; } if (y < up->bbox[1]) { up->bbox[1] = y; } if (x > up->bbox[2]) { up->bbox[2] = x; } if (y > up->bbox[3]) { up->bbox[3] = y; } return; } void addPts(UserPath *up, float x, float y) /* adds x and y to user path. Updates bounding box as necessary */ { if (!((up->numberOfPoints + 2) < up->max)) { growUserPath(up); } up->points[up->numberOfPoints++] = x; up->points[up->numberOfPoints++] = y; checkBoundingBox(up, x, y); return; } void addOp(UserPath *up, 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. */ { up->ops[up->numberOfOps++] = op; return; } void add(UserPath *up, int op, float x, float y) /* * adds operator and x and y to user path. Operator should be one of the * operators above */ { if (!((up->numberOfPoints + 2) < up->max)) { growUserPath(up); } up->ops[up->numberOfOps++] = op; up->points[up->numberOfPoints++] = x; up->points[up->numberOfPoints++] = y; checkBoundingBox(up, x, y); return; } void UPmoveto(UserPath *up, float x, float y) /* adds <x y moveto> to user path and updates bounding box */ { add(up, dps_moveto, x, y); up->cp.x = x; up->cp.y = y; return; } void UPrmoveto(UserPath *up, float x, float y) /* adds <x y rmoveto> to user path and updates bounding box */ { if (!((up->numberOfPoints + 2) < up->max)) { growUserPath(up); } up->ops[up->numberOfOps++] = dps_rmoveto; up->points[up->numberOfPoints++] = x; up->points[up->numberOfPoints++] = y; up->cp.x += x; up->cp.y += y; checkBoundingBox(up, up->cp.x, up->cp.y); return; } void UPlineto(UserPath *up, float x, float y) /* adds <x y lineto> to user path and updates bounding box */ { add(up, dps_lineto, x, y); up->cp.x = x; up->cp.y = y; return; } void UPrlineto(UserPath *up, float x, float y) /* adds <x y rlineto> to user path and updates bounding box */ { if (!((up->numberOfPoints + 2) < up->max)) { growUserPath(up); } up->ops[up->numberOfOps++] = dps_rlineto; up->points[up->numberOfPoints++] = x; up->points[up->numberOfPoints++] = y; up->cp.x += x; up->cp.y += y; checkBoundingBox(up, up->cp.x, up->cp.y); return; } void UPcurveto(UserPath *up, 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 */ { addPts(up, x1, y1); addPts(up, x2, y2); add(up, dps_curveto, x3, y3); up->cp.x = x3; up->cp.y = y3; return; } void UPrcurveto(UserPath *up, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) /* adds <x1 y1 x2 y2 rcurveto> to user path and updates bounding box */ { if (!((up->numberOfPoints + 6) < up->max)) { growUserPath(up); } up->ops[up->numberOfOps++] = dps_rcurveto; up->points[up->numberOfPoints++] = dx1; up->points[up->numberOfPoints++] = dy1; up->points[up->numberOfPoints++] = dx2; up->points[up->numberOfPoints++] = dy2; up->points[up->numberOfPoints++] = dx3; up->points[up->numberOfPoints++] = dy3; checkBoundingBox(up, up->cp.x + dx1, up->cp.y + dy1); checkBoundingBox(up, up->cp.x + dx2, up->cp.y + dy2); checkBoundingBox(up, up->cp.x + dx3, up->cp.y + dy3); up->cp.x = dx3; up->cp.y = dy3; return; } void UParc(UserPath *up, 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 (!((up->numberOfPoints + 5) < up->max)) { growUserPath(up); } up->ops[up->numberOfOps++] = dps_arc; up->points[up->numberOfPoints++] = x; up->points[up->numberOfPoints++] = y; up->points[up->numberOfPoints++] = r; up->points[up->numberOfPoints++] = ang1; up->points[up->numberOfPoints++] = ang2; checkBoundingBox(up, x + r, y + r); checkBoundingBox(up, x - r, y - r); up->cp.x = x + cos(ang2 / 57.3) * r; up->cp.y = y + sin(ang2 / 57.3) * r; return; } void UParcn(UserPath *up, 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 (!((up->numberOfPoints + 5) < up->max)) { growUserPath(up); } up->ops[up->numberOfOps++] = dps_arcn; up->points[up->numberOfPoints++] = x; up->points[up->numberOfPoints++] = y; up->points[up->numberOfPoints++] = r; up->points[up->numberOfPoints++] = ang1; up->points[up->numberOfPoints++] = ang2; checkBoundingBox(up, x + r, y + r); checkBoundingBox(up, x - r, y - r); up->cp.x = x + cos(ang2 / 57.3) * r; up->cp.y = y + sin(ang2 / 57.3) * r; return; } void UParct(UserPath *up, 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 (!((up->numberOfPoints + 5) < up->max)) { growUserPath(up); } up->ops[up->numberOfOps++] = dps_arcn; up->points[up->numberOfPoints++] = x1; up->points[up->numberOfPoints++] = y1; up->points[up->numberOfPoints++] = x2; up->points[up->numberOfPoints++] = y2; up->points[up->numberOfPoints++] = r; checkBoundingBox(up, x1, y1); checkBoundingBox(up, x2, y2); up->cp.x = x2; up->cp.y = y2; return; } void closePath(UserPath *up) /* adds <closepath> to user path and updates bounding box */ { up->ops[up->numberOfOps++] = dps_closepath; return; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.