Annotation of Examples/AppKit/Backspace/UserPath.m, revision 1.1

1.1     ! root        1: /* 
        !             2:  * UserPath.m by Bruce Blumberg, NeXT Computer, Inc.
        !             3:  *
        !             4:  * You may freely copy,distribute and re-use the code in this example. NeXT
        !             5:  * disclaims any warranty of any kind, expressed or implied, as to its fitness
        !             6:  * for any particular purpose
        !             7:  *
        !             8:  */
        !             9: 
        !            10: #import "UserPath.h"
        !            11: #import <mach/mach_init.h>
        !            12: #import <appkit/graphics.h>
        !            13: #import <appkit/errors.h>
        !            14: #import <math.h>
        !            15: #import <libc.h>
        !            16: 
        !            17: static NXZone      *upZone = NULL;
        !            18: 
        !            19: NXZone *userPathZone()
        !            20: /* Creates a unique zone for use by all user paths */
        !            21: {
        !            22:     if (!upZone) {
        !            23:        upZone = NXCreateZone(vm_page_size, vm_page_size, 1);
        !            24:     }
        !            25:     
        !            26:     return upZone;
        !            27: }
        !            28: 
        !            29: UserPath *newUserPath()
        !            30: /* Creates a new User Path in the zone returned by userPathZone */
        !            31: {
        !            32:     UserPath    *up;
        !            33: 
        !            34:     up = (UserPath *)NXZoneMalloc(userPathZone(), sizeof(UserPath));
        !            35:     up->max = 32;
        !            36:     up->points = (float *)NXZoneMalloc(userPathZone(),
        !            37:                                       sizeof(float) * up->max);
        !            38:     up->ops = (char *)NXZoneMalloc(userPathZone(),
        !            39:                                   (2 + (up->max / 2)) * sizeof(char));
        !            40:     up->ping = NO;
        !            41:     
        !            42:     return up;
        !            43: }
        !            44: 
        !            45: void freeUserPath(UserPath *up)
        !            46: /* Frees User Path and its associated buffers */
        !            47: {
        !            48:     free(up->points);
        !            49:     free(up->ops);
        !            50:     free(up);
        !            51:     
        !            52:     return;
        !            53: }
        !            54: 
        !            55: void growUserPath(UserPath *up)
        !            56: /*
        !            57:  * grows the  associated buffers as necessary. buffer size doubles on each
        !            58:  * call. You never need to call grow directly as it is called as needed by the
        !            59:  * methods and functions which add elements into the buffer
        !            60:  */
        !            61: {
        !            62:  /* double the size of the internal buffers */
        !            63:     up->max *= 2;
        !            64:     up->points = (float *)NXZoneRealloc(userPathZone(), up->points,
        !            65:                                        sizeof(float) * up->max);
        !            66:     up->ops = (char *)NXZoneRealloc(userPathZone(), up->ops,
        !            67:                                    (2 + (up->max / 2)) * sizeof(char));
        !            68: 
        !            69:     return;
        !            70: }
        !            71: 
        !            72: void beginUserPath(UserPath *up, BOOL cache)
        !            73: /*
        !            74:  * Call this to start generating a user path. The cache argument specifies if
        !            75:  * you want the user path cached at the server (i.e. dps_ucache). In either
        !            76:  * case, the UserPath object will automatically calculate the bounding box for
        !            77:  * the path and add the dps_setbbox operator.
        !            78:  */
        !            79: {
        !            80:     up->numberOfPoints = up->numberOfOps = 0;
        !            81:     up->cp.x = up->cp.y = 0;
        !            82:     up->bbox[0] = up->bbox[1] = 1.0e6;
        !            83:     up->bbox[2] = up->bbox[3] = -1.0e6;
        !            84:     if (cache) {
        !            85:        up->ops[up->numberOfOps++] = dps_ucache;
        !            86:     }
        !            87:     up->ops[up->numberOfOps++] = dps_setbbox;
        !            88:     up->opForUserPath = 0;
        !            89:     
        !            90:     return;
        !            91: }
        !            92: 
        !            93: void endUserPath(UserPath *up, int op)
        !            94: /*
        !            95:  * Call this to stop filling the path. Note this does not send the userpath to
        !            96:  * the server -- use sendUserPath. The op argument should be one of the
        !            97:  * following:
        !            98:  *     dps_uappend, dps_ufill ,dps_ueofill, dps_ustroke, dps_ustrokepath,
        !            99:  *     dps_inufill, dps_inueofill, dps_inustroke, dps_def, dps_put.
        !           100:  * These are defined in <dpsclient/dpsNext.h.  
        !           101:  */
        !           102: {
        !           103:     up->opForUserPath = op;
        !           104:     
        !           105:     return;
        !           106: }
        !           107: 
        !           108: 
        !           109: void UPdebug(UserPath *up, BOOL shouldPing)
        !           110: /*
        !           111:  * Sets ping to YES so that after each time a user path is sent down to the
        !           112:  * window server, an NXPing() is sent after. The purpose is to catch PostScript
        !           113:  * errors that may be generated by the user path. sendUserPath brackets the
        !           114:  * download and the NXPing() in an NX_DURING... NX_HANDLER construct. Normally
        !           115:  * ping is NO. 
        !           116:  */
        !           117: {
        !           118:     up->ping = shouldPing;
        !           119:     
        !           120:     return;
        !           121: }
        !           122: 
        !           123: int sendUserPath(UserPath *up)
        !           124: /*
        !           125:  * Call this to send the path down to the server. If ping==YES (set via
        !           126:  * debug:), the function will send an NXPing() after the Path. In any event,
        !           127:  * code is bracketed by a NX_DURING ... NX_HANDLER construct which will try to
        !           128:  * catch postscript errors.  If ping==NO (the default) it is unlikely to catch
        !           129:  * errors, with ping==YES it will. Whether you can recover or not is another
        !           130:  * matter. sendUserPath returns 0 on success and -1 on failure. If no previous
        !           131:  * endUserPath: has been sent, will return -2 and will not send the path to the
        !           132:  * server.
        !           133:  */
        !           134: {
        !           135:     NXHandler           exception;
        !           136: 
        !           137:     exception.code = 0;
        !           138:     if (up->opForUserPath != 0) {
        !           139:       NX_DURING
        !           140:        DPSDoUserPath(up->points, up->numberOfPoints, dps_float, up->ops,
        !           141:                      up->numberOfOps, up->bbox, up->opForUserPath);
        !           142:        if (up->ping) {
        !           143:            NXPing();
        !           144:        }
        !           145:        
        !           146:       NX_HANDLER
        !           147:        exception = NXLocalHandler;
        !           148:       NX_ENDHANDLER
        !           149:        if (exception.code) {
        !           150:            NXReportError(&exception);
        !           151:            if (exception.code == dps_err_ps) {
        !           152:                return -1;
        !           153:            }
        !           154:        } else {
        !           155:            return 0;
        !           156:        }
        !           157:     }
        !           158:     
        !           159:     return -1;
        !           160: }
        !           161: 
        !           162: void checkBoundingBox(UserPath *up, float x, float y)
        !           163: /* Checks if bounding box needs to be enlarged based on x and y */
        !           164: {
        !           165:     if (x < up->bbox[0]) {
        !           166:        up->bbox[0] = x;
        !           167:     }
        !           168:     if (y < up->bbox[1]) {
        !           169:        up->bbox[1] = y;
        !           170:     }
        !           171:     if (x > up->bbox[2]) {
        !           172:        up->bbox[2] = x;
        !           173:     }
        !           174:     if (y > up->bbox[3]) {
        !           175:        up->bbox[3] = y;
        !           176:     }
        !           177:     
        !           178:     return;
        !           179: }
        !           180: 
        !           181: void addPts(UserPath *up, float x, float y)
        !           182: /* adds x and y to user path. Updates bounding box as necessary */
        !           183: {
        !           184:     if (!((up->numberOfPoints + 2) < up->max)) {
        !           185:        growUserPath(up);
        !           186:     }
        !           187:     
        !           188:     up->points[up->numberOfPoints++] = x;
        !           189:     up->points[up->numberOfPoints++] = y;
        !           190:     checkBoundingBox(up, x, y);
        !           191:     
        !           192:     return;
        !           193: }
        !           194: 
        !           195: void addOp(UserPath *up, int op)
        !           196: /*
        !           197:  * adds operator to user path.  Operator should be one of the following:
        !           198:  *     dps_moveto, dps_rmoveto, dps_lineto, dps_rlineto, dps_curveto,
        !           199:  *     dps_rcurveto, dps_arc, dps_arcn, dps_arct, dps_closepath.
        !           200:  */
        !           201: {
        !           202:     up->ops[up->numberOfOps++] = op;
        !           203:     
        !           204:     return;
        !           205: }
        !           206: 
        !           207: void add(UserPath *up, int op, float x, float y)
        !           208: /*
        !           209:  * adds operator and x and y to user path. Operator should be one of the
        !           210:  * operators above
        !           211:  */
        !           212: {
        !           213:     if (!((up->numberOfPoints + 2) < up->max)) {
        !           214:        growUserPath(up);
        !           215:     }
        !           216:     
        !           217:     up->ops[up->numberOfOps++] = op;
        !           218:     up->points[up->numberOfPoints++] = x;
        !           219:     up->points[up->numberOfPoints++] = y;
        !           220:     checkBoundingBox(up, x, y);
        !           221:     
        !           222:     return;
        !           223: }
        !           224: 
        !           225: void UPmoveto(UserPath *up, float x, float y)
        !           226: /* adds <x y moveto> to user path and updates bounding box */
        !           227: {
        !           228:     add(up, dps_moveto, x, y);
        !           229:     up->cp.x = x;
        !           230:     up->cp.y = y;
        !           231:     
        !           232:     return;
        !           233: }
        !           234: 
        !           235: void UPrmoveto(UserPath *up, float x, float y)
        !           236: /* adds <x y rmoveto> to user path and updates bounding box */
        !           237: {
        !           238:     if (!((up->numberOfPoints + 2) < up->max)) {
        !           239:        growUserPath(up);
        !           240:     }
        !           241:     up->ops[up->numberOfOps++] = dps_rmoveto;
        !           242:     up->points[up->numberOfPoints++] = x;
        !           243:     up->points[up->numberOfPoints++] = y;
        !           244:     up->cp.x += x;
        !           245:     up->cp.y += y;
        !           246:     checkBoundingBox(up, up->cp.x, up->cp.y);
        !           247:     
        !           248:     return;
        !           249: }
        !           250: 
        !           251: void UPlineto(UserPath *up, float x, float y)
        !           252: /* adds <x y lineto> to user path and updates bounding box */
        !           253: {
        !           254:     add(up, dps_lineto, x, y);
        !           255:     up->cp.x = x;
        !           256:     up->cp.y = y;
        !           257:     
        !           258:     return;
        !           259: }
        !           260: 
        !           261: void UPrlineto(UserPath *up, float x, float y)
        !           262: /* adds <x y rlineto> to user path and updates bounding box */
        !           263: {
        !           264:     if (!((up->numberOfPoints + 2) < up->max)) {
        !           265:        growUserPath(up);
        !           266:     }
        !           267:     up->ops[up->numberOfOps++] = dps_rlineto;
        !           268:     up->points[up->numberOfPoints++] = x;
        !           269:     up->points[up->numberOfPoints++] = y;
        !           270:     up->cp.x += x;
        !           271:     up->cp.y += y;
        !           272:     checkBoundingBox(up, up->cp.x, up->cp.y);
        !           273:     
        !           274:     return;
        !           275: }
        !           276: 
        !           277: void UPcurveto(UserPath *up, float x1, float y1, float x2, float y2, float x3,
        !           278:               float y3)
        !           279: /* adds <x1 y1 x2 y2 curveto> to user path and updates bounding box */
        !           280: {
        !           281:     addPts(up, x1, y1);
        !           282:     addPts(up, x2, y2);
        !           283:     add(up, dps_curveto, x3, y3);
        !           284:     up->cp.x = x3;
        !           285:     up->cp.y = y3;
        !           286:     
        !           287:     return;
        !           288: }
        !           289: 
        !           290: void UPrcurveto(UserPath *up, float dx1, float dy1, float dx2, float dy2,
        !           291:                float dx3, float dy3)
        !           292: /* adds <x1 y1 x2 y2 rcurveto> to user path and updates bounding box */
        !           293: {
        !           294:     if (!((up->numberOfPoints + 6) < up->max)) {
        !           295:        growUserPath(up);
        !           296:     }
        !           297:     up->ops[up->numberOfOps++] = dps_rcurveto;
        !           298:     up->points[up->numberOfPoints++] = dx1;
        !           299:     up->points[up->numberOfPoints++] = dy1;
        !           300:     up->points[up->numberOfPoints++] = dx2;
        !           301:     up->points[up->numberOfPoints++] = dy2;
        !           302:     up->points[up->numberOfPoints++] = dx3;
        !           303:     up->points[up->numberOfPoints++] = dy3;
        !           304:     checkBoundingBox(up, up->cp.x + dx1, up->cp.y + dy1);
        !           305:     checkBoundingBox(up, up->cp.x + dx2, up->cp.y + dy2);
        !           306:     checkBoundingBox(up, up->cp.x + dx3, up->cp.y + dy3);
        !           307:     up->cp.x = dx3;
        !           308:     up->cp.y = dy3;
        !           309: 
        !           310:     return;
        !           311: }
        !           312: 
        !           313: void UParc(UserPath *up, float x, float y, float r, float ang1, float ang2)
        !           314: /* adds <x y r ang1 ang2 arc> to user path and updates bounding box */
        !           315: {
        !           316:     if (!((up->numberOfPoints + 5) < up->max)) {
        !           317:        growUserPath(up);
        !           318:     }
        !           319:     up->ops[up->numberOfOps++] = dps_arc;
        !           320:     up->points[up->numberOfPoints++] = x;
        !           321:     up->points[up->numberOfPoints++] = y;
        !           322:     up->points[up->numberOfPoints++] = r;
        !           323:     up->points[up->numberOfPoints++] = ang1;
        !           324:     up->points[up->numberOfPoints++] = ang2;
        !           325:     checkBoundingBox(up, x + r, y + r);
        !           326:     checkBoundingBox(up, x - r, y - r);
        !           327:     up->cp.x = x + cos(ang2 / 57.3) * r;
        !           328:     up->cp.y = y + sin(ang2 / 57.3) * r;
        !           329:     
        !           330:     return;
        !           331: }
        !           332: 
        !           333: void UParcn(UserPath *up, float x, float y, float r, float ang1, float ang2)
        !           334: /* adds <x y r ang1 ang2 arcn> to user path and updates bounding box */
        !           335: {
        !           336:     if (!((up->numberOfPoints + 5) < up->max)) {
        !           337:        growUserPath(up);
        !           338:     }
        !           339:     up->ops[up->numberOfOps++] = dps_arcn;
        !           340:     up->points[up->numberOfPoints++] = x;
        !           341:     up->points[up->numberOfPoints++] = y;
        !           342:     up->points[up->numberOfPoints++] = r;
        !           343:     up->points[up->numberOfPoints++] = ang1;
        !           344:     up->points[up->numberOfPoints++] = ang2;
        !           345:     checkBoundingBox(up, x + r, y + r);
        !           346:     checkBoundingBox(up, x - r, y - r);
        !           347:     up->cp.x = x + cos(ang2 / 57.3) * r;
        !           348:     up->cp.y = y + sin(ang2 / 57.3) * r;
        !           349:     
        !           350:     return;
        !           351: }
        !           352: 
        !           353: void UParct(UserPath *up, float x1, float y1, float x2, float y2, float r)
        !           354: /* adds <x1 y1 x2 y2 r arct> to user path and updates bounding box */
        !           355: {
        !           356:     if (!((up->numberOfPoints + 5) < up->max)) {
        !           357:        growUserPath(up);
        !           358:     }
        !           359:     up->ops[up->numberOfOps++] = dps_arcn;
        !           360:     up->points[up->numberOfPoints++] = x1;
        !           361:     up->points[up->numberOfPoints++] = y1;
        !           362:     up->points[up->numberOfPoints++] = x2;
        !           363:     up->points[up->numberOfPoints++] = y2;
        !           364:     up->points[up->numberOfPoints++] = r;
        !           365:     checkBoundingBox(up, x1, y1);
        !           366:     checkBoundingBox(up, x2, y2);
        !           367:     up->cp.x = x2;
        !           368:     up->cp.y = y2;
        !           369:     
        !           370:     return;
        !           371: }
        !           372: 
        !           373: void closePath(UserPath *up)
        !           374: /* adds <closepath> to user path and updates bounding box */
        !           375: {
        !           376:     up->ops[up->numberOfOps++] = dps_closepath;
        !           377:     
        !           378:     return;
        !           379: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.