root / pkpgcounter / trunk / pdlanalyzer / postscript.py @ 220

Revision 220, 5.4 kB (checked in by jerome, 19 years ago)

Big improvements on readability + maintainability

  • Property svn:eol-style set to native
  • Property svn:keywords set to Auth Date Id Rev
Line 
1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3#
4# pkpgcounter : a generic Page Description Language parser
5#
6# (c) 2003, 2004, 2005 Jerome Alet <alet@librelogiciel.com>
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20#
21# $Id$
22#
23
24import sys
25import popen2
26
27from pdlanalyzer import pdlparser
28
29class Parser(pdlparser.PDLParser) :
30    """A parser for PostScript documents."""
31    def isValid(self) :   
32        """Returns 1 if data is PostScript, else 0."""
33        if self.firstblock.startswith("%!") or \
34           self.firstblock.startswith("\004%!") or \
35           self.firstblock.startswith("\033%-12345X%!PS") or \
36           ((self.firstblock[:128].find("\033%-12345X") != -1) and \
37             ((self.firstblock.find("LANGUAGE=POSTSCRIPT") != -1) or \
38              (self.firstblock.find("LANGUAGE = POSTSCRIPT") != -1) or \
39              (self.firstblock.find("LANGUAGE = Postscript") != -1))) or \
40              (self.firstblock.find("%!PS-Adobe") != -1) :
41            if self.debug : 
42                sys.stderr.write("DEBUG: Input file is in the PostScript format.\n")
43            return 1
44        else :   
45            return 0
46       
47    def throughGhostScript(self) :
48        """Get the count through GhostScript, useful for non-DSC compliant PS files."""
49        if self.debug :
50            sys.stderr.write("Internal parser sucks, using GhostScript instead...\n")
51        self.infile.seek(0)
52        command = 'gs -sDEVICE=bbox -dNOPAUSE -dBATCH -dQUIET - 2>&1 | grep -c "%%HiResBoundingBox:" 2>/dev/null'
53        child = popen2.Popen4(command)
54        try :
55            data = self.infile.read(MEGABYTE)   
56            while data :
57                child.tochild.write(data)
58                data = self.infile.read(MEGABYTE)
59            child.tochild.flush()
60            child.tochild.close()   
61        except (IOError, OSError), msg :   
62            raise pdlparser.PDLParserError, "Problem during analysis of Binary PostScript document : %s" % msg
63           
64        pagecount = 0
65        try :
66            pagecount = int(child.fromchild.readline().strip())
67        except (IOError, OSError, AttributeError, ValueError), msg :
68            raise pdlparser.PDLParserError, "Problem during analysis of Binary PostScript document : %s" % msg
69        child.fromchild.close()
70       
71        try :
72            child.wait()
73        except OSError, msg :   
74            raise pdlparser.PDLParserError, "Problem during analysis of Binary PostScript document : %s" % msg
75        return pagecount * self.copies
76       
77    def natively(self) :
78        """Count pages in a DSC compliant PostScript document."""
79        self.infile.seek(0)
80        pagecount = 0
81        for line in self.infile.xreadlines() : 
82            if line.startswith(r"%%Page: ") :
83                pagecount += 1
84            elif line.startswith(r"%%Requirements: numcopies(") :   
85                try :
86                    number = int(line.strip().split('(')[1].split(')')[0])
87                except :     
88                    pass
89                else :   
90                    if number > self.copies :
91                        self.copies = number
92            elif line.startswith(r"%%BeginNonPPDFeature: NumCopies ") :
93                # handle # of copies set by some Windows printer driver
94                try :
95                    number = int(line.strip().split()[2])
96                except :     
97                    pass
98                else :   
99                    if number > self.copies :
100                        self.copies = number
101            elif line.startswith("1 dict dup /NumCopies ") :
102                # handle # of copies set by mozilla/kprinter
103                try :
104                    number = int(line.strip().split()[4])
105                except :     
106                    pass
107                else :   
108                    if number > self.copies :
109                        self.copies = number
110        return pagecount * self.copies
111       
112    def getJobSize(self) :   
113        """Count pages in PostScript document."""
114        self.copies = 1
115        return self.natively() or self.throughGhostScript()
116       
117def test() :       
118    """Test function."""
119    if (len(sys.argv) < 2) or ((not sys.stdin.isatty()) and ("-" not in sys.argv[1:])) :
120        sys.argv.append("-")
121    totalsize = 0   
122    for arg in sys.argv[1:] :
123        if arg == "-" :
124            infile = sys.stdin
125            mustclose = 0
126        else :   
127            infile = open(arg, "rb")
128            mustclose = 1
129        try :
130            parser = Parser(infile, debug=1)
131            totalsize += parser.getJobSize()
132        except pdlparser.PDLParserError, msg :   
133            sys.stderr.write("ERROR: %s\n" % msg)
134            sys.stderr.flush()
135        if mustclose :   
136            infile.close()
137    print "%s" % totalsize
138   
139if __name__ == "__main__" :   
140    test()
Note: See TracBrowser for help on using the browser.