QScintilla/Exporters/ExporterPDF.py

changeset 3011
18292228c724
parent 2965
d133c7edd88a
child 3034
7ce719013078
child 3057
10516539f238
equal deleted inserted replaced
3010:befeff46ec0f 3011:18292228c724
26 PDF_MARGIN_DEFAULT = 72 # 1.0" 26 PDF_MARGIN_DEFAULT = 72 # 1.0"
27 PDF_ENCODING = "WinAnsiEncoding" 27 PDF_ENCODING = "WinAnsiEncoding"
28 28
29 PDFfontNames = [ 29 PDFfontNames = [
30 "Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique", 30 "Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique",
31 "Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique", 31 "Helvetica", "Helvetica-Bold", "Helvetica-Oblique",
32 "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic" 32 "Helvetica-BoldOblique", "Times-Roman", "Times-Bold", "Times-Italic",
33 "Times-BoldItalic"
33 ] 34 ]
34 PDFfontAscenders = [629, 718, 699] 35 PDFfontAscenders = [629, 718, 699]
35 PDFfontDescenders = [157, 207, 217] 36 PDFfontDescenders = [157, 207, 217]
36 PDFfontWidths = [600, 0, 0] 37 PDFfontWidths = [600, 0, 0]
37 38
172 if style_ == -1: 173 if style_ == -1:
173 styleNext = self.styleCurrent 174 styleNext = self.styleCurrent
174 175
175 buf = "" 176 buf = ""
176 if styleNext != self.styleCurrent or style_ == -1: 177 if styleNext != self.styleCurrent or style_ == -1:
177 if self.style[self.styleCurrent].font != self.style[styleNext].font or \ 178 if self.style[self.styleCurrent].font != \
178 style_ == -1: 179 self.style[styleNext].font or style_ == -1:
179 buf += "/F{0:d} {1:d} Tf ".format(self.style[styleNext].font + 1, 180 buf += "/F{0:d} {1:d} Tf ".format(
180 self.fontSize) 181 self.style[styleNext].font + 1, self.fontSize)
181 if self.style[self.styleCurrent].fore != self.style[styleNext].fore or \ 182 if self.style[self.styleCurrent].fore != \
182 style_ == -1: 183 self.style[styleNext].fore or style_ == -1:
183 buf += "{0}rg ".format(self.style[styleNext].fore) 184 buf += "{0}rg ".format(self.style[styleNext].fore)
184 return buf 185 return buf
185 186
186 def startPDF(self): 187 def startPDF(self):
187 """ 188 """
211 # build objects for font resources; note that font objects are 212 # build objects for font resources; note that font objects are
212 # *expected* to start from index 1 since they are the first objects 213 # *expected* to start from index 1 since they are the first objects
213 # to be inserted (PDF1.4Ref(p317)) 214 # to be inserted (PDF1.4Ref(p317))
214 for i in range(4): 215 for i in range(4):
215 buffer = \ 216 buffer = \
216 "<</Type/Font/Subtype/Type1/Name/F{0:d}/BaseFont/{1}/Encoding/{2}>>\n"\ 217 "<</Type/Font/Subtype/Type1/Name/F{0:d}/BaseFont/{1}/" \
217 .format(i + 1, PDFfontNames[self.fontSet * 4 + i], PDF_ENCODING) 218 "Encoding/{2}>>\n".format(
219 i + 1, PDFfontNames[self.fontSet * 4 + i], PDF_ENCODING)
218 self.oT.add(buffer) 220 self.oT.add(buffer)
219 221
220 self.pageContentStart = self.oT.index 222 self.pageContentStart = self.oT.index
221 223
222 def endPDF(self): 224 def endPDF(self):
227 # flush buffers 229 # flush buffers
228 self.endPage() 230 self.endPage()
229 231
230 # refer to all used or unused fonts for simplicity 232 # refer to all used or unused fonts for simplicity
231 resourceRef = self.oT.add( 233 resourceRef = self.oT.add(
232 "<</ProcSet[/PDF/Text]\n/Font<</F1 1 0 R/F2 2 0 R/F3 3 0 R/F4 4 0 R>> >>\n") 234 "<</ProcSet[/PDF/Text]\n/Font<</F1 1 0 R/F2 2 0 R/F3 3 0 R/"
235 "F4 4 0 R>> >>\n")
233 236
234 # create all the page objects (PDF1.4Ref(p88)) 237 # create all the page objects (PDF1.4Ref(p88))
235 # forward reference pages object; calculate its object number 238 # forward reference pages object; calculate its object number
236 pageObjectStart = self.oT.index 239 pageObjectStart = self.oT.index
237 pagesRef = pageObjectStart + self.pageCount 240 pagesRef = pageObjectStart + self.pageCount
257 260
258 # append the cross reference table (PDF1.4Ref(p64)) 261 # append the cross reference table (PDF1.4Ref(p64))
259 xref = self.oT.xref() 262 xref = self.oT.xref()
260 263
261 # end the file with the trailer (PDF1.4Ref(p67)) 264 # end the file with the trailer (PDF1.4Ref(p67))
262 buffer = "trailer\n<< /Size {0:d} /Root {1:d} 0 R\n>>\nstartxref\n{2:d}\n%%EOF\n"\ 265 buffer = \
263 .format(self.oT.index, catalogRef, xref) 266 "trailer\n<< /Size {0:d} /Root {1:d} 0 R\n>>\nstartxref\n{2:d}\n" \
267 "%%EOF\n".format(self.oT.index, catalogRef, xref)
264 self.oT.write(buffer) 268 self.oT.write(buffer)
265 269
266 def add(self, ch, style_): 270 def add(self, ch, style_):
267 """ 271 """
268 Public method to add a character to the page. 272 Public method to add a character to the page.
423 tabSize = Preferences.getEditor("TabWidth") 427 tabSize = Preferences.getEditor("TabWidth")
424 if tabSize == 0: 428 if tabSize == 0:
425 tabSize = 4 429 tabSize = 4
426 430
427 # get magnification value to add to default screen font size 431 # get magnification value to add to default screen font size
428 self.pr.fontSize = Preferences.getEditorExporter("PDF/Magnification") 432 self.pr.fontSize = Preferences.getEditorExporter(
433 "PDF/Magnification")
429 434
430 # set font family according to face name 435 # set font family according to face name
431 fontName = Preferences.getEditorExporter("PDF/Font") 436 fontName = Preferences.getEditorExporter("PDF/Font")
432 self.pr.fontSet = PDF_FONT_DEFAULT 437 self.pr.fontSet = PDF_FONT_DEFAULT
433 if fontName == "Courier": 438 if fontName == "Courier":
519 else: 524 else:
520 self.pr.fontSize = PDF_FONTSIZE_DEFAULT 525 self.pr.fontSize = PDF_FONTSIZE_DEFAULT
521 526
522 try: 527 try:
523 # save file in win ansi using cp1250 528 # save file in win ansi using cp1250
524 f = open(filename, "w", encoding="cp1250", errors="backslashreplace") 529 f = open(filename, "w", encoding="cp1250",
530 errors="backslashreplace")
525 531
526 # initialise PDF rendering 532 # initialise PDF rendering
527 ot = PDFObjectTracker(f) 533 ot = PDFObjectTracker(f)
528 self.pr.oT = ot 534 self.pr.oT = ot
529 self.pr.startPDF() 535 self.pr.startPDF()
548 # expand tabs 554 # expand tabs
549 ts = tabSize - (column % tabSize) 555 ts = tabSize - (column % tabSize)
550 column += ts 556 column += ts
551 self.pr.add(' ' * ts, style) 557 self.pr.add(' ' * ts, style)
552 elif ch == b'\r' or ch == b'\n': 558 elif ch == b'\r' or ch == b'\n':
553 if ch == b'\r' and self.editor.byteAt(pos + 1) == b'\n': 559 if ch == b'\r' and \
560 self.editor.byteAt(pos + 1) == b'\n':
554 pos += 1 561 pos += 1
555 # close and begin a newline... 562 # close and begin a newline...
556 self.pr.nextLine() 563 self.pr.nextLine()
557 column = 0 564 column = 0
558 else: 565 else:
564 utf8Len = 4 571 utf8Len = 4
565 elif (utf8Ch[0] & 0xE0) == 0xE0: 572 elif (utf8Ch[0] & 0xE0) == 0xE0:
566 utf8Len = 3 573 utf8Len = 3
567 elif (utf8Ch[0] & 0xC0) == 0xC0: 574 elif (utf8Ch[0] & 0xC0) == 0xC0:
568 utf8Len = 2 575 utf8Len = 2
569 column -= 1 # will be incremented again later 576 column -= 1 # will be incremented
577 # again later
570 elif len(utf8Ch) == utf8Len: 578 elif len(utf8Ch) == utf8Len:
571 ch = utf8Ch.decode('utf8') 579 ch = utf8Ch.decode('utf8')
572 self.pr.add(ch, style) 580 self.pr.add(ch, style)
573 utf8Ch = b"" 581 utf8Ch = b""
574 utf8Len = 0 582 utf8Len = 0
575 else: 583 else:
576 column -= 1 # will be incremented again later 584 column -= 1 # will be incremented
585 # again later
577 else: 586 else:
578 self.pr.add(ch.decode(), style) 587 self.pr.add(ch.decode(), style)
579 column += 1 588 column += 1
580 589
581 pos += 1 590 pos += 1
583 # write required stuff and close the PDF file 592 # write required stuff and close the PDF file
584 self.pr.endPDF() 593 self.pr.endPDF()
585 f.close() 594 f.close()
586 except IOError as err: 595 except IOError as err:
587 QApplication.restoreOverrideCursor() 596 QApplication.restoreOverrideCursor()
588 E5MessageBox.critical(self.editor, 597 E5MessageBox.critical(
598 self.editor,
589 self.trUtf8("Export source"), 599 self.trUtf8("Export source"),
590 self.trUtf8( 600 self.trUtf8(
591 """<p>The source could not be exported to <b>{0}</b>.</p>""" 601 """<p>The source could not be exported to"""
592 """<p>Reason: {1}</p>""")\ 602 """ <b>{0}</b>.</p><p>Reason: {1}</p>""")\
593 .format(filename, str(err))) 603 .format(filename, str(err)))
594 finally: 604 finally:
595 QApplication.restoreOverrideCursor() 605 QApplication.restoreOverrideCursor()

eric ide

mercurial