"""Furcadia Shape File (FSH) Manipulation Module (c) 2005 - IceDragon This module is responsible for parsing and creation of the Furcadia Shape (FSH) files. """ ###--# Imports #--### from struct import pack,unpack from array import array ###--# Classes #--### class fsh: """ This is the general container of shapes, FSH files can be imported and exported from/to. """ ### Variables ### filename = '' # Name of the last loaded/saved file shapes = [] # The list of shapes themselves tail = '' # The data specified after shapes themselves (tail/junk) ### Constructor ### def __init__( self, filename = '' ): """ This is the class constructor function. Specify an optional filename in order to import the data from an existing FSH file. """ if filename != '': self.importFsh( filename ) ### Functions ### def importFsh( self, filename ): """ Import the container contents from an FSH file. """ fd = open( filename, 'rb' ) # Reading shape amount # shapes = unpack( 'H', fd.read(2) )[0] fd.seek( shapes * 2,1 ) # Skip unneeded chunk sizes # Readinng shapes, filling the list # for shapeNo in range(shapes): s = shape() s.width, s.height = unpack( 'BB', fd.read(2) ) s.offset = unpack( 'bb', fd.read(2) ) s.fromString( fd.read( s.width * s.height) ) self.addShape( s ) # Reading the tail (if any) # self.tail = fd.read() fd.close() def exportFsh( self, filename ): """ Export the container contents to an FSH file. """ fd = open( filename, 'wb' ) # Storing shape amount # fd.write( pack( 'H', len( self.shapes ) ) ) # Writing sizes # for s in self.shapes: fd.write( pack( 'H', s.getSize() ) ) # Writing shapes # for s in self.shapes: fd.write( pack( 'BBbb', s.width, s.height, s.offset[0], s.offset[1] ) ) fd.write( s.toString() ) # Writing tail # fd.write( self.tail ) fd.close() def addShape( self, shape ): """ Append a specific shape to the end of the list. """ self.shapes.append( shape ) def insertShape( self, idx, shape ): """ Insert a specific sape to the middle of the list. """ self.shapes.insert( idx,shape ) def deleteShape( self, shapeNo ): """ Delete a specific shape number from the list. """ del( self.shapes[shapeNo] ) class shape: """ This class contains a single shape and all the additional information for it. It should normally not be used directly """ ### Variables ### width = 0 height = 0 offset = (0,0) data = array( 'B' ) ### Functions ### def __init__( self, width = 0, height = 0 ): """ This is the class constructor function. The shape will be initialized if the widdth and height are specified. """ self.offset = (0,0) if (height*width) > 0: self.init( width,height ) def init( self, width, height ): """ Initialize a shape to specific dimensions, filling it with 0. """ self.width = width self.height = height self.data = array( 'B', [0]*(self.getSize()) ) def fromString( self, string ): """ Store an image in memory from a specific string (according to WxH)! """ self.data = array( 'B', string ) # Correcting (trim/fill) to current width/height length = len(self.data) size = self.getSize() if length < size: self.data += array( 'B', '\x00'*(size-length) ) elif length > size: self.data = self.data[:size] return self.data def toString( self ): """ Return the stored image in as a string """ return self.data.tostring() def pixel( self, x, y, color = '' ): """ Set or get the color at a specific set of coordinates, depending on whether the color value was specified. """ pos = ((self.height - 1 - y) * self.width) + x if pos > self.getSize(): return 0 # Requested pixel that's out of range! if color != '': self.data[pos] = color return data[pos] def offset( self, x = '', y = '' ): """ Set or get the current image offset (x,y) depending on whether the X and/or Y is set. """ if x == '': x = self.offset[0] if y == '': y = self.offset[1] self.offset = (x,y) return self.offset def getSize( self ): """ Get the current image size (WxH) """ return self.width * self.height ###--# Central Functions #--### ###--# End of Script #--###