/* * 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 * */ #include "UserPath.h" #include #include #include #include #include static NSZone *upZone = NULL; NSZone *userPathZone() /* Creates a unique zone for use by all user paths */ { if (!upZone) { upZone = NSCreateZone(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 *)NSZoneMalloc(userPathZone(), sizeof(UserPath)); up->max = 8192; // JDC up->points = (float *)NSZoneMalloc(userPathZone(), sizeof(float) * up->max); up->ops = (char *)NSZoneMalloc(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 */ printf ("growUserPath\n"); up->max *= 2; up->points = (float *)NSZoneRealloc(userPathZone(), up->points, sizeof(float) * up->max); up->ops = (char *)NSZoneRealloc(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 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 NSPing() is sent after. The purpose is to catch PostScript * errors that may be generated by the user path. sendUserPath brackets the * download and the NSPing() in an NS_DURING... NS_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 NSPing() after the Path. In any event, * code is bracketed by a NS_DURING ... NS_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. */ { NSHandler exception; exception.code = 0; if (up->opForUserPath != 0) { NS_DURING DPSDoUserPath(up->points, up->numberOfPoints, dps_float, up->ops, up->numberOfOps, up->bbox, up->opForUserPath); if (up->ping) { NSPing(); } NS_HANDLER exception = NSLocalHandler; NS_ENDHANDLER if (exception.code) { NSReportError(&exception); if (exception.code == dps_err_ps) { return -1; } } else { return 0; } } return -1; } void UPmoveto(UserPath *up, float x, float y) /* adds to user path and updates bounding box */ { up->ops[up->numberOfOps++] = dps_moveto; up->points[up->numberOfPoints++] = x; up->points[up->numberOfPoints++] = 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 UPlineto(UserPath *up, float x, float y) /* adds to user path and updates bounding box */ { up->ops[up->numberOfOps++] = dps_lineto; up->points[up->numberOfPoints++] = x; up->points[up->numberOfPoints++] = 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; }