mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-30 08:00:51 +00:00
210 lines
5.2 KiB
Mathematica
210 lines
5.2 KiB
Mathematica
|
/*
|
||
|
* 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()
|
||
|
/* 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 = 8192; // JDC
|
||
|
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 */
|
||
|
printf ("growUserPath\n");
|
||
|
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 UPmoveto(UserPath *up, float x, float y)
|
||
|
/* adds <x y moveto> 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 <x y lineto> 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;
|
||
|
}
|
||
|
|