This is PICTFile.m in view mode; [Download] [Up]
/***********************************************************************\
PICT file class for Convert PICT which converts graphics from PICT to eps formats.
Copyright (C) 1993 David John Burrowes
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author, David John Burrowes, can be reached at:
davidjohn@kira.net.netcom.com
David John Burrowes
1926 Ivy #10
San Mateo, CA 94403-1367
\***********************************************************************/
/*
====================================================================
This is the implementation file for the PICTFile class. Full documentation for this class can be found in the PICTFile.rtf file. I will not duplicate all that fine information here.
This is $Revision: 1.10 $ of this file
It was last modified by $Author: death $ on $Date: 93/04/04 23:29:46 $
Note that this file was created while using the New Century Schoolbook Roman typeface. You may find that some things line up strangely if you don't use that family.
* $Log: PICTFile.m,v $
Revision 1.10 93/04/04 23:29:46 death
Sun Apr 4 23:29:45 PDT 1993
Revision 1.9 93/01/09 21:07:04 death
Sat Jan 9 21:07:04 PST 1993
Revision 1.8 93/01/01 11:51:13 death
Fri Jan 1 11:51:12 PST 1993
Revision 1.7 92/12/31 15:34:01 death
Thu Dec 31 15:34:01 PST 1992
Revision 1.6 92/12/05 23:06:55 death
Sat Dec 5 23:06:54 PST 1992
Revision 1.5 92/12/03 18:01:12 death
Thu Dec 3 18:01:11 PST 1992
Revision 1.4 92/11/27 19:37:24 death
Fri Nov 27 19:37:24 PST 1992
Revision 1.3 92/11/08 09:26:15 death
Sun Nov 8 09:26:15 PST 1992
Revision 1.2 92/08/09 19:46:19 death
Sun Aug 9 19:46:19 PDT 1992
Revision 1.1 92/08/09 08:53:00 death
Sun Aug 9 08:52:59 PDT 1992
*====================================================================
*/
//
// Import our own definition
//
#import "PICTFile.h"
#import <architecture/byte_order.h> // for big/little endian conversins
@implementation PICTFile
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: free
// Parameters: none
// Returns: self
// Stores: none
// Description:
// Frees various data owned by the instance.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- free
{
if (PICTHeader != NullByteString)
FreeByteString(PICTHeader);
if (BoundingRect != (PICTRect*) NullByteString)
FreeByteString((ByteString)BoundingRect);
return [super free];
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: OpenWithAccess:
// Parameters: the means of accessing the specified file
// Returns: self
// Stores: none
// Description:
// This is a simple subclass-ed method from the File class. This simply traps to
// make sure that the operation is not one that involves file writing, as this is not
// supported at present by the PICTFile class. If it is an operation involving
// writing, and error is set, and this returns self.
// Bugs:
// We don't check for errors when reading the header or opcodes or anything...
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- OpenWithAccess: (AccessType) operation
{
PICTOpcode theOpcode;
[self ResetResults];
if (operation != FILE_READ)
{
[self StoreErrorCode: ERR_MAYNOTWRITE
AndText: "You may ONLY read from a PICT file."];
}
else
{
[super OpenWithAccess: operation];
if ([self GetErrorCode] == ERR_OK)
{
PICTHeader = NewByteString(512);
[self Read: 512 BytesInto: PICTHeader];
[self AdvanceBytes: 2]; // skip the size
BoundingRect = [self GetRect];
//
// 92.12.03 djb Added because I found a Superpaint doc which had a large
// number of 0's after the bounding rect. Weird.
//
do
{
theOpcode = [self GetOpcode];
}
while( (theOpcode == 0) && ([self GetErrorCode] != ERR_EOF));
if (theOpcode == 0x11)
{
switch ([self GetByte])
{
case 0x01:
PICTVersion = 1;
break;
case 0x02:
PICTVersion = 2;
break;
}
}
if (PICTVersion == 0)
{
PICTVersion = 9999; // unlikely Apple will ever do a 9999 vers. =)
[self StoreErrorCode: ERR_UNKNOWNVERSION
AndText: "Unknown PICT version!"];
}
}
}
return self;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: initAndUse:
// Parameters: none
// Returns: self
// Stores: none
// Description:
// This is a simple subclass-ed method from the File class. We subclass it
// because we need to initalize our instance variables.
// Bugs:
// We don't initalize the bounding rect
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- initAndUse: (roCString) pathname
{
[super initAndUse: pathname];
PICTHeader = NullByteString;
PICTVersion = 0;
FoundEnd = NO;
return self;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: initAndUseTemporary
// Parameters: none
// Returns: self
// Stores: none
// Description:
// This is a simple subclass-ed method from the File class. This method essentially
// implies doing write access to a file, which we don't presently support, so we just
// return an error indirectly by setting FoundEnd to be YES.
// Bugs:
// We should be setting an error here.
// We don't initalize the bounding rect
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- initAndUseTemporary
{
[super initAndUseTemporary];
PICTHeader = NullByteString;
PICTVersion = 0;
FoundEnd = YES;
return self;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: GetVersion
// Parameters: none
// Returns: an integer representing the PICT file version number
// Stores: none
// Description:
// Returns the version number of the PICT file to the caller.
// Bugs:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (Integer) GetVersion
{
return PICTVersion;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: GetHeader
// Parameters: none
// Returns: A pointer to a block of constant data that is a copy of the 512byte
// pict file header.
// Stores: none
// Description:
// Returns a pointer to the 512 byte header of the PICT file. The 512 bytes are
// not terminated in any way, and it is assumed the caller is aware of this.
// Bugs:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (ConstByteString) GetHeader
{
return PICTHeader;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: GetBounds
// Parameters: none
// Returns: A pointer to a new struct describing the bounds of the pict file
// Stores: none
// Description:
// Returns a rectangle struct to the caller containing the boundrary rectangl
// of the PICT image in this PICT file. The caller is responsible for disposing of
// the rectangle.
// Bugs:
// We blindly assume the memory allocation worked.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (PICTRect*) GetBounds
{
PICTRect* tempRect;
tempRect = (PICTRect*) NewByteString(sizeof(PICTRect));
tempRect->left = BoundingRect->left;
tempRect->right = BoundingRect->right;
tempRect->top = BoundingRect->top;
tempRect->bottom = BoundingRect->bottom;
return tempRect;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: GetOpcode
// Parameters: none
// Returns: A PICT opcode
// Stores: none
// Description:
// Reads the next opcode from the PICT file and returns it. This reads either a
// one or two byte opcode, depending on whether it's version 1 or 2 (or above). If
// the version is 2 or above, it will also automatically move to the next even word
// boundrary to read the next opcode.
// History:
// 93.08.01 djb Added NXSwap code for endianness
// 93.08.15 djb Argh! I need to be casting the results!!!
// Bugs:
// By always returning the FF opcode when we've reached the end, things must
// be carefull that they don't loop forever somehow....
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (PICTOpcode) GetOpcode
{
PICTOpcode theOpcode;
if (FoundEnd == YES)
theOpcode = 0xFF;
else
{
switch (PICTVersion)
{
case 0:
case 1:
theOpcode = [self ReadByte];
break;
case 2:
//
// Pict 2 opcodes always occur on 16 bit boundaries. If we aren't on
// an even byte number, then scoot forward a byte.
//
if (EvenUnsignedNum([self GetCurrentPosition]) != YES)
[self AdvanceBytes: 1];
[self Read: 2 BytesInto: (ByteString) &theOpcode];
theOpcode = (PICTOpcode)NXSwapBigShortToHost(theOpcode);
break;
default:
//
// if we don't know the current version, try to quit with the quit opcode.
//
theOpcode = 0xFF;
FoundEnd = YES;
break;
}
if (theOpcode == 0xFF)
FoundEnd = YES;
}
return theOpcode;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: GetRect
// Parameters: none
// Returns: A Pict rectangle (ptr to) (or pass NULL if an erorr occurred)
// Stores: none
// Description:
// Reads an 8 byte PICT rectangle from the PICT file, and returns this
// copy to the caller.
// History:
// 93.08.01 djb Added NXSwap code for endianness
// 93.08.15 djb Argh! I need to be casting the results!!!
// 93.08.16 djb Argh! again! Wasn't casting properly in all cases.
// Bugs:
// We set no error codes.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (PICTRect*) GetRect
{
PICTRect* tempRect;
tempRect = (PICTRect*) NewByteString(sizeof(PICTRect));
[self Read: 8 BytesInto: (ByteString) tempRect];
tempRect->left = (INTEGER) NXSwapBigShortToHost(tempRect->left);
tempRect->right = (INTEGER) NXSwapBigShortToHost(tempRect->right);
tempRect->top = (INTEGER) NXSwapBigShortToHost(tempRect->top);
tempRect->bottom = (INTEGER) NXSwapBigShortToHost(tempRect->bottom);
if ([self GetErrorCode] != ERR_OK)
{
FreeByteString((ByteString) tempRect);
tempRect = NULL;
}
return tempRect;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: GetPoint
// Parameters: none
// Returns: A Pict point (ptr to) (or pass NULL if an erorr occurred)
// Stores: none
// Description:
// Reads a 4 byte point from the PICT file and returns a copy to the caller.
// History:
// 93.08.01 djb Added NXSwap code for endianness
// 93.08.15 djb Argh! I need to be casting the results!!!
// 93.08.16 djb Argh! again! Wasn't casting properly in all cases.
// Bugs:
// We set no error codes.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (PICTPoint*) GetPoint
{
PICTPoint* tempPt;
tempPt = (PICTPoint*) NewByteString(sizeof(PICTPoint));
[self Read: 4 BytesInto: (ByteString)tempPt];
tempPt->x = (INTEGER) NXSwapBigShortToHost(tempPt->x);
tempPt->y = (INTEGER) NXSwapBigShortToHost(tempPt->y);
if ([self GetErrorCode] != ERR_OK)
{
FreeByteString((ByteString) tempPt);
tempPt = NULL;
}
return tempPt;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: GetByte
// Parameters: none
// Returns: A byte
// Stores: none
// Description:
// This is just like ReadByte in the File class. It reads a byte and returns it
// to the caller. This is provided for naming consistancy with the other methods here.
// Bugs:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (Byte) GetByte
{
return [self ReadByte];
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: GetSignedByte
// Parameters: none
// Returns: A byte
// Stores: none
// Description:
// This is just like ReadByte in the File class. It reads a byte and returns it
// to the caller. This is provided for naming consistancy with the other methods here.
// Bugs:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (SignedByte) GetSignedByte
{
return (SignedByte) [self ReadByte];
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: GetPString
// Parameters: none
// Returns: A CString, or a NullCString if a problem occurred.
// Stores: none
// Description:
// This reads in a Pascal style string from the PICT file, and returns the copy
// as a CString structure to the caller (who is responsible for disposing of it)
// Note, though, thatthe file reading routines it calls may store errors...
// Bugs:
// Not checking them error codes again....
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (CString) GetPString
{
Byte length;
CString theString;
length = [self ReadByte];
theString = NewCString(length);
[self Read: length BytesInto: (ByteString) theString];
theString[length] = EndOfCString;
return theString;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: GetINTEGER
// Parameters: none
// Returns: An integer
// Stores: none
// Description:
// This reads a 2 byte signed integer in and then returns it to the caller as an
// Integer type
// History:
// 93.08.01 djb Added NXSwap code for endianness
// 93.08.15 djb Argh! I need to be casting the results!!!
// 93.08.16 djb Argh! again! Wasn't casting properly in all cases.
// Bugs:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (Integer) GetINTEGER
{
Signed16Bits theInt;
[self Read: 2 BytesInto: (ByteString) &theInt];
return (INTEGER) NXSwapBigShortToHost(theInt);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: GetPositiveINTEGER
// Parameters: none
// Returns: A positive integer
// Stores: none
// Description:
// This reas a 2 byte signed integer in and then returns it to the caller as a
// PositiveInteger type.
// History:
// 93.08.01 djb Added NXSwap code for endianness
// 93.08.15 djb Argh! I need to be casting the results!!!
// 93.08.16 djb Argh! again! Wasn't casting properly in all cases.
// Bugs:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (PositiveInteger) GetPositiveINTEGER
{
bits16 theInt;
[self Read: 2 BytesInto: (ByteString) &theInt];
return (bits16) NXSwapBigShortToHost(theInt);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: GetLONGINT
// Parameters: none
// Returns: A long int
// Stores: none
// Description:
// This reads a 4 byte signed integer in and then returns it to the caller as an
// Integer type.
// History:
// 93.08.01 djb Added NXSwap code for endianness
// 93.08.15 djb Argh! I need to be casting the results!!!
// 93.08.16 djb Argh! again! Wasn't casting properly in all cases.
// Bugs:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (Integer) GetLONGINT
{
Signed32Bits theInt;
[self Read: 4 BytesInto: (ByteString) &theInt];
return (LONGINT) NXSwapBigLongToHost(theInt);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: GetPositiveLONGINT
// Parameters: none
// Returns: A positive integer
// Stores: none
// Description:
// This reas a 2 byte signed integer in and then returns it to the caller as a
// PositiveInteger type.
// History:
// 93.08.01 djb Added NXSwap code for endianness
// 93.08.15 djb Argh! I need to be casting the results!!!
// 93.08.16 djb Argh! again! Wasn't casting properly in all cases.
// Bugs:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (PositiveInteger) GetPositiveLONGINT
{
bits32 theInt;
[self Read: 4 BytesInto: (ByteString) &theInt];
return (bits32) NXSwapBigLongToHost(theInt);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: GetFixedNumber
// Parameters: none
// Returns: A real number
// Stores: none
// Description:
// This reas a 4 byte signed integer in and then converts it to the fixed pont number
// it really is by shoving a decimal point in after the 16th bit, and returning as
// a real number..
// History:
// 93.08.01 djb Added NXSwap code for endianness
// 93.08.15 djb Argh! I need to be casting the results!!!
// 93.08.16 djb Argh! again! Wasn't casting properly in all cases.
// Bugs:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (Real) GetFixedNumber
{
Signed32Bits fixedNumber;
[self Read: 4 BytesInto: (ByteString) &fixedNumber];
fixedNumber = (LONGINT) NXSwapBigLongToHost(fixedNumber);
return fixedNumber / 65536.0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Routine: GetPolyVerbs
// Parameters: none
// Returns: an 8 bit bitfield of options for drawing a polygon.
// Stores: none
// Description:
// This merly provides a way for the app to read in the bitfield that is used for
// one of the piccomments. This way if we need to ever tweak the data, we can do
// it just here.
// Bugs:
// This does some really gross typecasting to convert the 1 byte value to a 1 byte
// bitfield. I'm sure there are easier ways...
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (TPolyVerbRec) GetPolyVerbs
{
TPolyVerbRec * dummy;
Byte temp = [self ReadByte];
dummy = (TPolyVerbRec *) & temp;
return *dummy;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.