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.
*
* An offscreen buffer, bufferId, is used to draw into and then
* this buffer is composited onscreen. This technique allows for the
* separation of the static drawing from the temporal drawing (modal
* loop redrawing and control point display). The static drawing takes
* place in the buffer while the temporal drawing takes place in this view.
* The static drawing is stuff that is complex and that will stay around for
* a while. Saving this drawing in a buffer elimates having to redraw it
* for something simple like drawing a control point or something.
* (The bufferId is the content view of a plain window the size of this view);
*
* Version: 2.0
* Author: Ken Fromm
* History:
* 03-17-91 Added this comment, fixed the preview exporting
* section.
*/
#import "DrawingView.h"
#import "Document.h"
#import "GraphicImport.h"
#import "SaveAsPanel.h"
#import "epsf.h"
#import "DrawingViewWraps.h"
#import <appkit/Cell.h>
#import <appkit/ClipView.h>
#import <appkit/Matrix.h>
#import <appkit/NXCursor.h>
#import <appkit/NXImage.h>
#import <appkit/NXBitmapImageRep.h>
#import <appkit/Text.h>
#import <appkit/nextstd.h>
#import <dpsclient/dpsclient.h>
#import <dpsclient/wraps.h>
#import <math.h>
extern char ControlFont[ ];
extern const NXRect DefaultWindowRect;
static char EpsfProcSet[] = "EPSF_Illustrator_abbrev 0 0";
void compositeBuffer(int gstate, const NXRect *srce, const NXPoint *dest, int op)
{
PScomposite(NX_X(srce), NX_Y(srce), NX_WIDTH(srce), NX_HEIGHT(srce),
gstate, dest->x, dest->y, op);
}
/*
* The buffer is used to prevent unnecessary drawing by
* retaining the image offscreen.
*
* Create a plain window the size of the rectangle passed in and
* then insert a view into the window as a subview.
*/
static id createBuffer(const NXSize *size)
{
id buffer, window;
NXRect contRect;
contRect.origin.x = contRect.origin.y = 0;
contRect.size = *size;
window = [Window newContent:&contRect
style:NX_PLAINSTYLE
backing:NX_RETAINED
buttonMask:0
defer:NO] ;
buffer = [[[View newFrame:&contRect] allocateGState] setClipping:NO];
[[window setContentView:buffer ] free];
[ window display];
return buffer;
}
@implementation DrawingView
+newFrame:(const NXRect *) frameRect
{
self = [super newFrame:frameRect];
[[self allocateGState] setClipping:NO];
bufferId = createBuffer(&frameRect->size);
return self;
}
- free
{
[graphicId free];
return [super free];
}
- buffer
{
return bufferId;
}
- image
{
return imageId;
}
- (float) controlPointSize
{
return FONTSIZE;
}
- resetCursorRects
{
[self addCursorRect:&bounds cursor:[NXApp cursor]];
return self;
}
/*
* This method copies the PostScript code for the graphics and writes it to the
* stream passed in. Includes the preview image when appropriate.
*/
- writePSToStream:(NXStream *) stream
{
id nximageId;
NXRect bbox;
if (stream)
{
nximageId = NULL;
imageId = NULL;
[graphicId getBounds:&bbox];
if ([[SaveAsPanel new] format] == SAVE_EPSPREVIEW)
{
nximageId = [[NXImage alloc] initSize:&bbox.size];
[nximageId useCacheWithDepth:NX_TwoBitGrayDepth];
if ([nximageId lockFocus])
{
PStranslate(-bbox.origin.x, -bbox.origin.y);
PSsetgray(NX_WHITE);
NXRectFill(&bbox);
[graphicId drawObject:&bbox withFlags:NOFLAGS inView:self];
imageId = [[NXBitmapImageRep alloc] initData:NULL fromRect:&bbox];
[nximageId unlockFocus];
}
}
[self copyPSCodeInside:&bbox to:stream];
[nximageId free];
[imageId free];
imageId = NULL;
}
return self;
}
/* Deletes the epsf object if it is selected. */
- delete:sender
{
float knobsize;
NXRect rect;
if ([graphicId selected])
{
knobsize = -[self controlPointSize];
[graphicId getBounds:&rect];
NXInsetRect(&rect, knobsize, knobsize);
[graphicId free];
graphicId = NULL;
[self display:&rect :1];
}
return self;
}
/*
* Constrain the point within the view. An offset is needed because when
* an object is moved, it is often grabbed in the center of the object. If the
* lower left offset and the upper right offset were not included then part of
* the object could be moved off of the view. (In some applications, that might
* be allowed but in this one the object is constrained to always lie in the
* page.)
*/
- constrainPoint:(NXPoint *)aPt withOffset:(const NXSize*)llOffset :(const NXSize*)urOffset
{
float margin;
NXPoint viewMin, viewMax;
margin = ceil(FONTSIZE/2);
viewMin.x = bounds.origin.x + llOffset->width + margin;
viewMin.y = bounds.origin.y + llOffset->height + margin;
viewMax.x = bounds.origin.x + bounds.size.width - urOffset->width - margin;
viewMax.y = bounds.origin.y + bounds.size.height - urOffset->height - margin;
aPt->x = MAX(viewMin.x, aPt->x);
aPt->y = MAX(viewMin.y, aPt->y);
aPt->x = MIN(viewMax.x, aPt->x);
aPt->y = MIN(viewMax.y, aPt->y);
return self;
}
/*
* Constrain a rectangle within the view.
*/
- constrainRect:(NXRect *)aRect
{
float margin;
NXPoint viewMin, viewMax;
margin = ceil(FONTSIZE/2);
viewMin.x = bounds.origin.x + margin;
viewMin.y = bounds.origin.y + margin;
viewMax.x = bounds.origin.x + bounds.size.width - aRect->size.width - margin;
viewMax.y = bounds.origin.y + bounds.size.height - aRect->size.height - margin;
aRect->origin.x = MAX(viewMin.x, aRect->origin.x);
aRect->origin.y = MAX(viewMin.y, aRect->origin.y);
aRect->origin.x = MIN(viewMax.x, aRect->origin.x );
aRect->origin.y = MIN(viewMax.y, aRect->origin.y);
return self;
}
/*
* Redraws the graphic. The image from the buffer is composited
* into the window and then the changed object is drawn atop the
* old image. A copy of the image is necessary because if the
* window were to allow scrolling the buffer would also have to be
* scrolled. Were this to happen the old image might have to be redrawn.
* As a result, a copy is created and the changes performed on the
* copy. Care is taken to limit the amount of area that must be
* composited and redrawn.
*
* Even though scrolling is not allowed in this instance, a copy is
* created anyways.
*/
- redrawObject:(int) pt_num
{
id copyId;
BOOL tracking,
dirtyFlag = NO;
int old_mask;
float knobsize;
NXPoint pt, pt_last, pt_old, delta;
NXRect rect_now, rect_start, rect_last;
NXEvent *event;
/*
* The freeTemp method is messaged at the bottom so as not to free
* the shared items.
*/
copyId = [graphicId copy];
knobsize = -[self controlPointSize];
[copyId getBounds:&rect_start];
NXInsetRect(&rect_start, knobsize, knobsize);
rect_now = rect_last = rect_start;
[copyId getPoint:pt_num :&pt_last];
pt_old = pt_last;
old_mask = [window addToEventMask:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
event = [NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
if (event->type != NX_MOUSEUP)
{
tracking = YES;
while (tracking)
{
pt = pt_old = event->location;
[self convertPoint:&pt fromView:nil];
[copyId constrainPoint:&pt forPtNum:&pt_num
inRect:&bounds withFlags:event->flags];
delta.x = pt.x - pt_last.x;
delta.y = pt.y - pt_last.y;
if (delta.x || delta.y)
{
dirtyFlag = YES;
/* Change the point location and get the new bounds. */
[copyId setPoint:pt_num :&delta];
[copyId getBounds:&rect_now];
NXInsetRect(&rect_now, knobsize, knobsize);
/* Composite the old image and then redraw the new one. */
compositeBuffer([bufferId gState], &rect_last, &rect_last.origin, NX_COPY);
[self drawObject:copyId forRect:&rect_now withFlags:REDRAWFLAG];
[self drawControl:copyId forRect:&rect_now withFlags:NOFLAGS];
/* Sync up the drawing so it proceeds a little smoother. */
[window flushWindow];
NXPing();
rect_last = rect_now;
pt_last = pt;
}
event = [NXApp getNextEvent:NX_MOUSEUPMASK|
NX_MOUSEDRAGGEDMASK];
tracking = (event->type != NX_MOUSEUP);
}
}
[window setEventMask:old_mask];
[graphicId freeTemp];
graphicId = copyId;
if (dirtyFlag)
{
/*
* The view has already been focused and we know what
* has to be redrawn so call drawSelf:: instead of display
*/
NXUnionRect(&rect_last, &rect_start);
[self drawSelf:&rect_start :1];
[window flushWindow];
NXPing();
}
return self;
}
/*
* Moves the selected objects by performing a translate before drawing
* the objects. This approach is used because the objects are drawn
* into windows and drawing simply means compositing the windows.
*
* The offsets constrain the selected object to stay within the dimensions
* of the view.
*/
- moveObject:(NXEvent *)event
{
BOOL tracking,
dirtyFlag = NO;
int old_mask;
float knobsize;
NXSize llOffset, urOffset;
NXPoint pt, pt_last, pt_old, delta;
NXRect rect_now, rect_start, rect_last;
knobsize = -[self controlPointSize];
[graphicId getBounds:&rect_start];
NXInsetRect(&rect_start, knobsize, knobsize);
rect_now = rect_last = rect_start;
pt_last = pt_old = event->location;
[self convertPoint:&pt_last fromView:nil];
/* Calculate where the mouse point falls relative to the object. */
llOffset.width = pt_last.x - rect_start.origin.x;
llOffset.height = pt_last.y - rect_start.origin.y;
urOffset.width = rect_start.origin.x + rect_start.size.width - pt_last.x;
urOffset.height = rect_start.origin.y + rect_start.size.height - pt_last.y;
/* Return nil if the the mouse was not dragged. */
old_mask = [window addToEventMask:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
event = [NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
if (event->type != NX_MOUSEUP)
{
tracking = YES;
while (tracking)
{
pt = pt_old = event->location;
[self convertPoint:&pt fromView:nil];
[self constrainPoint:&pt withOffset:&llOffset :&urOffset];
[self constrainPoint:&pt_last withOffset:&llOffset :&urOffset];
delta.x = pt.x - pt_last.x;
delta.y = pt.y - pt_last.y;
if (delta.x || delta.y)
{
dirtyFlag = YES;
NXOffsetRect(&rect_now, delta.x, delta.y);
[self constrainRect:&rect_now];
/*
* Composite the old image into the window and then
* translate the user space and draw the graphicId object.
*/
compositeBuffer([bufferId gState], &rect_last, &rect_last.origin, NX_COPY);
PSgsave();
PStranslate(rect_now.origin.x - rect_start.origin.x,
rect_now.origin.y - rect_start.origin.y);
[self drawObject:graphicId forRect:&rect_start withFlags:MOVEFLAG];
[self drawControl:graphicId forRect:&rect_start
withFlags:NOFLAGS];
PSgrestore();
[window flushWindow];
NXPing();
rect_last = rect_now;
pt_last = pt;
}
event = [NXApp getNextEvent:NX_MOUSEUPMASK|
NX_MOUSEDRAGGEDMASK];
tracking = (event->type != NX_MOUSEUP);
}
if (dirtyFlag)
{
delta.x = rect_now.origin.x - rect_start.origin.x;
delta.y = rect_now.origin.y - rect_start.origin.y; [graphicId moveAll:&delta];
/*
* The view has already been focused and we know what
* has to be redrawn so call drawSelf:: instead of display
*/
NXUnionRect(&rect_now, &rect_start);
[self drawSelf:&rect_start :1];
[window flushWindow];
NXPing();
}
}
[window setEventMask:old_mask];
return self;
}
/* Check to see whether a control point has been hit. */
- checkControl:(const NXPoint *) p :(int *) pt_num
{
NXRect hitRect;
NXSetRect(&hitRect, p->x - HITSETTING/2, p->y - HITSETTING/2, HITSETTING, HITSETTING);
return [graphicId hitControl:&hitRect :pt_num forSize:[self controlPointSize]];
}
/*
* Check to see whether the epsf object has been hit. Return it if yes.
*/
- checkObject:(const NXPoint *) p
{
UPath *hitPoint;
/* Bounding Box */
hitPoint = [NXApp hitPoint];
hitPoint->pts[0] = floor(p->x - HITSETTING/2);
hitPoint->pts[1] = floor(p->y - HITSETTING/2);
hitPoint->pts[2] = ceil(p->x + HITSETTING/2);
hitPoint->pts[3] = ceil(p->y + HITSETTING/2);
/* Moveto */
hitPoint->pts[4] = p->x - HITSETTING/2;
hitPoint->pts[5] = p->y - HITSETTING/2;
/* Rlineto's */
hitPoint->pts[7] = HITSETTING;
hitPoint->pts[8] = HITSETTING;
hitPoint->pts[11] = -HITSETTING;
return [graphicId hitObject:hitPoint];
}
/*
* Set the object as selected then draw the control points.
*/
- selectObject
{
float knobsize;
NXRect drawRect;
[graphicId setSelected:YES];
knobsize = -[self controlPointSize];
[graphicId getBounds:&drawRect];
NXInsetRect(&drawRect, knobsize, knobsize);
[self drawControl:graphicId forRect:&drawRect withFlags:NOFLAGS];
[window flushWindow];
return self;
}
/*
* Redraw thecontrol points for the occupied portion. The control points
* are drawn in this view since they can be drawn quickly.
*/
- deselectObject
{
float knobsize;
NXRect drawRect;
[graphicId setSelected:NO];
knobsize = -[self controlPointSize];
[graphicId getBounds:&drawRect];
NXInsetRect(&drawRect, knobsize, knobsize);
[self drawControl:graphicId forRect:&drawRect withFlags:CLEARFLAG];
[window flushWindow];
return self;
}
/*
* Test for a mouse down hit on either the control points or the object.
*/
- testObject:(NXEvent *)event
{
int pt_num;
NXPoint p;
p = event->location;
[self convertPoint:&p fromView:nil];
[self lockFocus];
if ([graphicId selected])
{
if ([self checkControl:&p :&pt_num])
[self redrawObject:pt_num];
else if ([self checkObject:&p])
[self moveObject:event];
else
[self deselectObject];
}
else if ([self checkObject:&p])
[self selectObject];
[self unlockFocus];
return self;
}
/*
* Pass the file name to the factory TIFF or EPS object to create a new
* instance. If successful then free the previous epsf object.
*/
- importFile:(const char *) file
{
id tempId;
char *end;
NXStream *stream;
if (file)
{
end = strrchr(file, '.');
if (end)
{
stream = NXMapFile(file, NX_READONLY);
if (stream)
{
if (strncmp(end, ".tiff", 5) == 0 ||
strncmp(end, ".ps", 3) == 0 ||
strncmp(end, ".eps", 4) == 0)
{
tempId = [[GraphicImport alloc] initFromStream:stream];
if (tempId)
{
[tempId setFilename:file];
[self delete:self];
[graphicId free];
graphicId = tempId;
[NXApp setOperation:OP_IMPORT];
return self;
}
NXCloseMemory(stream, NX_FREEBUFFER);
}
else
Notify("Import Error", "Unable to open file.");
}
}
else
Notify("Import Error", "Unable to import file. Unrecognized file type.");
}
return nil;
}
/*
* Place the epsId with its upper left corner at p;
*/
- placeObjectAt:(const NXPoint *) p
{
float knobsize;
NXPoint pt;
NXRect rect_draw;
if (graphicId)
{
pt = *p;
[graphicId getBounds:&rect_draw];
pt.y = pt.y - rect_draw.size.height;
[graphicId setOrigin:&pt];
knobsize = -[self controlPointSize];
[graphicId getBounds:&rect_draw];
NXInsetRect(&rect_draw, knobsize, knobsize);
[self display:&rect_draw :1];
}
return self;
}
/*
* Begins the setup for placing an imported file into the document.
* The object for the file is created and then waits for the mouse
* down to begin placement and sizing. This method first gets the
* object and then messages the redrawObject method to draw
* the subsequent sizing rectangles.
*/
- importObject:(NXEvent *)event
{
float knobsize;
NXPoint p;
NXRect rect_draw;
if (graphicId)
{
p = event->location;
[self convertPoint:&p fromView:nil];
NXSetRect(&rect_draw, p.x, p.y-SIZE_MIN, SIZE_MIN, SIZE_MIN);
[graphicId setBounds:&rect_draw];
knobsize = -[self controlPointSize];
[graphicId getBounds:&rect_draw];
NXInsetRect(&rect_draw, knobsize, knobsize);
[self lockFocus];
[self drawObject:graphicId forRect:&rect_draw withFlags:REDRAWFLAG];
[self drawControl:graphicId forRect:&rect_draw withFlags:NOFLAGS];
[self redrawObject:8];
if ([graphicId error])
{
[graphicId getBounds:&rect_draw];
NXInsetRect(&rect_draw, knobsize, knobsize);
[graphicId free];
graphicId = NULL;
[self display:&rect_draw :1];
}
else
[self selectObject];
[self unlockFocus];
}
return self;
}
/*
* Depending on the current operation, check for selection, zoom or
* import a file.
*/
- mouseDown:(NXEvent *)event
{
int operation;
operation = [NXApp operation];
switch (operation)
{
case OP_SELECT:
[self testObject:event];
break;
case OP_IMPORT:
[self importObject:event];
[NXApp setOperation:OP_SELECT];
break;
}
return self;
}
/*
* Deletes the epsf object if selected.
*/
- keyDown:(NXEvent *) event
{
if ([NXApp operation] == OP_SELECT &&
event->data.key.charSet == NX_ASCIISET &&
event->data.key.charCode == NX_DELETE)
return [self delete:self];
else
return nil;
}
/*
* Draw the control points using the user path buffer to hold
* the data for the xyshow.
*/
- drawControl:object forRect:(NXRect *)r withFlags:(int)flags
{
float knobsize;
NXPoint lastpoint;
NXRect rect;
UPath *upathBuffer;
if (r)
rect = *r;
else
[self getVisibleRect:&rect];
if (flags & CLEARFLAG)
compositeBuffer([bufferId gState], &rect, &rect.origin, NX_COPY);
if ([object selected])
{
lastpoint.x = 0;
lastpoint.y = 0;
upathBuffer = [NXApp upathBuffer];
upathBuffer->num_ops = 0;
upathBuffer->num_pts = 0;
knobsize = [self controlPointSize];
NXInsetRect(&rect, -knobsize/2, -knobsize/2);
[object putControlPoints:upathBuffer forRect:&rect :&lastpoint];
upathBuffer->ops[upathBuffer->num_ops] = 0;
upathBuffer->pts[upathBuffer->num_pts] = 0;
upathBuffer->pts[upathBuffer->num_pts + 1] = 0;
if (upathBuffer->num_ops > 0)
{
PSWSetControlPoints(ControlFont, knobsize, NX_BLACK, 0.15);
PSWDrawControlPoints(upathBuffer->pts[0], upathBuffer->pts[1],
&upathBuffer->pts[2], upathBuffer->num_pts, upathBuffer->ops);
}
}
return self;
}
- drawObject:object forRect:(NXRect *)r withFlags:(int) flags
{
NXRect rect;
if (r)
rect = *r;
else
[self getVisibleRect:&rect];
[object drawObject:&rect withFlags:flags inView:self];
return self;
}
/*
* Fill in the background of the rectangle and then draw the epsf object.
* If NX_DRAWING, then draw into the buffer and composite it into
* the window.
*/
- drawSelf:(NXRect *)r :(int) count
{
if (NXDrawingStatus == NX_DRAWING)
{
[bufferId lockFocus];
PSsetgray(NX_WHITE);
NXRectFill(r);
}
[self drawObject:graphicId forRect:r withFlags:REFRESHFLAG];
if (NXDrawingStatus == NX_DRAWING && !imageId)
{
[bufferId unlockFocus];
compositeBuffer([bufferId gState], r, &r->origin, NX_COPY);
[self drawControl:graphicId forRect:r withFlags:NOFLAGS];
}
return self;
}
/*
* This method is only overridden to eliminate during a copy
* the rectclip and gsave/grestore pairing that results from
* a lockFocus. These are usually harmless operations but
* they interfere with trying to produce Illustrator format files.
*/
- display:(NXRect *)r :(int) count :(BOOL)flag
{
if (NXDrawingStatus == NX_COPYING)
{
[self drawSelf:r :count];
DPSFlushContext(DPSGetCurrentContext());
}
else
[super display:r :count :flag];
return self;
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
/*
* Used when printing. Returns the global resources used in the document.
*/
- addResources:(Resource *) resourceDoc
{
NXAtom string;
if (NXDrawingStatus == NX_COPYING)
{
string = NXUniqueString(EpsfProcSet);
if (!resourceDoc[RES_PROCSETS].states[RES_PRESENT])
resourceDoc[RES_PROCSETS].states[RES_PRESENT] = [List new];
[resourceDoc[RES_PROCSETS].states[RES_PRESENT]
addObjectIfAbsent:(id) string];
if (!resourceDoc[RES_PROCSETS].states[RES_SUPPLIED])
resourceDoc[RES_PROCSETS].states[RES_SUPPLIED] = [List new];
[resourceDoc[RES_PROCSETS].states[RES_SUPPLIED]
addObjectIfAbsent:(id) string];
}
return self;
}
/*
* Print the %%DocumentResource comments. A list of the resources is
* accumulated from the epsf files (only one in this case).
* The list is then written to the current context.
*/
- beginResourceComments:(const NXRect *) bbox
{
int i, j;
Resource resourceDoc[RES_NUMTYPES];
bzero(&resourceDoc, sizeof(resourceDoc));
[self addResources:resourceDoc];
[graphicId addResources:resourceDoc for:(NXRect *) bbox];
for (i = 0; i < RES_NUMTYPES; i++)
{
for (j = 0; j < RES_NUMSTATES; j++)
{
if (resourceDoc[i].states[j])
{
WriteEpsfResource(resourceDoc[i].states[j], i, j);
[resourceDoc[i].states[j] free];
}
}
}
return self;
}
/*
* Write out the necessary information. Overridden to include
* the fonts from the EPSF files.
*/
- beginPrologueBBox:(const NXRect *)boundingBox
creationDate:(const char *)dateCreated
createdBy:(const char *)anApplication
fonts:(const char *)fontNames
forWhom:(const char *)user
pages:(int)numPages
title:(const char *)aTitle
{
time_t clock;
DPSContext ctxt;
ctxt = DPSGetCurrentContext();
if (!boundingBox)
boundingBox = &bounds;
if (!dateCreated)
{
clock = time(0);
dateCreated = ctime(&clock);
}
if (!anApplication)
anApplication = [NXApp appName];
if (!user)
user = (char *) getlogin();
if (numPages <= 0)
numPages = 1;
if (!aTitle)
aTitle = [[window delegate] filename];
DPSPrintf(ctxt, "%%!PS-Adobe-2.0 EPSF-1.2\n");
DPSPrintf(ctxt, "%%%%Creator: %s\n", anApplication);
DPSPrintf(ctxt, "%%%%For: %s\n", user);
DPSPrintf(ctxt, "%%%%Title: %s\n", aTitle);
DPSPrintf(ctxt, "%%%%CreationDate: %s", dateCreated);
DPSPrintf(ctxt, "%%%%BoundingBox: %d %d %d %d\n", (int) floor(boundingBox->origin.x),
(int) floor(boundingBox->origin.y),
(int) ceil(boundingBox->origin.x + boundingBox->size.width),
(int) ceil(boundingBox->origin.y + boundingBox->size.height));
if (NXDrawingStatus == NX_COPYING)
DPSPrintf(ctxt, "%%AI3_TemplateBox: %d %d %d %d\n", 306, 396, 306, 396);
if (NXDrawingStatus != NX_COPYING)
DPSPrintf(ctxt, "%%%%Pages: %d\n", numPages);
[self beginResourceComments:boundingBox];
return self;
}
/*
* Includes the abbreviated Illustrator proc set so that
* the eps files produced through Save To will print on their
* own. Also includes the preview data as a comment when
* specified.
*/
- endHeaderComments
{
DPSContext ctxt;
if (NXDrawingStatus == NX_COPYING)
{
ctxt = DPSGetCurrentContext();
DPSPrintf(ctxt, "%%%%EndComments\n\n");
DPSPrintf(ctxt, "%%%%BeginProcSet: EPSF_Illustrator_abbrev 0 0\n");
WriteEpsfProcSetDef ();
DPSPrintf(ctxt, "%%%%EndProcSet\n\n");
if (imageId && [[SaveAsPanel new] format] == SAVE_EPSPREVIEW)
WriteEpsfPreview(imageId);
}
else
[super endHeaderComments];
return self;
}
/*
* If saving in illustrator, override the prologue comment.
*/
- endPrologue
{
DPSContext ctxt;
if (NXDrawingStatus == NX_COPYING)
{
ctxt = DPSGetCurrentContext();
DPSPrintf(ctxt, "%%%%EndProlog\n\n");
}
else
[super endPrologue];
return self;
}
/* Initialize the Illustrator abbreviated proc set. */
- beginSetup
{
DPSContext ctxt;
if (NXDrawingStatus == NX_COPYING)
{
ctxt = DPSGetCurrentContext();
DPSPrintf(ctxt, "%%%%BeginSetup\n");
WriteEpsfProcSetInit();
}
else
[super beginSetup];
return self;
}
- endSetup
{
DPSContext ctxt;
if (NXDrawingStatus == NX_COPYING)
{
ctxt = DPSGetCurrentContext();
DPSPrintf(ctxt, "%%%%EndSetup\n");
}
else
[super endSetup];
return self;
}
/* Terminate the Illustrator abbreviated proc set. */
- beginTrailer
{
DPSContext ctxt;
if (NXDrawingStatus == NX_COPYING)
{
ctxt = DPSGetCurrentContext();
DPSPrintf(ctxt, "%%%%Trailer\n");
WriteEpsfProcSetTerm();
}
else
[super beginTrailer];
return self;
}
- endTrailer
{
if (NXDrawingStatus != NX_COPYING)
[super endTrailer];
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.