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() |