home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * (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.
- */
-
- /*
- * ClockView.m
- *
- * This class handles the drawing of the clock and the moving of the alarm.
- * The clock face is drawn into a bitmap and then composited into the buffered
- * window before drawing the hands. The hands are stored in the server
- * as user paths. Each hand also has a graphic state associated with it. Before
- * hand is drawn, its graphic state is installed and then rotated to its current
- * angle and then the user path is rendered.
- *
- * An animator object has been borrowed from the stopwatch implementation in
- * the NeXTDeveloper directory. This object makes adjustments to the timed
- * entry in order to keep the timing up to date.
- *
- * Version: 2.0
- * Author: Ken Fromm
- * History:
- * 03-07-91 Added this comment.
- */
-
- #import "Animator.h"
- #import "ClockView.h"
- #import "ClockViewWraps.h"
-
- #import <appkit/Cell.h>
- #import <appkit/Control.h>
- #import <appkit/NXImage.h>
- #import <appkit/View.h>
- #import <appkit/nextstd.h>
-
- #import <dpsclient/dpsclient.h>
- #import <dpsclient/wraps.h>
-
- @implementation ClockView
-
- static void drawClockHand(id self, int hand);
-
- /*
- * These are the user path operands and operators for the clock hands.
- * They are sent and stored in the server.
- */
- static float ptsHour[] = { -10, -10, 10, 170, -4.5, 0, 0, 120, 0,120, 4.5, 180, 0, 0, -120,
- 0, 0, 0, 0, 10, 360, 0};
- static char opsHour[] = {dps_setbbox, dps_moveto, dps_rlineto, dps_arcn, dps_rlineto,
- dps_closepath, dps_moveto, dps_arcn, dps_closepath};
- static float ptsMin[] = { -10, -10, 10, 175, -4.5, 0, 0, 162, 0,162, 4.5, 180, 0, 0, -162,
- 0, 0, 0, 0, 10, 360, 0};
- static char opsMin[] = {dps_setbbox, dps_moveto, dps_rlineto, dps_arcn, dps_rlineto,
- dps_closepath, dps_moveto, dps_arcn, dps_closepath};
- static float ptsSec[] = { -10, -30, 10, 170, -1.5, 0, 0, 145, 3, 0, 0, -145,
- 4, 0, 0, -20, 0, -20, 5.5, 360, 180, 0, 20, 4, 0, 0, 0, 0, 0, 10, 360, 0};
- static char opsSec[] = {dps_setbbox, dps_moveto, dps_rlineto, dps_rlineto, dps_rlineto,
- dps_rlineto, dps_rlineto, dps_arcn, dps_rlineto, dps_rlineto, dps_closepath,
- dps_moveto, dps_arcn, dps_closepath};
-
- static float ptsAlarmTop[] = { -5, 70, 5, 120, -1.0, 100, 0, 5, 0, 105, 1.0, 180, 0, 0, -5};
- static char opsAlarmTop[] = {dps_setbbox, dps_moveto, dps_rlineto, dps_arcn, dps_rlineto,
- dps_closepath};
- static float ptsAlarmBot[] = { -5, -2, 5, 120, -1.0, 0, 0, 100, 2.0, 0, 0, -100};
- static char opsAlarmBot[] = {dps_setbbox, dps_moveto, dps_rlineto, dps_rlineto,
- dps_rlineto, dps_closepath};
-
- /*
- * Initialize the instance variables and create an Animator object.
- * The animator is used to keep the timed_entry up to date. Without
- * the animator adjustments, the clock loses time. An array to hold
- * the hit detection user path is allocated. This mouse location
- * will be inserted into this user path before the hit detection is
- * tested for.
- */
- - initFrame:(const NXRect *) frameRect
- {
- [super initFrame:frameRect];
- [self setClipping:NO];
-
- gstatesOn = upathsServer = YES;
- totalTime = numIterations = 0;
- angleAlarm = 0;
- gstateHour = gstateMin = gstateSec = gstateShad = 0;
- upathHour = upathMin = upathSec = upathAlarmTop = upathAlarmBot = 0;
-
- NX_MALLOC(hitPoint.pts, float, MAX_PTS_HIT);
- NX_MALLOC(hitPoint.ops, char, MAX_OPS_HIT);
- [self initializeHitPoint];
-
- animatorId = [Animator newChronon: 1.0
- adaptation: 3.0
- target: self
- action: @selector(tick:)
- autoStart: NO
- eventMask: NX_ALLEVENTS];
-
- return self;
- }
-
- /* Most of these will remain the same between hit detection tests. */
- - initializeHitPoint
- {
- int i;
-
- for (i = 0; i < MAX_PTS_HIT; i++)
- {
- hitPoint.pts[i] = 0;
- }
- hitPoint.num_pts = i;
-
- hitPoint.ops[0] = dps_setbbox;
- hitPoint.ops[1] = dps_moveto;
- hitPoint.ops[2] = dps_rlineto;
- hitPoint.ops[3] = dps_rlineto;
- hitPoint.ops[4] = dps_rlineto;
- hitPoint.ops[5] = dps_closepath;
- hitPoint.num_ops = 6;
-
- return self;
- }
-
- - free
- {
- if (hitPoint.pts)
- NX_FREE(hitPoint.pts);
- if (hitPoint.ops)
- NX_FREE(hitPoint.ops);
-
- [animatorId free];
- [imageId free];
-
- return [super free];
- }
-
- - setDisplayTime:anObject
- {
- displayTime = anObject;
-
- return self;
- }
-
- - toggleGstate:sender
- {
- totalTime = numIterations = 0;
- gstatesOn = [sender state];
-
- return self;
- }
-
- - toggleUpath:sender
- {
- totalTime = numIterations = 0;
- upathsServer = [sender state];
-
- return self;
- }
-
- /* Use DPSDoUserPath to draw the lines of the clock. */
- static void drawUpathLines (pts, ops, clr, wid, x, y, startlen, endlen, deg)
- float pts[];
- char ops[];
- float clr, wid, x, y, startlen, endlen, deg;
- {
- int i , j;
-
- float angle;
-
- deg = ABS(deg * RADIAN);
- i = 4; j = 1;
- for (angle = 0; angle < 2 * M_PI; angle += deg)
- {
- pts[i++] = (floor) (x + (float) cos(angle) * startlen);
- pts[i++] = (floor) (y + (float) sin(angle) * startlen);
- ops[j++] = dps_moveto;
-
- pts[i++] = (floor) (x + (float) cos(angle) * endlen);
- pts[i++] = (floor) (y + (float) sin(angle) * endlen);
- ops[j++] = dps_lineto;
- }
-
- PSsetgray(clr);
- PSsetlinewidth(wid);
- DPSDoUserPath(&pts[4], i - 4, dps_float, &ops[1], j -1, pts, dps_ustroke);
- }
-
- /*
- * Draw the clock face into an offscreen bitmap. Resizes the bitmap if the
- * frame of this view is larger than the current size of the bitmap. Uses the
- * frame dimensions instead of the bounds because the bounds are
- * affected by the scale:: method and do not produce the correct
- * dimensions in the default user space.
- */
- - drawFace
- {
- char *ops;
-
- float *pts;
-
- NXSize size;
-
- NXPoint center;
-
- float maxnums, maxdashes, maxcircle;
-
- if (imageId)
- {
- [imageId getSize:&size];
- if (size.width < frame.size.width || size.height < frame.size.height)
- [imageId setSize:&frame.size];
- }
- else
- imageId = [[NXImage newSize:&frame.size] setFlipped:NO];
-
- center.x = floor(bounds.size.width/2);
- center.y = floor(bounds.size.height/2);
- maxcircle = MIN(center.y - 10, center.x -10);
- maxnums = maxcircle * SIZENUMS;
- maxdashes = maxcircle * SIZEDASHES;
-
- NX_MALLOC(pts, float, MAX_PTS);
- NX_MALLOC(ops, char, MAX_OPS);
-
- pts[0] = bounds.origin.x;
- pts[1] = bounds.origin.y;
- pts[2] = bounds.origin.x + bounds.size.width;
- pts[3] = bounds.origin.y + bounds.size.height;
- ops[0] = dps_setbbox;
-
- [imageId lockFocus];
- PSscale(frame.size.width/bounds.size.width, frame.size.height/bounds.size.height);
- PSWEraseView (CLRVIEW, bounds.origin.x, bounds.origin.y,
- bounds.size.width, bounds.size.height);
- PSWMakeCircle(center.x, center.y, maxcircle);
- PSWFillPath(CLRCIRC);
-
- PSsetlinecap(1);
- drawUpathLines(pts, ops, CLRMIN, WIDMIN, center.x, center.y,
- maxdashes * LENMIN, maxdashes, DEGMIN);
- drawUpathLines(pts, ops, CLRHOUR, WIDHOUR, center.x, center.y,
- maxdashes * LENHOUR, maxdashes, DEGHOUR);
- [imageId unlockFocus];
-
- if (pts)
- NX_FREE(pts);
- if (ops)
- NX_FREE(ops);
-
- return self;
- }
-
- /* Define the userpaths of the hands as user objects. */
- - defineUPaths
- {
- /* Setup hour hand upath. */
- PSWSetUpath(ptsHour, sizeof (ptsHour)/sizeof (float),
- opsHour, sizeof (opsHour)/sizeof (char));
- upathHour = DPSDefineUserObject(0);
-
- /* Setup minute hand upath. */
- PSWSetUpath(ptsMin, sizeof (ptsMin)/sizeof (float),
- opsMin, sizeof (opsMin)/sizeof (char));
- upathMin = DPSDefineUserObject(0);
-
- /* Setup seconds hand upath. */
- PSWSetUpath(ptsSec, sizeof (ptsSec)/sizeof (float),
- opsSec, sizeof (opsSec)/sizeof (char));
- upathSec = DPSDefineUserObject(0);
-
- /* Setup top of alarm hand upath. */
- PSWSetUpath(ptsAlarmTop, sizeof (ptsAlarmTop)/sizeof (float),
- opsAlarmTop, sizeof (opsAlarmTop)/sizeof (char));
- upathAlarmTop = DPSDefineUserObject(0);
-
- /* Setup bottom of alarm hand upath. */
- PSWSetUpath(ptsAlarmBot, sizeof (ptsAlarmBot)/sizeof (float),
- opsAlarmBot, sizeof (opsAlarmBot)/sizeof (char));
- upathAlarmBot = DPSDefineUserObject(0);
-
- return self;
- }
-
- /*
- * If a user object has not been allocated, then a gstate has also not been
- * allocated. As a result, create a gstate before defining the user object.
- * If a user object exists, then copy the new gstate into the old
- * structure. No need to redefine the user object because
- * it still refers to the same structure. The PSpop() pops the result of
- * PScurrentgstate() off of the stack.
- */
- static int definegstate(gstate, offsetx, offsety, color, linewidth)
- int gstate;
- float offsetx, offsety, color, linewidth;
- {
- PSgsave();
- PSWSetGstate(offsetx, offsety, color, linewidth);
- if (!gstate)
- {
- PSgstate();
- gstate = DPSDefineUserObject(gstate);
- }
- else
- {
- PScurrentgstate(gstate);
- PSpop();
- }
- PSgrestore();
-
- return gstate;
- }
-
- /*
- * Redefine the gsates because the CTM has changed as the result
- * of the scale:: method.
- */
- - defineGStates
- {
- float angle;
-
- NXPoint center;
-
- struct timeval timeofDay;
- struct tm *localTime;
-
- if (window)
- {
- center.x = floor(bounds.size.width/2);
- center.y = floor(bounds.size.height/2);
-
- [[animatorId startEntry] resetRealTime];
-
- [self lockFocus];
- gettimeofday(&timeofDay, NULL);
- localTime = localtime(&timeofDay.tv_sec);
-
- angleHour = ((localTime->tm_hour % 12) + localTime->tm_min/60.0) * DEGHOUR;
- gstateHour = definegstate (gstateHour, center.x, center.y,
- CLRHANDS - 0.2, LNWIDHANDS);
-
- angleMin = (localTime->tm_min + localTime->tm_sec/60.0) * DEGMIN;
- gstateMin = definegstate(gstateMin, center.x + OFFSETHANDSX,
- center.y + OFFSETHANDSY, CLRHANDS - 0.2, LNWIDHANDS);
-
- angleSec = localTime->tm_sec * DEGMIN;
- gstateSec = definegstate(gstateSec,
- center.x + (2 * OFFSETHANDSX),
- center.y + (2 * OFFSETHANDSY),
- CLRSECOND, LNWIDSECOND);
-
- gstateShad = definegstate(gstateShad,
- center.x + (2 * OFFSETHANDSX) + OFFSETSHADX,
- center.y + (2 * OFFSETHANDSY) + OFFSETSHADY,
- CLRSHADOW, LNWIDSECOND);
- [self unlockFocus];
- }
-
- return self;
- }
-
- /*
- * This method changes the title of the menu cell according to the
- * value of the trace variable.
- */
- -trace:sender
- {
- trace = YES;
-
- return self;
- }
-
- /* Messaged by the Animator object after a timed entry has been received. */
- - tick:sender
- {
- angleSec = angleSec + TICKSEC;
- angleMin = angleMin + TICKMIN;
- angleHour = angleHour + TICKHOUR;
-
- [self display];
-
- return self;
- }
-
- /*
- * Scales the view and then redefines the graphic states.
- * The graphic state objects pick up the scaled view upon redefinition.
- */
- - sizeTo:(NXCoord)width :(NXCoord)height
- {
- NXRect xframe;
-
- [animatorId stopEntry];
-
- xframe = frame;
- [super sizeTo:width :height];
-
- if (xframe.size.width && xframe.size.height)
- {
- [self scale:width/xframe.size.width :height/xframe.size.height];
- [self drawFace];
- [self defineGStates];
- }
-
- return self;
- }
-
- /* Enter a modal loop to redraw the alarm hand per mouse drag event. */
- - setAlarm:(NXEvent *)event
- {
- int old_mask;
-
- NXPoint p, center;
-
- NXEvent peek;
-
- center.x = floor(bounds.size.width/2);
- center.y = floor(bounds.size.height/2);
-
- old_mask = [window addToEventMask:NX_MOUSEUPMASK|
- NX_MOUSEDRAGGEDMASK|NX_TIMERMASK];
- event = [NXApp getNextEvent:NX_MOUSEUPMASK|
- NX_MOUSEDRAGGEDMASK|NX_TIMERMASK];
-
- [self lockFocus];
- while (event->type != NX_MOUSEUP)
- {
- if (event->type == NX_TIMER)
- {
- angleSec = angleSec + TICKSEC;
- angleMin = angleMin + TICKMIN;
- angleHour = angleHour + TICKHOUR;
- if (![NXApp peekNextEvent:NX_MOUSEDRAGGEDMASK into:&peek])
- event = [NXApp getNextEvent:NX_MOUSEDRAGGEDMASK];
- }
-
- if (event->type == NX_MOUSEDRAGGED)
- {
- p = event->location;
- [self convertPoint:&p fromView:nil];
- angleAlarm = atan((p.y - center.y)/(p.x - center.x))/RADIAN - 90;
- if (p.x - center.x < 0)
- angleAlarm -= 180;
- if ([NXApp peekNextEvent:NX_TIMERMASK into:&peek
- waitFor:0 threshold:NX_BASETHRESHOLD])
- {
- angleSec = angleSec + TICKSEC;
- angleMin = angleMin + TICKMIN;
- angleHour = angleHour + TICKHOUR;
- event = [NXApp getNextEvent:NX_TIMERMASK];
- }
- }
-
- PSgsave();
- [self drawSelf:&bounds :1];
- PSgrestore();
-
- [window flushWindow];
- NXPing();
-
- event = [NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK|NX_TIMERMASK
- waitFor:1000 threshold:NX_BASETHRESHOLD];
- }
-
- [window setEventMask:old_mask];
-
- return self;
- }
-
- /* Set the hit detection userpath upon a mouse down. */
- - setHitPoint:(const NXPoint *)p
- {
- float z;
-
- NXPoint pt;
-
- pt.x = p->x - floor(bounds.size.width/2);
- pt.y = p->y - floor(bounds.size.height/2);
-
- z = sqrt (pt.x * pt.x + pt.y * pt.y);
- pt.x = pt.x - (z * sin(ABS(angleAlarm) * RADIAN));
- pt.y = pt.y + z - z * cos(ABS(angleAlarm) * RADIAN);
-
- /* Bounding Box */
- hitPoint.pts[0] = floor(pt.x - HITSETTING/2);
- hitPoint.pts[1] = floor(pt.y - HITSETTING/2);
- hitPoint.pts[2] = ceil(pt.x + HITSETTING/2);
- hitPoint.pts[3] = ceil(pt.y + HITSETTING/2);
-
- /* Moveto */
- hitPoint.pts[4] = pt.x - HITSETTING/2;
- hitPoint.pts[5] = pt.y - HITSETTING/2;
-
- /* Rlineto's */
- hitPoint.pts[7] = HITSETTING;
- hitPoint.pts[8] = HITSETTING;
- hitPoint.pts[11] = -HITSETTING;
-
- return self;
- }
-
- /*
- * Check for hit detection. No boundary check is made because the
- * alarm hand can reside in pretty much the whole view.
- */
- - (BOOL) isHit:(const NXPoint *) p
- {
- int hit;
-
- [self setHitPoint:p];
- PSgsave();
- PSWInstallGstate(gstateHour, angleAlarm);
- PSWHitPath(upathAlarmTop, upathAlarmBot, hitPoint.pts,
- hitPoint.num_pts, hitPoint.ops, hitPoint.num_ops, &hit);
- PSgrestore();
-
- return (BOOL) hit;
- }
-
- /* This method handles a mouse down. */
- - mouseDown:(NXEvent *)event
- {
- NXPoint p;
-
- p = event->location;
- [self convertPoint:&p fromView:nil];
-
- if ([self isHit:&p])
- [self setAlarm:event];
-
- return self;
- }
-
- /*
- * Either draws with gstates or doesn't. A slight performance advantage is
- * gained with gstates but they use up an appreciable amount of memory
- * so they should be used judiciously.
- */
- - setStateAndDraw
- {
- NXPoint center;
-
- if (gstatesOn)
- {
- PSWInstallGstate(gstateHour, angleAlarm);
- drawClockHand(self, ALARM);
-
- PSWInstallGstate(gstateHour, angleHour);
- drawClockHand(self, HOUR);
-
- PSWInstallGstate(gstateMin, angleMin);
- drawClockHand(self, MINUTE);
-
- PSWInstallGstate(gstateShad, angleSec);
- drawClockHand(self, SHADOW);
-
- PSWInstallGstate(gstateSec, angleSec);
- drawClockHand(self, SECOND);
- }
- else
- {
- center.x = floor(bounds.size.width/2);
- center.y = floor(bounds.size.height/2);
-
- PSgsave();
- PStranslate(center.x, center.y);
- PSrotate(angleAlarm);
- drawClockHand(self, ALARM);
- PSgrestore();
-
- PSgsave();
- PSsetgray(CLRHANDS - 0.2);
- PSsetlinewidth(LNWIDHANDS);
- PStranslate(center.x , center.y);
- PSrotate(angleHour);
- drawClockHand(self, HOUR);
- PSgrestore();
-
- PSgsave();
- PSsetgray(CLRHANDS - 0.2);
- PSsetlinewidth(LNWIDHANDS);
- PStranslate(center.x + OFFSETHANDSX,
- center.y + OFFSETHANDSY);
- PSrotate(angleMin);
- drawClockHand(self, MINUTE);
- PSgrestore();
-
- PSgsave();
- PSsetgray(CLRSHADOW);
- PStranslate(center.x + (2*OFFSETHANDSX) + OFFSETSHADX,
- center.y + (2*OFFSETHANDSY) + OFFSETSHADY);
- PSrotate(angleSec);
- drawClockHand(self, SHADOW);
- PSgrestore();
-
- PSgsave();
- PSsetgray(CLRSECOND);
- PSsetlinewidth(LNWIDSECOND);
- PStranslate(center.x + OFFSETHANDSX + OFFSETSHADX,
- center.y + OFFSETHANDSY + OFFSETSHADY);
- PSrotate(angleSec);
- drawClockHand(self, SECOND);
- PSgrestore();
- }
- }
-
- /*
- * Draws the clock hands either as stored in the server
- * or by sending them each time.
- */
- static void drawClockHand(id self, int hand)
- {
- if (self->upathsServer)
- {
- switch(hand)
- {
- case ALARM:
- PSsetgray(CLRALARMTOP);
- PSWUpathFill(self->upathAlarmTop);
- PSsetgray(CLRALARMBOT);
- PSWUpathFill(self->upathAlarmBot);
- break;
- case HOUR:
- PSWUpathStrokeFill(self->upathHour);
- break;
- case MINUTE:
- PSWUpathStrokeFill(self->upathMin);
- break;
- case SHADOW:
- PSWUpathFill(self->upathSec);
- break;
- case SECOND:
- PSWUpathFill(self->upathSec);
- PSWDrawCircle(CLRSECOND - 0.2);
- break;
- }
- }
- else
- {
- switch(hand)
- {
- case ALARM:
- PSsetgray(CLRALARMTOP);
- DPSDoUserPath(&ptsAlarmTop[4], sizeof (ptsAlarmTop)/sizeof (float) - 4,
- dps_float, &opsAlarmTop[1], sizeof (opsAlarmTop)/sizeof (char) -1,
- ptsAlarmTop, dps_ufill);
- PSsetgray(CLRALARMBOT);
- DPSDoUserPath(&ptsAlarmBot[4], sizeof (ptsAlarmBot)/sizeof (float) - 4,
- dps_float, &opsAlarmBot[1], sizeof (opsAlarmBot)/sizeof (char) - 1,
- ptsAlarmBot, dps_ufill);
- break;
- case HOUR:
- DPSDoUserPath(&ptsHour[4], sizeof (ptsHour)/sizeof (float) - 4,
- dps_float, &opsHour[1], sizeof (opsHour)/sizeof (char) - 1,
- ptsHour, dps_ustroke);
- PSsetgray(CLRHANDS);
- DPSDoUserPath(&ptsHour[4], sizeof (ptsHour)/sizeof (float) - 4,
- dps_float, &opsHour[1], sizeof (opsHour)/sizeof (char) - 1,
- ptsHour, dps_ufill);
- break;
- case MINUTE:
- DPSDoUserPath(&ptsMin[4], sizeof (ptsMin)/sizeof (float) - 4,
- dps_float, &opsMin[1], sizeof (opsMin)/sizeof (char) - 1,
- ptsMin, dps_ustroke);
- PSsetgray(CLRHANDS);
- DPSDoUserPath(&ptsMin[4], sizeof (ptsMin)/sizeof (float) - 4,
- dps_float, &opsMin[1], sizeof (opsMin)/sizeof (char) - 1,
- ptsMin, dps_ufill);
- break;
- case SHADOW:
- DPSDoUserPath(&ptsSec[4], sizeof (ptsSec)/sizeof (float) - 4,
- dps_float, &opsSec[1], sizeof (opsSec)/sizeof (char) - 1,
- ptsSec, dps_ufill);
- break;
- case SECOND:
- DPSDoUserPath(&ptsSec[4], sizeof (ptsSec)/sizeof (float) - 4,
- dps_float, &opsSec[1], sizeof (opsSec)/sizeof (char) - 1,
- ptsSec, dps_ufill);
- PSWDrawCircle(CLRSECOND - 0.2);
- break;
- }
- }
- }
-
- - drawSelf:(NXRect *)r :(int) count
- {
- int ElapsedTime;
-
- [displayTime setStringValue:""];
-
- PSWMarkTime (); NXPing ();
- if (trace)
- DPSTraceContext(DPSGetCurrentContext(), YES);
- [imageId composite:NX_COPY toPoint:&bounds.origin];
- [self setStateAndDraw];
- if (trace)
- DPSTraceContext(DPSGetCurrentContext(), NO);
- PSWReturnTime (&ElapsedTime);
-
- trace = NO;
- totalTime += ElapsedTime;
- ++numIterations;
- [displayTime setIntValue:(totalTime/numIterations)];
-
- return self;
- }
-
- @end
-