/*
Pencil V1.0, Copyright 1994, 95 by Florian Marquardt.
This program may be distributed under the terms of the GNU general
public license (Start Pencil and select "Info>COPYING..." for a copy of the
license).
*/
// changed 23_10_94: added save/restore for EPS-hack
#import "PencilImage.h"
#import <math.h>

extern BOOL globalOutlines;
extern BOOL movementStatus;
#define M_180_PI 180.0/M_PI
extern void expandRect(NXRect *, float, float);
#define TRANSFORMX(a,b) (tx+sx*cos(phi)*(a)-sy*sin(phi)*(b))
#define TRANSFORMY(a,b) (ty+sx*sin(phi)*(a)+sy*cos(phi)*(b))

@implementation PencilImage
- initFromFile:(const char *)filename
{
	[super init];
	sx=sy=1;
	transformed=NO;
	if(theImage=[NXImage alloc])
	{
		[theImage setDataRetained:YES];
		if([theImage  loadFromFile:filename])
			return self;
		else
		{
			[theImage free];
			return nil;
		}
	}
	else
		return nil;
}

- free
{
	if(theImage)	[theImage free];
	return [super free];
}

- (BOOL)selected:(NXEvent *)te:(int *)cp:(id)view
{
	NXPoint pt;
	NXSize thesize;

	pt=te->location;
	[self transformPoint:&pt];
	[theImage getSize:&thesize];
	if(pt.x>=0 && pt.y>=0 && pt.x<=thesize.width && pt.y<=thesize.height)
		return(YES);
	else
		return(NO);
}

- (BOOL)move:(NXEvent *)tte:(int *)cp:(id)view:(float)bsize
{
	return NO;
}

- (void)draw:(NXRect *)re
{
	if(!re || NXIntersectsRect(&bounds, re))
	{
	if(globalOutlines)
	{
	NXSize thesize;
	[theImage getSize:&thesize];
	PSgsave();
	if(translated)	PStranslate(tx,ty);
	if(rotated)		PSrotate(M_180_PI*phi);
	if(scaled)		PSscale(sx,sy);
	PSsetlinewidth(0);
	PSsetgray(.333);
	PSrectstroke(0,0,thesize.width,thesize.height);
	PSgrestore();
	}
	else
	{
	PSgsave();
	if(translated)	PStranslate(tx,ty);
	if(rotated)		PSrotate(M_180_PI*phi);
	if(scaled)		PSscale(sx,sy);
	if([[theImage bestRepresentation] isKindOf:[NXEPSImageRep class]])
	{	// Sorry, we need this very UGLY hack, because
		// we want rotated images and therefore we would
		// need "draw", but unfortunately "draw" uses a
		// different DPS context for EPS images (which results in wrong clipping), so...
		char *theEPScode; int length;
		char *thetext;
		NXRect box;

		[[(NXEPSImageRep *)[theImage bestRepresentation] getBoundingBox:&box] getEPS:&theEPScode length:&length];
		thetext=(char *)malloc(sizeof(char)*(length+1));
		strncpy(thetext, theEPScode, length);
		thetext[length]=0;
		DPSPrintf(DPSGetCurrentContext(), "0 setgray 0 setlinewidth save %g %g translate\n%s\nrestore\n", -box.origin.x, -box.origin.y, thetext);
		free(thetext);
	}
	else // we need "draw", since we want rotated tiff images, too
		[[theImage bestRepresentation] draw];
	PSgrestore();
	}
	}
}

- (void)drawPath
{
	NXSize thesize;
	[theImage getSize:&thesize];
	DPSPrintf(DPSGetCurrentContext()," matrix currentmatrix ");
	if(translated)	PStranslate(tx,ty);
	if(rotated)		PSrotate(M_180_PI*phi);
	if(scaled)		PSscale(sx,sy);
	PSmoveto(0,0);
	PSlineto(thesize.width,0);
	PSlineto(thesize.width,thesize.height);
	PSlineto(0, thesize.height);
	PSclosepath();
	DPSPrintf(DPSGetCurrentContext()," setmatrix\n");
}

- calculateBoundingBox:(id)view
{
	float llx, lly, urx, ury;
	NXSize thesize;

	[theImage getSize:&thesize];
	llx=lly=0;
	urx=thesize.width;
	ury=thesize.height;
	bounds.origin.x=TRANSFORMX(llx,lly);
	bounds.origin.y=TRANSFORMY(llx,lly);
	bounds.size.width=bounds.size.height=0;
	expandRect(&bounds, TRANSFORMX(llx,ury),TRANSFORMY(llx,ury));
	expandRect(&bounds, TRANSFORMX(urx,ury), TRANSFORMY(urx,ury));
	expandRect(&bounds, TRANSFORMX(urx,lly),TRANSFORMY(urx,lly));
	return self;
}

- (void)drawControl:(NXRect *)re:(int)cp:(float)bsize
{
	NXSize thesize;

	[theImage getSize:&thesize];
	if(!movementStatus || ![[theImage bestRepresentation] isKindOf:[NXEPSImageRep class]])
		[self draw:re];
	if(transformed)	{	PSgsave();
	if(translated)	PStranslate(tx,ty);
	if(rotated)		PSrotate(M_180_PI*phi);
	if(scaled)		PSscale(sx,sy);
	}
	PSsetlinewidth(0);
/*	if([[theImage bestRepresentation] isKindOf:[NXEPSImageRep class]])
	{
		PSsetgray(.5);
		PSsetlinewidth(0);
		PSmoveto(0,0); 
		PSlineto(thesize.width,thesize.height);
		PSstroke();
		PSmoveto(thesize.width,0);
		PSlineto(0,thesize.height);
		PSstroke();
	}
	PSsetgray(.8);
	PSrectstroke(2,2,thesize.width-4,thesize.height-4);
*/
	PSsetrgbcolor(1,0,0);
	PSsetlinewidth(2);
#define WW thesize.width*.1
#define HH thesize.height*.1
#define HO (thesize.height-2)
#define WO (thesize.width-2)
	PSmoveto(WW+2,2);
	PSrlineto(-WW,0);
	PSrlineto(0, HH);
	PSstroke();
	PSmoveto(WW+2,HO);
	PSrlineto(-WW,0);
	PSrlineto(0,-HH);
	PSstroke();
	PSmoveto(WO-WW,2);
	PSrlineto(WW,0);
	PSrlineto(0,HH);
	PSstroke();
	PSmoveto(WO-WW,HO);
	PSrlineto(WW,0);
	PSrlineto(0,-HH);
	PSstroke();
	if(transformed)	PSgrestore();
}

- (void)drawIfNeeded:(NXRect *)re:(int)cp:(float)bsize
{ 	if([[theImage bestRepresentation] isKindOf:[NXEPSImageRep class]]) 		[self drawControl:re:cp:bsize];  }
//  used for redrawing EPS after a move...

- write:(NXTypedStream *)stream
{
	[super write:stream];
	NXWriteObject(stream,theImage);
	return self;	
}

- read:(NXTypedStream *)stream
{
	[super read:stream];
	theImage=NXReadObject(stream);
	return self;
}

- (void)writeType:(NXStream *)to
{
	NXPrintf(to,"3");
}
@end