1/* EPSExport.m 2 * 3 * Copyright (C) 2000-2012 by vhf interservice GmbH 4 * Author: Ilonka Fleischmann 5 * 6 * created: 2000-12-21 7 * modified: 2012-09-13 (-writeToFile: workaround: keep scaleFactor >= 1.0 not to clip graphics) 8 * 2012-02-07 (-writeToFile: use writeToFile:...encoding:error:) 9 * 10 * This file is part of the vhf Export Library. 11 * 12 * This library is free software; you can redistribute it and/or 13 * modify it under the terms of the vhf Public License as 14 * published by the vhf interservice GmbH. Among other things, 15 * the License requires that the copyright notices and this notice 16 * be preserved on all copies. 17 * 18 * This library is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 21 * See the vhf Public License for more details. 22 * 23 * You should have received a copy of the vhf Public License along 24 * with this library; see the file LICENSE. If not, write to vhf. 25 * 26 * If you want to link this library to your proprietary software, 27 * or for other uses which are not covered by the definitions 28 * laid down in the vhf Public License, vhf also offers a proprietary 29 * license scheme. See the vhf internet pages or ask for details. 30 * 31 * vhf interservice GmbH, Im Marxle 3, 72119 Altingen, Germany 32 * eMail: info@vhf.de 33 * http://www.vhf.de 34 */ 35 36#include <AppKit/AppKit.h> 37#include <VHFShared/vhfCommonFunctions.h> 38#include <VHFShared/VHFStringAdditions.h> // stringByReplacing -> eps export, -writeToFile:... 10.5 compatibility 39#include "App.h" 40#include "EPSExport.h" 41#include "Graphics.h" 42#include "messages.h" 43#include "locations.h" 44#include "PreferencesMacros.h" 45 46@interface EPSExport(PrivateMethods) 47@end 48 49@implementation EPSExport 50 51+ (EPSExport*)epsExport 52{ 53 return [[[EPSExport allocWithZone:[self zone]] init] autorelease]; 54} 55 56/* initialize 57 */ 58- init 59{ 60 return [super init]; 61} 62 63- (void)setDocumentView:view 64{ 65 docView = view; 66} 67 68typedef struct _EPSState 69{ 70 int noPoint; 71 NSPoint point; 72 BOOL setBounds; // if we have an clipRect 73 float maxW; 74 NSPoint ll; 75 NSPoint ur; 76 float width; 77 NSColor *color; 78 BOOL fill; 79}EPSState; 80 81- (NSString*)epsLine:(VLine*)g :(EPSState*)epsState 82{ NSPoint s, e; 83 NSString *str=@""; 84 [(VLine*)g getVertices:&s :&e]; 85 86 if ( /*!epsState->pathMode &&*/ 87 (epsState->noPoint || Diff(epsState->point.x, s.x) > TOLERANCE || Diff(epsState->point.y, s.y) > TOLERANCE) ) 88 { 89 if ( !epsState->noPoint ) 90 str = [str stringByAppendingFormat:@"stroke\n"]; // so we stroke previous graphics 91 92 str = [str stringByAppendingFormat:@"%.0f %.0f moveto\n", s.x, s.y]; 93 if ( epsState->setBounds ) 94 { if ( epsState->ll.x > s.x ) epsState->ll.x = s.x; 95 if ( epsState->ll.y > s.y ) epsState->ll.y = s.y; 96 if ( epsState->ur.x < s.x ) epsState->ur.x = s.x; 97 if ( epsState->ur.y < s.y ) epsState->ur.y = s.y; 98 } 99 } 100 str = [str stringByAppendingFormat:@"%.0f %.0f lineto\n", e.x, e.y]; 101 if ( epsState->setBounds ) 102 { if ( epsState->ll.x > e.x ) epsState->ll.x = e.x; 103 if ( epsState->ll.y > e.y ) epsState->ll.y = e.y; 104 if ( epsState->ur.x < e.x ) epsState->ur.x = e.x; 105 if ( epsState->ur.y < e.y ) epsState->ur.y = e.y; 106 } 107 epsState->point = e; 108 epsState->noPoint = 0; 109 return str; 110} 111 112- (NSString*)epsRectangle:(VRectangle*)g :(EPSState*)epsState 113{ NSPoint o, s; 114 NSString *str=@""; 115 [(VRectangle*)g getVertices:&o :&s]; 116 117 if ( !epsState->noPoint ) // else we have no previous graphics 118 str = [str stringByAppendingFormat:@"stroke\n"]; // so we stroke previous graphics 119 120// if ( /*!epsState->pathMode &&*/ 121// (epsState->noPoint || Diff(epsState->point.x, o.x) > TOLERANCE || Diff(epsState->point.y, o.y) > TOLERANCE) ) 122 { str = [str stringByAppendingFormat:@"%.0f %.0f moveto\n", o.x, o.y]; 123 if ( epsState->setBounds ) 124 { if ( epsState->ll.x > o.x ) epsState->ll.x = o.x; 125 if ( epsState->ll.y > o.y ) epsState->ll.y = o.y; 126 } 127 } 128 if ( [g filled] ) 129 str = [str stringByAppendingFormat:@"%.0f %.0f %.0f %.0f rectfill\n", o.x, o.y, s.x, s.y]; 130 else 131 str = [str stringByAppendingFormat:@"%.0f %.0f %.0f %.0f rectstroke\n", o.x, o.y, s.x, s.y]; 132 if ( epsState->setBounds ) 133 { if ( epsState->ur.x < o.x+s.x ) epsState->ur.x = o.x+s.x; 134 if ( epsState->ur.y < o.y+s.y ) epsState->ur.y = o.y+s.y; 135 } 136 return str; 137} 138 139- (NSString*)epsArc:(VArc*)g :(EPSState*)epsState 140{ NSString *str=@""; 141 NSPoint c, s; 142 float a, ba, r; 143 144 [(VArc*)g getCenter:&c start:&s angle:&a]; 145 ba = [(VArc*)g begAngle]; 146 r = [(VArc*)g radius]; 147 148 if ( a == 360.0 && !epsState->noPoint ) // else we have no previous graphics 149 str = [str stringByAppendingFormat:@"stroke\n"]; // so we stroke previous graphics 150 151 if ( /*!epsState->pathMode &&*/ 152 (epsState->noPoint || Diff(epsState->point.x, s.x) > TOLERANCE || Diff(epsState->point.y, s.y) > TOLERANCE) ) 153 str = [str stringByAppendingFormat:@"%.0f %.0f moveto\n", s.x, s.y]; 154 if ( a > 0 ) 155 { float ea = ba+a; 156 if (ea > 360.0) ea -= 360.0; 157 str = [str stringByAppendingFormat:@"%.0f %.0f %.0f %.0f %.0f arc\n", c.x, c.y, r, ba, ea]; 158 } 159 else 160 { float ea = ba+a; 161 if (ea < 0) ea += 360.0; 162 str = [str stringByAppendingFormat:@"%.0f %.0f %.0f %.0f %.0f arcn\n", c.x, c.y, r, ba, ea]; 163 } 164 if ( epsState->setBounds ) 165 { NSRect b = [(VArc*)g bounds]; 166 if ( epsState->ll.x > b.origin.x ) epsState->ll.x = b.origin.x; 167 if ( epsState->ll.y > b.origin.y ) epsState->ll.y = b.origin.y; 168 if ( epsState->ur.x < b.origin.x+b.size.width ) epsState->ur.x = b.origin.x+b.size.width; 169 if ( epsState->ur.y < b.origin.y+b.size.height ) epsState->ur.y = b.origin.y+b.size.height; 170 } 171 epsState->point = [(VArc*)g pointWithNum:-1]; // default is end 172 epsState->noPoint = 0; 173 174 return str; 175} 176 177- (NSString*)epsCurve:(VCurve*)g :(EPSState*)epsState 178{ NSPoint p0, p1, p2, p3; 179 NSString *str=@""; 180 [(VCurve*)g getVertices:&p0 :&p1 :&p2 :&p3]; 181 182 if ( /*!epsState->pathMode &&*/ 183 (epsState->noPoint || Diff(epsState->point.x, p0.x) > TOLERANCE || Diff(epsState->point.y, p0.y) > TOLERANCE) ) 184 str = [str stringByAppendingFormat:@"%.0f %.0f moveto\n", p0.x, p0.y]; 185 str = [str stringByAppendingFormat:@"%.0f %.0f %.0f %.0f %.0f %.0f curveto\n", p1.x, p1.y, p2.x, p2.y, p3.x, p3.y]; 186 if ( epsState->setBounds ) 187 { NSRect b = [(VArc*)g bounds]; 188 if ( epsState->ll.x > b.origin.x ) epsState->ll.x = b.origin.x; 189 if ( epsState->ll.y > b.origin.y ) epsState->ll.y = b.origin.y; 190 if ( epsState->ur.x < b.origin.x+b.size.width ) epsState->ur.x = b.origin.x+b.size.width; 191 if ( epsState->ur.y < b.origin.y+b.size.height ) epsState->ur.y = b.origin.y+b.size.height; 192 } 193 epsState->point = p3; 194 epsState->noPoint = 0; 195 return str; 196} 197 198- (NSString*)epsPath:(VPath*)g :(EPSState*)epsState 199{ NSString *str=@""; 200 int i, cnt=[[g list] count]; 201 202 if ( !cnt ) 203 return str; 204 205 str = [str stringByAppendingFormat:@"gsave\n"]; 206 207 str = [str stringByAppendingFormat:@"newpath\n"]; 208epsState->noPoint = 1; 209 for (i=0; i<cnt; i++) 210 { VGraphic *gr = [[g list] objectAtIndex:i]; 211 212// if ( i == 1 ) epsState->pathMode = 1; // first graphic need a moveto 213 214 if ( [gr isKindOfClass:[VLine class]] ) 215 str = [str stringByAppendingString:[self epsLine:(VLine*)gr :epsState]]; // move if possible and lineto 216 else if ( [gr isKindOfClass:[VRectangle class]] ) 217 str = [str stringByAppendingString:[self epsRectangle:(VRectangle*)gr :epsState]]; 218 else if ( [gr isKindOfClass:[VArc class]] ) 219 str = [str stringByAppendingString:[self epsArc:(VArc*)gr :epsState]]; 220 else if ( [gr isKindOfClass:[VCurve class]] ) 221 str = [str stringByAppendingString:[self epsCurve:(VCurve*)gr :epsState]]; 222 else NSLog(@"epsPath gr type not implemented\n"); 223// else if ( [g isKindOfClass:[VGroup class]] && [gr isKindOfClass:[VPath class]] ) 224// str = [str stringByAppendingString:[self epsPath:gr :epsState]]; 225 } 226 str = [str stringByAppendingFormat:@"closepath\n"]; 227 if ( [g filled] ) 228 str = [str stringByAppendingFormat:@"eofill\n"]; 229 else 230 str = [str stringByAppendingFormat:@"stroke\n"]; 231 232 str = [str stringByAppendingFormat:@"grestore\n"]; // state is the same as before path ! 233 return str; 234} 235 236- (NSString*)epsGroup:(VGroup*)g :(EPSState*)epsState 237{ NSString *str=@""; 238 int i, cnt=[[g list] count]; 239 240 if ( !cnt ) 241 return str; 242 243 for (i=0; i<cnt; i++) 244 { VGraphic *gr = [[g list] objectAtIndex:i]; 245 246 if ( ![[gr color] isEqual:epsState->color] ) 247 { 248 if ( [[[gr color] colorSpaceName] isEqual:@"NSCalibratedWhiteColorSpace"] ) 249 str = [str stringByAppendingFormat:@"%.2f setgray\n", [[gr color] whiteComponent]]; 250 else 251 str = [str stringByAppendingFormat:@"%.2f %.2f %.2f setrgbcolor\n", 252 [[gr color] redComponent], [[gr color] greenComponent], [[gr color] blueComponent]]; 253 epsState->color = [gr color]; 254 } 255 if ( epsState->width != [gr width] ) 256 { str = [str stringByAppendingFormat:@"%.2f setlinewidth\n", [gr width]]; 257 epsState->width = [gr width]; 258 if ( epsState->maxW < epsState->width ) epsState->maxW = epsState->width; 259 } 260 261 if ( [gr isKindOfClass:[VLine class]] ) 262 str = [str stringByAppendingString:[self epsLine:(VLine*)gr :epsState]]; // move if possible and lineto 263 else if ( [gr isKindOfClass:[VRectangle class]] ) 264 str = [str stringByAppendingString:[self epsRectangle:(VRectangle*)gr :epsState]]; 265 else if ( [gr isKindOfClass:[VArc class]] ) 266 str = [str stringByAppendingString:[self epsArc:(VArc*)gr :epsState]]; 267 else if ( [gr isKindOfClass:[VCurve class]] ) 268 str = [str stringByAppendingString:[self epsCurve:(VCurve*)gr :epsState]]; 269 else if ( [gr isKindOfClass:[VPath class]] ) 270 str = [str stringByAppendingString:[self epsPath:(VPath*)gr :epsState]]; 271 else if ( [gr isKindOfClass:[VGroup class]] ) 272 str = [str stringByAppendingString:[self epsGroup:(VGroup*)gr :epsState]]; 273 else NSLog(@"epsGroup gr type not implemented\n"); 274 } 275 return str; 276} 277 278- (NSString*)epsImage:(VImage*)g :(EPSState*)epsState 279{ NSString *str=@""; 280 281 282 return str; 283} 284 285- (NSString*)epsVText:(VText*)g :(EPSState*)epsState 286{ NSString *str = @""; 287 NSRect b = [g bounds]; 288 NSPoint o; 289 NSString *curStr; // , *text = [g string]; 290 BOOL filled = [g filled]; 291 float lineHeight = [g lineHeight]; 292 NSScanner *scanner = [NSScanner scannerWithString:[g string]]; 293 NSCharacterSet *skipSet = [NSCharacterSet characterSetWithCharactersInString:@"\n\r"]; 294 int first = 1; 295 296 o = b.origin; 297 o.y += b.size.height - lineHeight; // ??? 298 str = [str stringByAppendingFormat:@"/%@ findfont\n", [[g font] fontName]]; 299 str = [str stringByAppendingFormat:@"%.1f scalefont setfont\n", [[g font] pointSize]]; 300 [scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@""]]; 301 [scanner scanCharactersFromSet:skipSet intoString:NULL]; 302 while ( ![scanner isAtEnd] ) 303 { 304 /* up to location != ' ' */ 305 if ( ![scanner scanUpToCharactersFromSet:skipSet intoString:&curStr] ) 306 curStr = @""; 307 308 curStr = [curStr stringByReplacing:@"\t" by:@" "]; // \t -> 4 or 8 blanks 309 310 if ( !first ) o.y -= lineHeight; 311 first = 0; 312 if ( ![curStr length] ) continue; // simpy \n 313 314 if ( epsState->noPoint || Diff(epsState->point.x, o.x) > TOLERANCE || Diff(epsState->point.y, o.y) > TOLERANCE ) 315 str = [str stringByAppendingFormat:@"%.0f %.0f moveto\n", o.x, o.y]; 316 if ( filled ) 317 { str = [str stringByAppendingFormat:@"(%@) true charpath\n", curStr]; // true -> no stroke ! 318 str = [str stringByAppendingFormat:@"eofill\n"]; 319 } 320 else 321 { str = [str stringByAppendingFormat:@"(%@) false charpath\n"]; 322 str = [str stringByAppendingFormat:@"stroke\n"]; 323 } 324 [scanner scanCharactersFromSet:skipSet intoString:NULL]; 325 } 326 if ( filled ) str = [str stringByAppendingFormat:@"eofill\n"]; 327 else str = [str stringByAppendingFormat:@"stroke\n"]; 328 329 if ( epsState->setBounds ) 330 { if ( epsState->ll.x > b.origin.x ) epsState->ll.x = b.origin.x; 331 if ( epsState->ll.y > b.origin.y ) epsState->ll.y = b.origin.y; 332 if ( epsState->ur.x < b.origin.x+b.size.width ) epsState->ur.x = b.origin.x+b.size.width; 333 if ( epsState->ur.y < b.origin.y+b.size.height ) epsState->ur.y = b.origin.y+b.size.height; 334 } 335 epsState->point = [g pointWithNum:PT_LOWERRIGHT]; 336 epsState->noPoint = 0; 337 return str; 338} 339 340- (BOOL)writeToFile:(NSString*)filename 341{ BOOL savedOk = NO; 342 NSString *backupFilename; 343 NSFileManager *fileManager = [NSFileManager defaultManager]; 344 345 backupFilename = [[[filename stringByDeletingPathExtension] stringByAppendingString:@"~"] 346 stringByAppendingPathExtension:EPS_EXT]; 347 /* file not writable */ 348 if ( [fileManager fileExistsAtPath:filename] && ![fileManager isWritableFileAtPath:filename] ) 349 { NSRunAlertPanel(SAVE_TITLE, CANT_CREATE_BACKUP, nil, nil, nil); 350 return NO; 351 } 352 /* rename to backup */ 353 if ( ([fileManager fileExistsAtPath:backupFilename] && ![fileManager removeFileAtPath:backupFilename handler:nil]) || ([fileManager fileExistsAtPath:filename] && ![fileManager movePath:filename toPath:backupFilename handler:nil]) ) 354 { NSRunAlertPanel(SAVE_TITLE, CANT_CREATE_BACKUP, nil, nil, nil); 355 return NO; 356 } 357 358 { NSArray *list = [docView layerList]; 359 NSString *string; 360 NSData *psData; 361 NSRect bRect; 362 NSPoint ll, ur; 363 int i, cnt; 364 VFloat sf = [docView scaleFactor]; 365 366 // bRect = [docView bounds]; 367 ll.x = ll.y = MAXCOORD; 368 ur.x = ur.y = 0.0; 369 cnt = [list count]; 370 for (i=0; i<cnt; i++) 371 { NSRect rect; 372 LayerObject *lObj = [list objectAtIndex:i]; 373 374 //if ( [lObj type] == LAYER_CLIPPING ) // type 375 // continue; 376 rect = [docView boundsOfArray:[lObj list]]; 377 if ( ![lObj state] || (!rect.size.width && !rect.size.height) ) 378 continue; 379 if ( ll.x > rect.origin.x ) ll.x = rect.origin.x; 380 if ( ll.y > rect.origin.y ) ll.y = rect.origin.y; 381 if ( ur.x < rect.origin.x+rect.size.width ) ur.x = rect.origin.x+rect.size.width; 382 if ( ur.y < rect.origin.y+rect.size.height ) ur.y = rect.origin.y+rect.size.height; 383 } 384 bRect.origin.x = ll.x; bRect.origin.y = ll.y; 385 bRect.size.width = ur.x - ll.x; bRect.size.height = ur.y - ll.y; 386 //bRect.size.width *= (sf > 0.0) ? (sf) : (1.0); 387 //bRect.size.height *= (sf > 0.0) ? (sf) : (1.0); 388 bRect.size.width *= (sf < 1.0) ? (1.0) : (sf); // workaround Apple: otherwise graphics gets clipped 389 bRect.size.height *= (sf < 1.0) ? (1.0) : (sf); 390 psData = [docView dataWithEPSInsideRect:bRect]; 391 string = [[NSString alloc] initWithData:psData encoding:NSASCIIStringEncoding]; 392 //savedOk = [string writeToFile:filename atomically:YES]; 393 savedOk = [string writeToFile:filename atomically:YES 394 encoding:NSUTF8StringEncoding error:NULL]; // >= 10.5 395 [string release]; 396 } 397 398#if 0 399 //else if ( isDirectory && [fileManager createDirectoryAtPath:filename attributes:nil] ) 400 //fileDirectory = [filename stringByDeletingLastPathComponent]; 401 /* save */ 402 //if ([fileManager isWritableFileAtPath:filename]) 403 { NSString *epsStr, *grStr=@""; 404 NSRect clipRect; 405 id layerList = [docView layerList]; 406 int i, lCnt = [layerList count]; 407 EPSState epsState; 408 409 epsState.noPoint = 1; 410 epsState.fill = 0; 411 epsState.color = [NSColor blackColor]; 412 epsState.setBounds = 1; 413 epsState.ll.x = epsState.ll.y = MAXCOORD; 414 epsState.ur.x = epsState.ur.y = 0.0; 415 epsState.maxW = 0; 416 417 grStr = [grStr stringByAppendingFormat:@"1 setlinecap\n"]; 418 grStr = [grStr stringByAppendingFormat:@"1 setlinejoin\n"]; 419 420// 72 25400 div 72 25400 div scale\n 421 422 // first clip rect 423 clipRect.size.width = clipRect.size.height = 0.0; 424 clipRect = [[docView clipObject] bounds]; 425 if ( clipRect.size.width && clipRect.size.height ) 426 { grStr = [grStr stringByAppendingFormat:@"%.0f %.0f %.0f %.0f rectclip\n", clipRect.origin.x, clipRect.origin.y, clipRect.size.width, clipRect.size.height]; 427 epsState.ll.x = clipRect.origin.x; 428 epsState.ll.y = clipRect.origin.y; 429 epsState.ur.x = clipRect.origin.x + clipRect.size.width; 430 epsState.ur.y = clipRect.origin.y + clipRect.size.height; 431 epsState.setBounds = 0; 432 } 433 for (i=(int)[layerList count]-1 ; i >=0 ; i--) 434 { LayerObject *lObj = [layerList objectAtIndex:i]; 435 436 if ([lObj type] == LAYER_CLIPPING || ![lObj state]) // visible - ???????????????????????? 437 continue; 438 { int j, cnt = [[lObj list] count]; 439 440// PageBoundingBox 441// grStr = [grStr stringByAppendingFormat:@"%%Page: 0 1\n"]; // BeginPageSetup EndPageSetup PageTrailer 442 for (j=0; j<cnt; j++) 443 { id g = [[lObj list] objectAtIndex:j]; 444 445 if ( ![g isKindOfClass:[VGroup class]] && ![[g color] isEqual:epsState.color] ) 446 { 447 if ( [[[g color] colorSpaceName] isEqual:@"NSCalibratedWhiteColorSpace"] ) 448 grStr = [grStr stringByAppendingFormat:@"%.2f setgray\n", [[g color] whiteComponent]]; 449 else 450 grStr = [grStr stringByAppendingFormat:@"%.2f %.2f %.2f setrgbcolor\n", 451 [[g color] redComponent], [[g color] greenComponent], [[g color] blueComponent]]; 452 epsState.color = [g color]; 453 } 454 if ( ![g isKindOfClass:[VGroup class]] && epsState.width != [g width] ) 455 { grStr = [grStr stringByAppendingFormat:@"%.2f setlinewidth\n", [g width]]; 456 epsState.width = [g width]; 457 if ( epsState.maxW < epsState.width ) epsState.maxW = epsState.width; 458 } 459 460 if ( [g isKindOfClass:[VLine class]] ) 461 grStr = [grStr stringByAppendingString:[self epsLine:g :&epsState]]; // move if possible and lineto 462 else if ( [g isKindOfClass:[VCurve class]] ) 463 grStr = [grStr stringByAppendingString:[self epsCurve:(VCurve*)g :&epsState]]; 464 else if ( [g isKindOfClass:[VRectangle class]] ) 465 grStr = [grStr stringByAppendingString:[self epsRectangle:g :&epsState]]; 466 else if ( [g isKindOfClass:[VArc class]] ) 467 grStr = [grStr stringByAppendingString:[self epsArc:g :&epsState]]; 468 else if ( [g isKindOfClass:[VPath class]] ) 469 grStr = [grStr stringByAppendingString:[self epsPath:g :&epsState]]; 470 else if ( [g isKindOfClass:[VGroup class]] ) 471 grStr = [grStr stringByAppendingString:[self epsGroup:g :&epsState]]; 472 else if ( [g isKindOfClass:[VImage class]] ) 473 grStr = [grStr stringByAppendingString:[self epsImage:g :&epsState]]; 474 else if ( [g isKindOfClass:[VText class]] ) 475 grStr = [grStr stringByAppendingString:[self epsVText:(VText*)g :&epsState]]; 476 } 477 } 478 } 479 if ( !epsState.noPoint && !epsState.fill ) 480 grStr = [grStr stringByAppendingFormat:@"stroke\n"]; 481 else if ( !epsState.noPoint && epsState.fill ) 482 grStr = [grStr stringByAppendingFormat:@"eofill\n"]; 483 484 epsState.ll.x -= epsState.maxW/2.0; epsState.ll.y -= epsState.maxW/2.0; 485 epsState.ur.x += epsState.maxW/2.0; epsState.ur.y += epsState.maxW/2.0; 486 487 // header 488 epsStr = [NSString stringWithFormat:@"%%!PS-Adobe-3.0 EPSF-3.0\n"]; 489 epsStr = [epsStr stringByAppendingFormat:@"%%%%Creator: Cenon\n"]; 490 epsStr = [epsStr stringByAppendingFormat:@"%%%%Copyright 2003 by vhf interservice - all rights reserved\n"]; 491 epsStr = [epsStr stringByAppendingFormat:@"%%%%CreationDate: %@\n", [[NSCalendarDate date] descriptionWithCalendarFormat:@"%Y-%m-%d"]]; 492 epsStr = [epsStr stringByAppendingFormat:@"%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", epsState.ll.x, epsState.ll.y, epsState.ll.x+Diff(epsState.ll.x, epsState.ur.x), epsState.ll.y+Diff(epsState.ll.y, epsState.ur.y)]; 493 epsStr = [epsStr stringByAppendingFormat:@"%%%%Pages: 0 1\n"]; 494 epsStr = [epsStr stringByAppendingFormat:@"%%%%EndComments\n"]; 495 496 // graphics 497 epsStr = [epsStr stringByAppendingString:grStr]; 498 499 // Trailer 500 epsStr = [epsStr stringByAppendingFormat:@"showpage\n"]; 501 epsStr = [epsStr stringByAppendingFormat:@"%%%%Trailer\n"]; 502/*%DocumentFonts: Helvetica-Light 503%+ Helvetica-Bold 504%+ Helvetica*/ 505 506 savedOk = [epsStr writeToFile:filename atomically:YES]; 507 } 508 //else 509 // NSRunAlertPanel(SAVE_TITLE, DIR_NOT_WRITABLE, nil, nil, nil); 510#endif 511 512 /* restore backup */ 513 if (!savedOk) 514 { 515 [fileManager removeFileAtPath:filename handler:nil]; // remove what we just started to write 516 [fileManager movePath:backupFilename toPath:filename handler:nil]; // restore backup 517 NSRunAlertPanel(SAVE_TITLE, CANT_SAVE, nil, nil, nil); 518 } 519 else 520 { 521 if (Prefs_RemoveBackups) 522 [fileManager removeFileAtPath:backupFilename handler:nil]; 523 } 524 return YES; 525} 526 527- (void)dealloc 528{ 529 [super dealloc]; 530} 531 532@end 533