| 23 | |
| 24 | import sys |
| 25 | import popen2 |
| 26 | |
| 27 | from pdlanalyzer.pdlparser import PDLParser, PDLParserError |
| 28 | |
| 29 | class PostScriptParser(PDLParser) : |
| 30 | """A parser for PostScript documents.""" |
| 31 | def throughGhostScript(self) : |
| 32 | """Get the count through GhostScript, useful for non-DSC compliant PS files.""" |
| 33 | if self.debug : |
| 34 | sys.stderr.write("Internal parser sucks, using GhostScript instead...\n") |
| 35 | self.infile.seek(0) |
| 36 | command = 'gs -sDEVICE=bbox -dNOPAUSE -dBATCH -dQUIET - 2>&1 | grep -c "%%HiResBoundingBox:" 2>/dev/null' |
| 37 | child = popen2.Popen4(command) |
| 38 | try : |
| 39 | data = self.infile.read(MEGABYTE) |
| 40 | while data : |
| 41 | child.tochild.write(data) |
| 42 | data = self.infile.read(MEGABYTE) |
| 43 | child.tochild.flush() |
| 44 | child.tochild.close() |
| 45 | except (IOError, OSError), msg : |
| 46 | raise PDLParserError, "Problem during analysis of Binary PostScript document : %s" % msg |
| 47 | |
| 48 | pagecount = 0 |
| 49 | try : |
| 50 | pagecount = int(child.fromchild.readline().strip()) |
| 51 | except (IOError, OSError, AttributeError, ValueError), msg : |
| 52 | raise PDLParserError, "Problem during analysis of Binary PostScript document : %s" % msg |
| 53 | child.fromchild.close() |
| 54 | |
| 55 | try : |
| 56 | child.wait() |
| 57 | except OSError, msg : |
| 58 | raise PDLParserError, "Problem during analysis of Binary PostScript document : %s" % msg |
| 59 | return pagecount * self.copies |
| 60 | |
| 61 | def natively(self) : |
| 62 | """Count pages in a DSC compliant PostScript document.""" |
| 63 | self.infile.seek(0) |
| 64 | pagecount = 0 |
| 65 | for line in self.infile.xreadlines() : |
| 66 | if line.startswith("%%Page: ") : |
| 67 | pagecount += 1 |
| 68 | elif line.startswith("%%Requirements: numcopies(") : |
| 69 | try : |
| 70 | number = int(line.strip().split('(')[1].split(')')[0]) |
| 71 | except : |
| 72 | pass |
| 73 | else : |
| 74 | if number > self.copies : |
| 75 | self.copies = number |
| 76 | elif line.startswith("%%BeginNonPPDFeature: NumCopies ") : |
| 77 | # handle # of copies set by some Windows printer driver |
| 78 | try : |
| 79 | number = int(line.strip().split()[2]) |
| 80 | except : |
| 81 | pass |
| 82 | else : |
| 83 | if number > self.copies : |
| 84 | self.copies = number |
| 85 | elif line.startswith("1 dict dup /NumCopies ") : |
| 86 | # handle # of copies set by mozilla/kprinter |
| 87 | try : |
| 88 | number = int(line.strip().split()[4]) |
| 89 | except : |
| 90 | pass |
| 91 | else : |
| 92 | if number > self.copies : |
| 93 | self.copies = number |
| 94 | return pagecount * self.copies |
| 95 | |
| 96 | def getJobSize(self) : |
| 97 | """Count pages in PostScript document.""" |
| 98 | return self.natively() or self.throughGhostScript() |
| 99 | |
| 100 | def test() : |
| 101 | """Test function.""" |
| 102 | raise RuntimeError, "Not implemented !" |
| 103 | |
| 104 | if __name__ == "__main__" : |
| 105 | test() |