Show
Ignore:
Timestamp:
06/28/04 23:20:32 (20 years ago)
Author:
jalet
Message:

PCLXL support now works !

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/pykota/pdlanalyzer.py

    r1574 r1575  
    2222# 
    2323# $Log$ 
     24# Revision 1.19  2004/06/28 21:20:30  jalet 
     25# PCLXL support now works ! 
     26# 
    2427# Revision 1.18  2004/06/27 22:59:37  jalet 
    2528# More work on PCLXL parser 
     
    256259    def __init__(self, infile) : 
    257260        """Initialize PCLXL Analyzer.""" 
    258         raise PDLAnalyzerError, "PCLXL (aka PCL6) is not supported yet." 
     261        # raise PDLAnalyzerError, "PCLXL (aka PCL6) is not supported yet." 
    259262        self.infile = infile 
    260263        self.islittleendian = None 
     
    268271                endian = ord(line[0]) 
    269272                if endian == 0x29 : 
    270                     self.littleendian() 
     273                    self.littleEndian() 
    271274                elif endian == 0x28 :     
    272                     self.bigendian() 
     275                    self.bigEndian() 
     276                # elif endian == 0x27 : TODO : What can we do here ?     
     277                #  
    273278                else :     
    274279                    raise PDLAnalyzerError, "No endianness marker 0x%02x at start !" % endian 
     
    276281            raise PDLAnalyzerError, "This file doesn't seem to be PCLXL (aka PCL6)" 
    277282        else :     
    278             self.tags = [ self.skipped ] * 256     
    279             self.tags[0x27] = lambda: self.debug("%08x : ASCII Binding" % self.infile.tell()) 
    280             self.tags[0x28] = self.bigendian  
    281             self.tags[0x29] = self.littleendian 
    282              
    283             self.tags[0x41] = lambda: self.debug("%08x : BeginSession" % self.infile.tell()) 
    284             self.tags[0x42] = lambda: self.debug("%08x : EndSession" % self.infile.tell()) 
     283            # Initialize table of tags 
     284            self.tags = [ 0 ] * 256     
     285             
     286            # GhostScript's sources tell us that HP printers 
     287            # only accept little endianness, but we can handle both. 
     288            self.tags[0x28] = self.bigEndian    # BigEndian 
     289            self.tags[0x29] = self.littleEndian # LittleEndian 
    285290             
    286291            self.tags[0x43] = self.beginPage    # BeginPage 
    287             self.tags[0x44] = self.endPage      # EndPage 
    288              
    289             self.tags[0x47] = lambda: self.debug("%08x : Comment" % self.infile.tell()) 
    290             self.tags[0x48] = lambda: self.debug("%08x : OpenDataSource" % self.infile.tell()) 
    291             self.tags[0x49] = lambda: self.debug("%08x : CloseDataSource" % self.infile.tell()) 
    292              
    293             self.tags[0xc0] = lambda: self.debug("%08x : ubyte" % self.infile.tell()) or 1 # ubyte 
    294             self.tags[0xc1] = lambda: self.debug("%08x : uint16" % self.infile.tell()) or 2 # uint16 
    295             self.tags[0xc2] = lambda: self.debug("%08x : uint32" % self.infile.tell()) or 4 # uint32 
    296             self.tags[0xc3] = lambda: self.debug("%08x : sint16" % self.infile.tell()) or 2 # sint16 
    297             self.tags[0xc4] = lambda: self.debug("%08x : sint32" % self.infile.tell()) or 4 # sint32 
    298             self.tags[0xc5] = lambda: self.debug("%08x : real32" % self.infile.tell()) or 4 # real32 
     292             
     293            self.tags[0xc0] = 1 # ubyte 
     294            self.tags[0xc1] = 2 # uint16 
     295            self.tags[0xc2] = 4 # uint32 
     296            self.tags[0xc3] = 2 # sint16 
     297            self.tags[0xc4] = 4 # sint32 
     298            self.tags[0xc5] = 4 # real32 
    299299             
    300300            self.tags[0xc8] = self.array_8  # ubyte_array 
     
    305305            self.tags[0xcd] = self.array_32 # real32_array 
    306306             
    307             self.tags[0xd0] = lambda: self.debug("%08x : ubyte_xy" % self.infile.tell()) or 2 # ubyte_xy 
    308             self.tags[0xd1] = lambda: self.debug("%08x : uint16_xy" % self.infile.tell()) or 4 # uint16_xy 
    309             self.tags[0xd2] = lambda: self.debug("%08x : uint32_xy" % self.infile.tell()) or 8 # uint32_xy 
    310             self.tags[0xd3] = lambda: self.debug("%08x : sint16_xy" % self.infile.tell()) or 4 # sint16_xy 
    311             self.tags[0xd4] = lambda: self.debug("%08x : sint32_xy" % self.infile.tell()) or 8 # sint32_xy 
    312             self.tags[0xd5] = lambda: self.debug("%08x : real32_xy" % self.infile.tell()) or 8 # real32_xy 
    313              
    314             self.tags[0xd0] = lambda: self.debug("%08x : ubyte_box" % self.infile.tell()) or 4  # ubyte_box 
    315             self.tags[0xd1] = lambda: self.debug("%08x : uint16_box" % self.infile.tell()) or 8  # uint16_box 
    316             self.tags[0xd2] = lambda: self.debug("%08x : uint32_box" % self.infile.tell()) or 16 # uint32_box 
    317             self.tags[0xd3] = lambda: self.debug("%08x : sint16_box" % self.infile.tell()) or 8  # sint16_box 
    318             self.tags[0xd4] = lambda: self.debug("%08x : sint32_box" % self.infile.tell()) or 16 # sint32_box 
    319             self.tags[0xd5] = lambda: self.debug("%08x : real32_box" % self.infile.tell()) or 16 # real32_box 
    320              
    321             self.tags[0xf8] = lambda: self.debug("%08x : attr_ubyte" % self.infile.tell()) or 1 # attr_ubyte 
    322             self.tags[0xf9] = lambda: self.debug("%08x : attr_uint16" % self.infile.tell()) or 2 # attr_uint16 
     307            self.tags[0xd0] = 2 # ubyte_xy 
     308            self.tags[0xd1] = 4 # uint16_xy 
     309            self.tags[0xd2] = 8 # uint32_xy 
     310            self.tags[0xd3] = 4 # sint16_xy 
     311            self.tags[0xd4] = 8 # sint32_xy 
     312            self.tags[0xd5] = 8 # real32_xy 
     313             
     314            self.tags[0xe0] = 4  # ubyte_box 
     315            self.tags[0xe1] = 8  # uint16_box 
     316            self.tags[0xe2] = 16 # uint32_box 
     317            self.tags[0xe3] = 8  # sint16_box 
     318            self.tags[0xe4] = 16 # sint32_box 
     319            self.tags[0xe5] = 16 # real32_box 
     320             
     321            self.tags[0xf8] = 1 # attr_ubyte 
     322            self.tags[0xf9] = 2 # attr_uint16 
    323323             
    324324            self.tags[0xfa] = self.embeddedData      # dataLength 
    325325            self.tags[0xfb] = self.embeddedDataSmall # dataLengthByte 
    326326             
    327     def debug(self, msg) : 
    328         """Outputs a debug message on stderr.""" 
    329         sys.stderr.write("%s\n" % msg) 
    330         sys.stderr.flush() 
    331          
    332     def skipped(self) :     
    333         """Skips a byte.""" 
    334         self.debug("%08x : skip" % self.infile.tell()) 
    335          
    336327    def beginPage(self) : 
    337328        """Indicates the beginning of a new page.""" 
    338329        self.pagecount += 1 
    339         self.debug("%08x : beginPage (%i)" % (self.infile.tell(), self.pagecount)) 
    340          
    341     def endPage(self) : 
    342         """Indicates the end of a page.""" 
    343         self.debug("%08x : endPage (%i)" % (self.infile.tell(), self.pagecount)) 
     330        return 0 
    344331         
    345332    def handleArray(self, itemsize) :         
    346333        """Handles arrays.""" 
    347         pos = self.infile.tell() 
    348         datatype = self.infile.read(1) 
    349         self.debug("%08x : Array of datatype 0x%02x" % (pos, ord(datatype))) 
    350         length = self.tags[ord(datatype)]() 
     334        datatype = self.minfile[self.pos] 
     335        self.pos += 1 
     336        length = self.tags[ord(datatype)] 
    351337        if length is None : 
    352             self.debug("Bogus array length at %s" % pos) 
    353         else :     
    354             sarraysize = self.infile.read(length) 
    355             if self.islittleendian : 
    356                 fmt = "<" 
    357             else :     
    358                 fmt = ">" 
    359             if length == 1 :     
    360                 fmt += "B" 
    361             elif length == 2 :     
    362                 fmt += "H" 
    363             elif length == 4 :     
    364                 fmt += "I" 
    365             else :     
    366                 raise PDLAnalyzerError, "Error on array size at %s" % self.infile.tell() 
    367             arraysize = struct.unpack(fmt, sarraysize)[0] 
    368             self.debug("itemsize %s * size %s = %s" % (itemsize, arraysize, itemsize*arraysize)) 
    369             return arraysize * itemsize 
     338            raise PDLAnalyzerError, "Error on array length at %s" % self.pos 
     339        elif callable(length) : 
     340            length = length() 
     341        pos = self.pos     
     342        posl = pos + length 
     343        sarraysize = self.minfile[pos:posl] 
     344        self.pos = posl 
     345        if self.islittleendian : 
     346            fmt = "<" 
     347        else :     
     348            fmt = ">" 
     349        if length == 1 :     
     350            fmt += "B" 
     351        elif length == 2 :     
     352            fmt += "H" 
     353        elif length == 4 :     
     354            fmt += "I" 
     355        else :     
     356            raise PDLAnalyzerError, "Error on array size at %s" % self.pos 
     357        arraysize = struct.unpack(fmt, sarraysize)[0] 
     358        return arraysize * itemsize 
    370359         
    371360    def array_8(self) :     
    372361        """Handles byte arrays.""" 
    373         self.debug("%08x : array_8" % self.infile.tell()) 
    374362        return self.handleArray(1) 
    375363         
    376364    def array_16(self) :     
    377365        """Handles byte arrays.""" 
    378         self.debug("%08x : array_16" % self.infile.tell()) 
    379366        return self.handleArray(2) 
    380367         
    381368    def array_32(self) :     
    382369        """Handles byte arrays.""" 
    383         self.debug("%08x : array_32" % self.infile.tell()) 
    384370        return self.handleArray(4) 
    385371         
    386372    def embeddedDataSmall(self) : 
    387373        """Handle small amounts of data.""" 
    388         self.debug("%08x : small_datablock" % self.infile.tell()) 
    389         pos = self.infile.tell() 
    390         val = ord(self.infile.read(1)) 
    391         self.debug("%08x : Small datablock length : 0x%02x" % (self.infile.tell()-1, val)) 
    392         return val 
     374        length = ord(self.minfile[self.pos]) 
     375        self.pos += 1 
     376        return length 
    393377         
    394378    def embeddedData(self) : 
    395379        """Handle normal amounts of data.""" 
    396         self.debug("%08x : large_datablock" % self.infile.tell()) 
    397380        if self.islittleendian : 
    398381            fmt = "<I" 
    399382        else :     
    400383            fmt = ">I" 
    401         pos = self.infile.tell() 
    402         data = self.infile.read(4) 
    403         val = struct.unpack(fmt, data)[0] 
    404         if val & 0xff000000 : # tries to detect possible errors when we missed an indianness tag maybe 
    405             if fmt == "<I" : 
    406                 fmt = ">I" 
    407             else :     
    408                 fmt = "<I" 
    409             val = struct.unpack(fmt, data)[0] 
    410         self.debug("%08x : Large datablock length : 0x%08x" % (self.infile.tell()-4, val)) 
    411         self.debug("Endian : %i" % self.islittleendian)  
    412         self.debug("Data read : %s" % str(["0x%02x" % ord(x) for x in data])) 
    413         return val 
    414          
    415     def littleendian(self) :         
     384        pos = self.pos 
     385        pos4 = pos + 4 
     386        data = self.minfile[pos:pos4] 
     387        self.pos = pos4 
     388        return struct.unpack(fmt, data)[0] 
     389         
     390    def littleEndian(self) :         
    416391        """Toggles to little endianness.""" 
    417         self.debug("%08x : littleendian" % self.infile.tell()) 
    418392        self.islittleendian = 1 # little endian 
    419          
    420     def bigendian(self) :     
     393        return 0 
     394         
     395    def bigEndian(self) :     
    421396        """Toggles to big endianness.""" 
    422         self.debug("%08x : bigendian" % self.infile.tell()) 
    423397        self.islittleendian = 0 # big endian 
     398        return 0 
    424399     
    425400    def getJobSize(self) : 
    426401        """Counts pages in a PCLXL (PCL6) document.""" 
     402        infileno = self.infile.fileno() 
     403        self.minfile = mmap.mmap(infileno, os.fstat(infileno).st_size, access=mmap.ACCESS_READ) 
    427404        self.pagecount = 0 
    428         while 1 : 
    429             char = self.infile.read(1) 
    430             if not char : 
    431                 break 
    432             index = ord(char)     
    433             length = self.tags[index]() 
    434             if length :     
    435                 self.infile.read(length)     
     405        self.pos = self.infile.tell() 
     406        try : 
     407            while 1 : 
     408                char = self.minfile[self.pos] 
     409                self.pos += 1 
     410                length = self.tags[ord(char)] 
     411                if not length :     
     412                    continue 
     413                if callable(length) :     
     414                    length = length() 
     415                self.pos += length     
     416        except IndexError : # EOF ? 
     417            self.minfile.close() # reached EOF 
    436418        return self.pagecount 
    437419