Changeset 704

Show
Ignore:
Timestamp:
01/25/06 15:14:02 (3 years ago)
Author:
laotzu
Message:

Refactor some of the code in PdfFileWriter?.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • pypdf/trunk/pyPdf/pdf.py

    r703 r704  
    4949class PdfFileWriter(object): 
    5050    def __init__(self): 
    51         self.header = "%PDF-1.3" 
    52         self.pages = [] 
    53  
    54     def addPage(self, page): 
    55         """ 
    56         Adds a page to this PDF file.  A dictionary of /Type = /Page. 
    57         Currently usually aquired from PdfFileReader.getPage(). 
    58  
    59         Stability: Added in v1.0, will exist for all v1.x releases. 
    60         """ 
    61         self.pages.append(page) 
    62  
    63     def write(self, stream): 
    64         """ 
    65         Writes this PDF file to an output stream.  Writes the file as a 
    66         PDF-1.3 format file. 
    67  
    68         Stability: Added in v1.0, will exist for all v1.x releases. 
    69         """ 
    70         objects = [] 
    71  
    72         # The pages will all have a new parent, so we need to replace their 
    73         # existing parent object. 
     51        self._header = "%PDF-1.3" 
     52        self._objects = []  # array of indirect objects 
     53 
     54        # The root of our page tree node. 
    7455        pages = DictionaryObject() 
    7556        pages.update({ 
    7657                NameObject("/Type"): NameObject("/Pages"), 
    77                 NameObject("/Count"): NumberObject(len(self.pages)), 
     58                NameObject("/Count"): NumberObject(0), 
    7859                NameObject("/Kids"): ArrayObject(), 
    7960                }) 
    80         objects.append(pages) 
    81         pages_ido = IndirectObject(len(objects), 0, self) 
    82         for page in self.pages: 
    83             page[NameObject("/Parent")] = pages_ido 
     61        self._pages = self._addObject(pages) 
    8462 
    8563        # info object 
    8664        info = DictionaryObject() 
    8765        info.update({ 
    88                 NameObject("/Producer"): StringObject("Python PDF Library - mfenniak@pobox.com") 
     66                NameObject("/Producer"): StringObject("Python PDF Library - http://stompstompstomp.com/pyPdf/") 
    8967                }) 
    90         objects.append(info) 
    91         info = IndirectObject(len(objects), 0, self) 
     68        self._info = self._addObject(info) 
    9269 
    9370        # root object 
     
    9572        root.update({ 
    9673            NameObject("/Type"): NameObject("/Catalog"), 
    97             NameObject("/Pages"): pages_ido
     74            NameObject("/Pages"): self._pages
    9875            }) 
    99         objects.append(root) 
    100         root = IndirectObject(len(objects), 0, self) 
    101  
    102         # The real work.  Find any indirect references in out pages, 
    103         # and make them into objects for us to write. 
     76        self._root = self._addObject(root) 
     77 
     78    def _addObject(self, obj): 
     79        self._objects.append(obj) 
     80        return IndirectObject(len(self._objects), 0, self) 
     81 
     82    def _getObject(self, ido): 
     83        assert ido.pdf == self 
     84        return self._objects[ido.idnum - 1] 
     85 
     86    def addPage(self, page): 
     87        """ 
     88        Adds a page to this PDF file.  A dictionary of /Type = /Page. 
     89        Currently usually aquired from PdfFileReader.getPage(). 
     90 
     91        Stability: Added in v1.0, will exist for all v1.x releases. 
     92        """ 
     93        assert page["/Type"] == "/Page" 
     94        page[NameObject("/Parent")] = self._pages 
     95        page = self._addObject(page) 
     96        pages = self._getObject(self._pages) 
     97        pages["/Kids"].append(page) 
     98        pages["/Count"] = NumberObject(pages["/Count"] + 1) 
     99 
     100    def write(self, stream): 
     101        """ 
     102        Writes this PDF file to an output stream.  Writes the file as a 
     103        PDF-1.3 format file. 
     104 
     105        Stability: Added in v1.0, will exist for all v1.x releases. 
     106        """ 
     107 
    104108        externalReferenceMap = {} 
    105         for page in self.pages: 
    106             page = self.sweepIndirectReferences(externalReferenceMap, objects, page) 
    107             objects.append(page) 
    108             pages["/Kids"].append(IndirectObject(len(objects), 0, self)) 
     109        self.stack = [] 
     110        self._sweepIndirectReferences(externalReferenceMap, self._root) 
     111        del self.stack 
    109112 
    110113        # Begin writing: 
    111         stream.write(self.header + "\n") 
    112         for i in range(len(objects)): 
    113             obj = objects[i] 
    114             objects[i] = stream.tell() 
     114        object_positions = [] 
     115        stream.write(self._header + "\n") 
     116        for i in range(len(self._objects)): 
     117            obj = self._objects[i] 
     118            object_positions.append(stream.tell()) 
    115119            stream.write(str(i + 1) + " 0 obj\n") 
    116120            obj.writeToStream(stream) 
     
    120124        xref_location = stream.tell() 
    121125        stream.write("xref\n") 
    122         stream.write("0 %s\n" % (len(objects) + 1)) 
     126        stream.write("0 %s\n" % (len(self._objects) + 1)) 
    123127        stream.write("%010d %05d f \n" % (0, 65535)) 
    124         for offset in objects: 
     128        for offset in object_positions: 
    125129            stream.write("%010d %05d n \n" % (offset, 0)) 
    126130 
     
    129133        trailer = DictionaryObject() 
    130134        trailer.update({ 
    131                 NameObject("/Size"): NumberObject(len(objects) + 1), 
    132                 NameObject("/Root"): root, 
    133                 NameObject("/Info"): info, 
     135                NameObject("/Size"): NumberObject(len(self._objects) + 1), 
     136                NameObject("/Root"): self._root, 
     137                NameObject("/Info"): self._info, 
    134138                }) 
    135139        trailer.writeToStream(stream) 
     
    138142        stream.write("\nstartxref\n%s\n%%%%EOF\n" % (xref_location)) 
    139143 
    140     def sweepIndirectReferences(self, externMap, objects, data): 
     144    def _sweepIndirectReferences(self, externMap, data): 
    141145        if isinstance(data, DictionaryObject): 
    142146            for key, value in data.items(): 
    143147                origvalue = value 
    144                 value = self.sweepIndirectReferences(externMap, objects, value) 
     148                value = self._sweepIndirectReferences(externMap, value) 
    145149                if value == None: 
    146150                    print objects, value, origvalue 
     
    148152                    # a dictionary value is a stream.  streams must be indirect 
    149153                    # objects, so we need to change this value. 
    150                     objects.append(value) 
    151                     value = IndirectObject(len(objects), 0, self) 
     154                    value = self._addObject(value) 
    152155                data[key] = value 
    153156            return data 
    154157        elif isinstance(data, ArrayObject): 
    155158            for i in range(len(data)): 
    156                 data[i] = self.sweepIndirectReferences(externMap, objects, data[i]) 
     159                data[i] = self._sweepIndirectReferences(externMap, data[i]) 
    157160            return data 
    158161        elif isinstance(data, IndirectObject): 
    159162            # internal indirect references are fine 
    160             if data.pdf != self: 
     163            if data.pdf == self: 
     164                if data.idnum in self.stack: 
     165                    return data 
     166                else: 
     167                    self.stack.append(data.idnum) 
     168                    realdata = self._getObject(data) 
     169                    self._sweepIndirectReferences(externMap, realdata) 
     170                    self.stack.pop() 
     171                    return data 
     172            else: 
    161173                newobj = externMap.get(data.pdf, {}).get(data.generation, {}).get(data.idnum, None) 
    162174                if newobj == None: 
    163175                    newobj = data.pdf.getObject(data) 
    164                     objects.append(None) # placeholder 
    165                     idnum = len(objects) 
     176                    self._objects.append(None) # placeholder 
     177                    idnum = len(self._objects) 
    166178                    newobj_ido = IndirectObject(idnum, 0, self) 
    167179                    if not externMap.has_key(data.pdf): 
     
    170182                        externMap[data.pdf][data.generation] = {} 
    171183                    externMap[data.pdf][data.generation][data.idnum] = newobj_ido 
    172                     newobj = self.sweepIndirectReferences(externMap, objects, newobj) 
    173                     objects[idnum-1] = newobj 
     184                    newobj = self._sweepIndirectReferences(externMap, newobj) 
     185                    self._objects[idnum-1] = newobj 
    174186                    return newobj_ido 
    175187                return newobj 
    176             else: 
    177                 return data 
    178188        else: 
    179189            return data 
     
    201211        """ 
    202212        if self.flattenedPages == None: 
    203             self.flatten() 
     213            self._flatten() 
    204214        return len(self.flattenedPages) 
    205215 
     
    214224        assert not self.trailer.has_key("/Encrypt") 
    215225        if self.flattenedPages == None: 
    216             self.flatten() 
     226            self._flatten() 
    217227        return self.flattenedPages[pageNumber] 
    218228 
    219     def flatten(self, pages = None, inherit = None): 
     229    def _flatten(self, pages = None, inherit = None): 
    220230        inheritablePageAttributes = ( 
    221231            NameObject("/Resources"), NameObject("/MediaBox"), 
     
    236246                    inherit[attr] = pages[attr] 
    237247            for page in pages["/Kids"]: 
    238                 self.flatten(page, inherit) 
     248                self._flatten(page, inherit) 
    239249        elif t == "/Page": 
    240250            for attr,value in inherit.items():