Annotation of Examples/AppKit/Backspace/UserPath.m, revision 1.1.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.