This is DrawingView.m in view mode; [Download] [Up]
/* * (a) (C) 1990 by Adobe Systems Incorporated. All rights reserved. * * (b) If this Sample Code is distributed as part of the Display PostScript * System Software Development Kit from Adobe Systems Incorporated, * then this copy is designated as Development Software and its use is * subject to the terms of the License Agreement attached to such Kit. * * (c) If this Sample Code is distributed independently, then the following * terms apply: * * (d) This file may be freely copied and redistributed as long as: * 1) Parts (a), (d), (e) and (f) continue to be included in the file, * 2) If the file has been modified in any way, a notice of such * modification is conspicuously indicated. * * (e) PostScript, Display PostScript, and Adobe are registered trademarks of * Adobe Systems Incorporated. * * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO * CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED * AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED. * ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY * OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO * WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY) * WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY * DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, * FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT * OF THIRD PARTY RIGHTS. */ /* * DrawingView.m * * This view represents the page that the image is drawn onto. It is * a subview of the DocView. The DocView is the document view of * the ClipView. This view's real size grows with the scale but the * bounds always stays the same. * * * Version: 2.0 * Author: Ken Fromm * History: * 03-07-91 Added this comment. */ #import "DrawingView.h" #import "DrawingViewWraps.h" #import "DocView.h" #import "Graphic.h" #import "ScrollApp.h" #import <objc/List.h> #import <appkit/Button.h> #import <appkit/Control.h> #import <appkit/Matrix.h> #import <appkit/nextstd.h> #import <dpsclient/dpsclient.h> #import <dpsclient/wraps.h> extern void initGparms(); extern void setGparms(); @implementation DrawingView /* * Allocate a gstate, set the clipping to NO because it will be clipped * by the clip view. */ +newFrame:(NXRect *) frm { self = [super newFrame:frm]; drawUpath = [NXApp getUpathBuffer]; drawManner = UPATH; return self; } - free { [self freeGraphics]; return [super free]; } - setFieldsMode:(BOOL) mode { displayFields = eraseFields = mode; return self; } - setTypeOfDrawing:sender { id matrixId; drawFrame = ([sender selectedRow] == 1); matrixId = [NXApp getStrokingMatrix]; [[matrixId cellAt:0 :0] setEnabled:drawFrame]; [[matrixId cellAt:1 :0] setEnabled:drawFrame]; matrixId = [NXApp getParameterMatrix]; [[matrixId cellAt:0 :0] setEnabled:!drawFrame]; [[matrixId cellAt:1 :0] setEnabled:!drawFrame]; [NXApp redrawAction:self]; return self; } - setSelectivity:sender { drawEverything = ([sender selectedRow] == 1); [NXApp redrawAction:self]; return self; } - setDrawingManner:sender { drawManner = [sender selectedRow]; [NXApp redrawAction:self]; return self; } - setStroking:sender { drawCombined = ([sender selectedRow] == 1); [NXApp redrawAction:self]; return self; } - setParameterSetting:sender { drawEveryPath = ([sender selectedRow] == 1); [NXApp redrawAction:self]; return self; } -setDrawOrigin:(NXPoint *)origin { drawOrigin = *origin; return self; } - freeGraphics { if (graphicsListId) [graphicsListId freeObjects]; [graphicsListId free]; return self; } - insertList:listId { [self freeGraphics]; graphicsListId = listId; return self; } - eraseFields:sender { id matrixId; int i; matrixId = [NXApp getTimingMatrix]; for (i= 0; i < [matrixId cellCount]; i++) [[matrixId cellAt:i :0] setStringValue:""]; matrixId = [NXApp getStatusMatrix]; for (i= 0; i < [matrixId cellCount]; i++) [[matrixId cellAt:i :0] setStringValue:""]; return self; } - displayFields:sender { id matrixId; int i, ucache_values[5]; if (timing_info.num_draws) { matrixId = [NXApp getTimingMatrix]; [[matrixId cellAt:0 :0] setFloatValue:timing_info.num_draws]; [[matrixId cellAt:1 :0] setFloatValue:timing_info.drawingtime/timing_info.num_draws]; if (!drawFrame) { [[matrixId cellAt:2 :0] setFloatValue:timing_info.num_fills/timing_info.num_draws]; [[matrixId cellAt:3 :0] setFloatValue:timing_info.num_strokes/timing_info.num_draws]; } else [[matrixId cellAt:3 :0] setFloatValue:timing_info.num_strokes/timing_info.num_draws]; [[matrixId cellAt:4 :0] setFloatValue:timing_info.num_subpaths/timing_info.num_draws]; } if (drawManner == UCACHE) { matrixId = [NXApp getStatusMatrix]; PSWUcachestatus(&ucache_values[0], &ucache_values[1], &ucache_values[2], &ucache_values[3], &ucache_values[4]); for (i= 0; i < [matrixId cellCount]; i++) [[matrixId cellAt:i :0] setIntValue:ucache_values[i]]; } /* Prepare for next time around. */ timing_info.num_fills = timing_info.num_strokes = 0; timing_info.num_subpaths = timing_info.num_draws = 0; timing_info.drawingtime = 0.0; return self; } /* * If the docview is zooming, then scale the drawing view. */ - mouseDown:(NXEvent *)event { NXPoint p; p = event->location; if ([superview isZooming]) { displayFields = eraseFields = YES; return [nextResponder scaleDrawView:self toPoint:&p]; } return self; } /* * Initialize the user path structure. Always include a ucache. * If ucache is not used then start at the second entry in the op * array and decrement num_ops by one. */ static void initUpath(UPath *aUpath) { aUpath->ops[0] = dps_ucache; aUpath->num_ops = 1; aUpath->pts[0] = 99999; aUpath->pts[1] = 99999; aUpath->pts[2] = -99999; aUpath->pts[3] = -99999; aUpath->num_pts = 4; } /* * Increment the stroke count and stroke the existing path. */ static void strokeRedBook(int *strokes) { *strokes += 1; PSstroke(); } /* * Call the appropriate wrap to construct the path. Not the recommended * approach to drawing (user paths are). Made external so Graphic.m * can make use of it. */ void makeRedBook(UPath *aUpath) { int i_op, i_pt; i_pt = 4; /* Skip the ucache operator. */ for (i_op = 1; i_op < aUpath->num_ops; i_op++) { switch (aUpath->ops[i_op]) { case dps_moveto: PSmoveto(aUpath->pts[i_pt], aUpath->pts[i_pt+1]); i_pt += 2; break; case dps_rmoveto: PSrmoveto(aUpath->pts[i_pt], aUpath->pts[i_pt+1]); i_pt += 2; break; case dps_lineto: PSlineto(aUpath->pts[i_pt], aUpath->pts[i_pt+1]); i_pt += 2; break; case dps_rlineto: PSrlineto(aUpath->pts[i_pt], aUpath->pts[i_pt+1]); i_pt += 2; break; case dps_curveto: PScurveto(aUpath->pts[i_pt], aUpath->pts[i_pt+1], aUpath->pts[i_pt+2], aUpath->pts[i_pt+3], aUpath->pts[i_pt+4], aUpath->pts[i_pt+5]); i_pt += 6; break; case dps_rcurveto: PSrcurveto(aUpath->pts[i_pt], aUpath->pts[i_pt+1], aUpath->pts[i_pt+2], aUpath->pts[i_pt+3], aUpath->pts[i_pt+4], aUpath->pts[i_pt+5]); i_pt += 6; break; case dps_closepath: PSclosepath(); break; } } } /* * If the ucache is to be used then include the first operator * otherwise skip it. */ static void strokeUpath(UPath *aUpath, int manner, int *strokes) { *strokes += 1; if (manner == UCACHE) DPSDoUserPath(&aUpath->pts[4], aUpath->num_pts - 4, dps_float, &aUpath->ops[0], aUpath->num_ops, aUpath->pts, dps_ustroke); else DPSDoUserPath(&aUpath->pts[4], aUpath->num_pts - 4, dps_float, &aUpath->ops[1], aUpath->num_ops-1, aUpath->pts, dps_ustroke); } /* * Omit the bounding box numbers at the beginning of the operand * array as well as the dps_ucache at the beginning of the operator * array. Update the bounding box of the user path if necessary. */ - getUpath:(NXRect *) r fromGraphic:graphicId { int ops_before; UPath *gUpath; [graphicId getUpath:&gUpath forRect:r]; if (gUpath) { timing_info.num_subpaths++; if (!drawCombined) { if (drawManner == REDBOOK) { makeRedBook(gUpath); strokeRedBook(&timing_info.num_strokes); } else strokeUpath(gUpath, drawManner, &timing_info.num_strokes); } else { if (drawUpath->num_pts + gUpath->num_pts > PTS_UPATH_BUFFER || drawUpath->num_ops + gUpath->num_ops > OPS_UPATH_BUFFER) { if (drawManner == REDBOOK) strokeRedBook(&timing_info.num_strokes); else strokeUpath(drawUpath, drawManner, &timing_info.num_strokes); initUpath(drawUpath); } if (drawManner == REDBOOK) makeRedBook(gUpath); else { bcopy(&gUpath->pts[4], &drawUpath->pts[drawUpath->num_pts], (gUpath->num_pts - 4)* (sizeof(float)/sizeof(char))); bcopy(&gUpath->ops[1], &drawUpath->ops[drawUpath->num_ops], gUpath->num_ops-1); drawUpath->pts[0] = MIN(gUpath->pts[0], drawUpath->pts[0]); drawUpath->pts[1] = MIN(gUpath->pts[1], drawUpath->pts[1]); drawUpath->pts[2] = MAX(gUpath->pts[2], drawUpath->pts[2]); drawUpath->pts[3] = MAX(gUpath->pts[3], drawUpath->pts[3]); } drawUpath->num_pts += gUpath->num_pts-4; drawUpath->num_ops += gUpath->num_ops-1; } } return self; } /* * Compare the bounds of the object with the rectangle to draw in order to * eliminate unnecessary drawing. The modal session stuff is just to * intercept the selection of the redraw button in the interface during * a trace. (This stops the drawing. It's only check during a trace * because the trace can be quite long.) */ - drawSelf:(NXRect *)r :(int) count { int i, num, ElapsedTime; BOOL tracing; GParms parms; GParms *p_parms; NXRect rect; NXRect *p_rect; NXModalSession theSession; if (eraseFields) { [self eraseFields:self]; eraseFields = NO; } PSsetgray(NX_WHITE); NXRectFill(r); initGparms(&parms); if (drawFrame) { parms.linewidth = 0.05; initUpath(drawUpath); } else { if (drawEveryPath) p_parms = NULL; else p_parms = &parms; } setGparms(&parms); NXSetColor(parms.color); if (drawEverything) p_rect = NULL; else { rect = *r; rect.origin.x += drawOrigin.x; rect.origin.y += drawOrigin.y; p_rect = ▭ } tracing = [NXApp tracing]; if (tracing) { [[NXApp redrawButton] setTitle:"STOP"]; [NXApp beginModalSession:&theSession for:[NXApp methodsWindow]]; DPSTraceContext(DPSGetCurrentContext(), YES); } PSgsave(); NXRectClip(r); PStranslate(-drawOrigin.x, -drawOrigin.y); PSWMarkTime (); NXPing(); num = [graphicsListId count]; for (i = 0; i < num; i++) { if (tracing && (i % MODALTRACE == 0)) if ([NXApp runDrawModalSession:&theSession] != NX_RUNCONTINUES) break; if (drawFrame) [self getUpath:p_rect fromGraphic:[graphicsListId objectAt:i]]; else [[graphicsListId objectAt:i] drawObject:p_rect currentParms:p_parms withManner:drawManner timingInfo:&timing_info]; } if (drawFrame && drawCombined) { if (drawManner == REDBOOK) strokeRedBook(&timing_info.num_strokes); else strokeUpath(drawUpath, drawManner, &timing_info.num_strokes); } PSWReturnTime (&ElapsedTime); PSgrestore(); if (tracing) { DPSTraceContext(DPSGetCurrentContext(), NO); [NXApp endModalSession:&theSession]; [[NXApp redrawButton] setTitle:"redraw"]; } timing_info.drawingtime += ElapsedTime; ++timing_info.num_draws; if (displayFields) { [self displayFields:self]; displayFields = NO; eraseFields = YES; } return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.