22 import Preferences |
22 import Preferences |
23 |
23 |
24 PDF_FONT_DEFAULT = 1 # Helvetica |
24 PDF_FONT_DEFAULT = 1 # Helvetica |
25 PDF_FONTSIZE_DEFAULT = 10 |
25 PDF_FONTSIZE_DEFAULT = 10 |
26 PDF_SPACING_DEFAULT = 1.2 |
26 PDF_SPACING_DEFAULT = 1.2 |
27 PDF_MARGIN_DEFAULT = 72 # 1.0" |
27 PDF_MARGIN_DEFAULT = 72 # 1.0" |
28 PDF_ENCODING = "WinAnsiEncoding" |
28 PDF_ENCODING = "WinAnsiEncoding" |
29 |
29 |
30 PDFfontNames = [ |
30 PDFfontNames = [ |
31 "Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique", |
31 "Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique", |
32 "Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique", |
32 "Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique", |
33 "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic" |
33 "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic" |
34 ] |
34 ] |
35 PDFfontAscenders = [629, 718, 699] |
35 PDFfontAscenders = [629, 718, 699] |
36 PDFfontDescenders = [157, 207, 217] |
36 PDFfontDescenders = [157, 207, 217] |
37 PDFfontWidths = [600, 0, 0] |
37 PDFfontWidths = [600, 0, 0] |
38 |
38 |
39 PDFpageSizes = { |
39 PDFpageSizes = { |
40 # name : (height, width) |
40 # name : (height, width) |
41 "Letter" : (792, 612), |
41 "Letter": (792, 612), |
42 "A4" : (842, 595), |
42 "A4": (842, 595), |
43 } |
43 } |
|
44 |
44 |
45 |
45 class PDFStyle(object): |
46 class PDFStyle(object): |
46 """ |
47 """ |
47 Simple class to store the values of a PDF style. |
48 Simple class to store the values of a PDF style. |
48 """ |
49 """ |
112 while ind < len(self.offsetList): |
114 while ind < len(self.offsetList): |
113 self.write("{0:010d} 00000 n \n".format(self.offsetList[ind])) |
115 self.write("{0:010d} 00000 n \n".format(self.offsetList[ind])) |
114 ind += 1 |
116 ind += 1 |
115 return xrefStart |
117 return xrefStart |
116 |
118 |
|
119 |
117 class PDFRender(object): |
120 class PDFRender(object): |
118 """ |
121 """ |
119 Class to manage line and page rendering. |
122 Class to manage line and page rendering. |
120 |
123 |
121 Apart from startPDF, endPDF everything goes in via add() and nextLine() |
124 Apart from startPDF, endPDF everything goes in via add() and nextLine() |
122 so that line formatting and pagination can be done properly. |
125 so that line formatting and pagination can be done properly. |
123 """ |
126 """ |
124 def __init__(self): |
127 def __init__(self): |
170 |
173 |
171 buf = "" |
174 buf = "" |
172 if styleNext != self.styleCurrent or style_ == -1: |
175 if styleNext != self.styleCurrent or style_ == -1: |
173 if self.style[self.styleCurrent].font != self.style[styleNext].font or \ |
176 if self.style[self.styleCurrent].font != self.style[styleNext].font or \ |
174 style_ == -1: |
177 style_ == -1: |
175 buf += "/F{0:d} {1:d} Tf ".format(self.style[styleNext].font + 1, |
178 buf += "/F{0:d} {1:d} Tf ".format(self.style[styleNext].font + 1, |
176 self.fontSize) |
179 self.fontSize) |
177 if self.style[self.styleCurrent].fore != self.style[styleNext].fore or \ |
180 if self.style[self.styleCurrent].fore != self.style[styleNext].fore or \ |
178 style_ == -1: |
181 style_ == -1: |
179 buf += "{0}rg ".format(self.style[styleNext].fore) |
182 buf += "{0}rg ".format(self.style[styleNext].fore) |
180 return buf |
183 return buf |
234 for i in range(self.pageCount): |
237 for i in range(self.pageCount): |
235 buffer = "<</Type/Page/Parent {0:d} 0 R\n" \ |
238 buffer = "<</Type/Page/Parent {0:d} 0 R\n" \ |
236 "/MediaBox[ 0 0 {1:d} {2:d}]\n" \ |
239 "/MediaBox[ 0 0 {1:d} {2:d}]\n" \ |
237 "/Contents {3:d} 0 R\n" \ |
240 "/Contents {3:d} 0 R\n" \ |
238 "/Resources {4:d} 0 R\n>>\n".format( |
241 "/Resources {4:d} 0 R\n>>\n".format( |
239 pagesRef, self.pageWidth, self.pageHeight, |
242 pagesRef, self.pageWidth, self.pageHeight, |
240 self.pageContentStart + i, resourceRef) |
243 self.pageContentStart + i, resourceRef) |
241 self.oT.add(buffer) |
244 self.oT.add(buffer) |
242 |
245 |
243 # create page tree object (PDF1.4Ref(p86)) |
246 # create page tree object (PDF1.4Ref(p86)) |
244 self.pageData = "<</Type/Pages/Kids[\n" |
247 self.pageData = "<</Type/Pages/Kids[\n" |
289 # escape these characters |
292 # escape these characters |
290 if ch == ')' or ch == '(' or ch == '\\': |
293 if ch == ')' or ch == '(' or ch == '\\': |
291 self.segment += '\\' |
294 self.segment += '\\' |
292 if ch != ' ': |
295 if ch != ' ': |
293 self.justWhiteSpace = False |
296 self.justWhiteSpace = False |
294 self.segment += ch # add to segment data |
297 self.segment += ch # add to segment data |
295 |
298 |
296 def flushSegment(self): |
299 def flushSegment(self): |
297 """ |
300 """ |
298 Public method to flush a segment of data. |
301 Public method to flush a segment of data. |
299 """ |
302 """ |
367 self.firstLine = False |
370 self.firstLine = False |
368 else: |
371 else: |
369 buffer = "T*\n" |
372 buffer = "T*\n" |
370 self.pageData += buffer |
373 self.pageData += buffer |
371 |
374 |
|
375 |
372 class ExporterPDF(ExporterBase): |
376 class ExporterPDF(ExporterBase): |
373 """ |
377 """ |
374 Class implementing an exporter for PDF. |
378 Class implementing an exporter for PDF. |
375 """ |
379 """ |
376 def __init__(self, editor, parent = None): |
380 def __init__(self, editor, parent=None): |
377 """ |
381 """ |
378 Constructor |
382 Constructor |
379 |
383 |
380 @param editor reference to the editor object (QScintilla.Editor.Editor) |
384 @param editor reference to the editor object (QScintilla.Editor.Editor) |
381 @param parent parent object of the exporter (QObject) |
385 @param parent parent object of the exporter (QObject) |
430 elif fontName == "Helvetica": |
434 elif fontName == "Helvetica": |
431 self.pr.fontSet = 1 |
435 self.pr.fontSet = 1 |
432 elif fontName == "Times": |
436 elif fontName == "Times": |
433 self.pr.fontSet = 2 |
437 self.pr.fontSet = 2 |
434 |
438 |
435 # page size: height, width, |
439 # page size: height, width, |
436 pageSize = Preferences.getEditorExporter("PDF/PageSize") |
440 pageSize = Preferences.getEditorExporter("PDF/PageSize") |
437 try: |
441 try: |
438 pageDimensions = PDFpageSizes[pageSize] |
442 pageDimensions = PDFpageSizes[pageSize] |
439 except KeyError: |
443 except KeyError: |
440 pageDimensions = PDFpageSizes["A4"] |
444 pageDimensions = PDFpageSizes["A4"] |
514 else: |
518 else: |
515 self.pr.fontSize = PDF_FONTSIZE_DEFAULT |
519 self.pr.fontSize = PDF_FONTSIZE_DEFAULT |
516 |
520 |
517 try: |
521 try: |
518 # save file in win ansi using cp1250 |
522 # save file in win ansi using cp1250 |
519 f = open(filename, "w", encoding = "cp1250", errors = "backslashreplace") |
523 f = open(filename, "w", encoding="cp1250", errors="backslashreplace") |
520 |
524 |
521 # initialise PDF rendering |
525 # initialise PDF rendering |
522 ot = PDFObjectTracker(f) |
526 ot = PDFObjectTracker(f) |
523 self.pr.oT = ot |
527 self.pr.oT = ot |
524 self.pr.startPDF() |
528 self.pr.startPDF() |
525 |
529 |
526 # do here all the writing |
530 # do here all the writing |
527 lengthDoc = self.editor.length() |
531 lengthDoc = self.editor.length() |
528 |
532 |
529 if lengthDoc == 0: |
533 if lengthDoc == 0: |
530 self.pr.nextLine() # enable zero length docs |
534 self.pr.nextLine() # enable zero length docs |
531 else: |
535 else: |
532 pos = 0 |
536 pos = 0 |
533 column = 0 |
537 column = 0 |
534 utf8 = self.editor.isUtf8() |
538 utf8 = self.editor.isUtf8() |
535 utf8Ch = b"" |
539 utf8Ch = b"" |
559 utf8Len = 4 |
563 utf8Len = 4 |
560 elif (utf8Ch[0] & 0xE0) == 0xE0: |
564 elif (utf8Ch[0] & 0xE0) == 0xE0: |
561 utf8Len = 3 |
565 utf8Len = 3 |
562 elif (utf8Ch[0] & 0xC0) == 0xC0: |
566 elif (utf8Ch[0] & 0xC0) == 0xC0: |
563 utf8Len = 2 |
567 utf8Len = 2 |
564 column -= 1 # will be incremented again later |
568 column -= 1 # will be incremented again later |
565 elif len(utf8Ch) == utf8Len: |
569 elif len(utf8Ch) == utf8Len: |
566 ch = utf8Ch.decode('utf8') |
570 ch = utf8Ch.decode('utf8') |
567 self.pr.add(ch, style) |
571 self.pr.add(ch, style) |
568 utf8Ch = b"" |
572 utf8Ch = b"" |
569 utf8Len = 0 |
573 utf8Len = 0 |
570 else: |
574 else: |
571 column -= 1 # will be incremented again later |
575 column -= 1 # will be incremented again later |
572 else: |
576 else: |
573 self.pr.add(ch.decode(), style) |
577 self.pr.add(ch.decode(), style) |
574 column += 1 |
578 column += 1 |
575 |
579 |
576 pos += 1 |
580 pos += 1 |