| OLD | NEW |
| (Empty) | |
| 1 #!/usr/bin/env python |
| 2 # Copyright 2014 The PDFium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 """Expands a hand-written PDF testcase (template) into a valid PDF file. |
| 7 |
| 8 There are several places in a PDF file where byte-offsets are required. This |
| 9 script replaces {{name}}-style variables in the input with calculated results |
| 10 |
| 11 {{header}} - expands to the header comment required for PDF files. |
| 12 {{xref}} - expands to a generated xref table, noting the offset. |
| 13 {{startxref} - expands to a startxref directive followed by correct offset. |
| 14 {{object x y}} - expands to |x y obj| declaration, noting the offset.""" |
| 15 |
| 16 import optparse |
| 17 import os |
| 18 import re |
| 19 import sys |
| 20 |
| 21 class TemplateProcessor: |
| 22 HEADER_TOKEN = '{{header}}' |
| 23 HEADER_REPLACEMENT = '%PDF-1.7\n%\xa0\xf2\xa4\xf4' |
| 24 |
| 25 XREF_TOKEN = '{{xref}}' |
| 26 XREF_REPLACEMENT = 'xref\n%d %d\n' |
| 27 XREF_REPLACEMENT_N = '%010d %05d n\n' |
| 28 XREF_REPLACEMENT_F = '0000000000 65536 f\n' |
| 29 |
| 30 STARTXREF_TOKEN= '{{startxref}}' |
| 31 STARTXREF_REPLACEMENT = 'startxref\n%d' |
| 32 |
| 33 OBJECT_PATTERN = r'\{\{object\s+(\d+)\s+(\d+)\}\}' |
| 34 OBJECT_REPLACEMENT = r'\1 \2 obj' |
| 35 |
| 36 def __init__(self): |
| 37 self.offset = 0 |
| 38 self.xref_offset = 0 |
| 39 self.max_object_number = 0 |
| 40 self.objects = { } |
| 41 |
| 42 def insert_xref_entry(self, object_number, generation_number): |
| 43 self.objects[object_number] = (self.offset, generation_number) |
| 44 self.max_object_number = max(self.max_object_number, object_number) |
| 45 |
| 46 def generate_xref_table(self): |
| 47 result = self.XREF_REPLACEMENT % (0, self.max_object_number + 1) |
| 48 for i in range(0, self.max_object_number + 1): |
| 49 if i in self.objects: |
| 50 result += self.XREF_REPLACEMENT_N % self.objects[i] |
| 51 else: |
| 52 result += self.XREF_REPLACEMENT_F |
| 53 return result |
| 54 |
| 55 def process_line(self, line): |
| 56 if self.HEADER_TOKEN in line: |
| 57 line = line.replace(self.HEADER_TOKEN, self.HEADER_REPLACEMENT) |
| 58 if self.XREF_TOKEN in line: |
| 59 self.xref_offset = self.offset |
| 60 line = self.generate_xref_table() |
| 61 if self.STARTXREF_TOKEN in line: |
| 62 replacement = self.STARTXREF_REPLACEMENT % self.xref_offset |
| 63 line = line.replace(self.STARTXREF_TOKEN, replacement) |
| 64 match = re.match(self.OBJECT_PATTERN, line) |
| 65 if match: |
| 66 self.insert_xref_entry(int(match.group(1)), int(match.group(2))) |
| 67 line = re.sub(self.OBJECT_PATTERN, self.OBJECT_REPLACEMENT, line) |
| 68 self.offset += len(line) |
| 69 return line |
| 70 |
| 71 def expand_file(input_filename): |
| 72 (input_root, extension) = os.path.splitext(input_filename) |
| 73 output_filename = input_root + '.pdf' |
| 74 processor = TemplateProcessor() |
| 75 try: |
| 76 with open(input_filename, 'r') as infile: |
| 77 with open(output_filename, 'w') as outfile: |
| 78 for line in infile: |
| 79 outfile.write(processor.process_line(line)) |
| 80 except IOError: |
| 81 print >> sys.stderr, 'failed to process %s' % input_filename |
| 82 |
| 83 def main(): |
| 84 for arg in sys.argv[1:]: |
| 85 expand_file(arg) |
| 86 return 0 |
| 87 |
| 88 if __name__ == '__main__': |
| 89 sys.exit(main()) |
| OLD | NEW |