├── examples ├── __init__.py ├── simple-csv-invoice.txt ├── simple-csv-invoice.py └── form.py ├── docs ├── index.md ├── reference │ ├── page_no.md │ ├── get_x.md │ ├── get_y.md │ ├── set_font_size.md │ ├── set_title.md │ ├── open.md │ ├── set_subject.md │ ├── set_author.md │ ├── set_x.md │ ├── close.md │ ├── get_string_width.md │ ├── ln.md │ ├── set_y.md │ ├── set_keywords.md │ ├── error.md │ ├── set_creator.md │ ├── set_top_margin.md │ ├── set_compression.md │ ├── set_line_width.md │ ├── set_right_margin.md │ ├── set_xy.md │ ├── add_link.md │ ├── accept_page_break.md │ ├── set_left_margin.md │ ├── set_link.md │ ├── line.md │ ├── set_doc_option.md │ ├── set_margins.md │ ├── set_auto_page_break.md │ ├── rect.md │ ├── set_stretching.md │ ├── load_resource.md │ ├── text.md │ ├── set_text_color.md │ ├── alias_nb_pages.md │ ├── link.md │ ├── header.md │ ├── footer.md │ ├── set_fill_color.md │ ├── ellipse.md │ ├── set_draw_color.md │ ├── dashed_line.md │ ├── rotate.md │ ├── output.md │ ├── write.md │ ├── set_display_mode.md │ ├── FPDF.md │ ├── multi_cell.md │ ├── add_page.md │ ├── image.md │ ├── cell.md │ ├── write_html.md │ ├── add_font.md │ └── set_font.md ├── Development.md ├── Python3.md ├── ReferenceManual.md ├── Testing.md └── ProjectHome.md ├── tests ├── lena.gif ├── py3k.pdf ├── flower2.jpg ├── img_cmyk.jpg ├── img_gray.jpg ├── img_rgb.jpg ├── masking.png ├── cover │ ├── __init__.py │ ├── test_issue63.py │ ├── checkenv.py │ ├── test_issue35.py │ ├── test_issue14.py │ ├── test_issue41.py │ ├── test_py3k.py │ ├── test_page_orient.py │ ├── test_issue71.py │ ├── test_page_size.py │ ├── test_issue70.py │ ├── test_jpeg.py │ ├── test_unicode.py │ ├── test_simple.py │ ├── test_nbpages.py │ ├── test_issue78.py │ ├── test_template.py │ ├── test_issue82.py │ ├── test_imgmask.py │ ├── test_issue62.py │ ├── test_issue60.py │ ├── test_winfonts.py │ ├── test_output.py │ ├── test_stretching.py │ ├── test_ttfonts.py │ └── test_issue33.py ├── dejavusanscondensed.cw.dat ├── prepare_local.bat ├── prepare_local.sh ├── HelloWorld.txt ├── issue65.py ├── respacks.txt ├── unifonts.py ├── unzlib.py ├── charmap.py ├── html_unicode.py └── html_.py ├── tutorial ├── index.htm ├── logo.png ├── tuto1.pdf ├── tuto2.htm ├── tuto2.pdf ├── tuto3.pdf ├── 20k_c1.txt ├── gradients.py ├── logo_pb.png ├── unicode.pdf ├── tuto1.py ├── tuto7.py ├── bookmark.py ├── tuto2.py ├── tuto3.py ├── unicode.py ├── tuto5.py ├── tuto4.py └── tuto6.py ├── attic ├── font │ ├── calligra.z │ ├── calligra.ttf │ ├── courier.py │ ├── symbol.py │ ├── times.py │ ├── timesi.py │ ├── timesb.py │ ├── timesbi.py │ ├── helvetica.py │ ├── helveticabi.py │ ├── helveticai.py │ ├── helveticab.py │ ├── zapfdingbats.py │ ├── calligra.py │ ├── cp874.map │ ├── cp1253.map │ └── cp1255.map ├── utils │ ├── Fix3.py │ ├── Fix2.py │ ├── Fix1.py │ └── PDFRUUtils.py ├── PHPutils.py ├── Bookmark.py └── TOC.py ├── setup.cfg ├── .gitignore ├── fpdf ├── __init__.py ├── php.py └── py3k.py ├── .hgtags ├── README.md ├── setup.py └── mkdocs.yml /examples/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | ProjectHome.md -------------------------------------------------------------------------------- /tests/lena.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tests/lena.gif -------------------------------------------------------------------------------- /tests/py3k.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tests/py3k.pdf -------------------------------------------------------------------------------- /tests/flower2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tests/flower2.jpg -------------------------------------------------------------------------------- /tests/img_cmyk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tests/img_cmyk.jpg -------------------------------------------------------------------------------- /tests/img_gray.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tests/img_gray.jpg -------------------------------------------------------------------------------- /tests/img_rgb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tests/img_rgb.jpg -------------------------------------------------------------------------------- /tests/masking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tests/masking.png -------------------------------------------------------------------------------- /tutorial/index.htm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tutorial/index.htm -------------------------------------------------------------------------------- /tutorial/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tutorial/logo.png -------------------------------------------------------------------------------- /tutorial/tuto1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tutorial/tuto1.pdf -------------------------------------------------------------------------------- /tutorial/tuto2.htm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tutorial/tuto2.htm -------------------------------------------------------------------------------- /tutorial/tuto2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tutorial/tuto2.pdf -------------------------------------------------------------------------------- /tutorial/tuto3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tutorial/tuto3.pdf -------------------------------------------------------------------------------- /attic/font/calligra.z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/attic/font/calligra.z -------------------------------------------------------------------------------- /tutorial/20k_c1.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tutorial/20k_c1.txt -------------------------------------------------------------------------------- /tutorial/gradients.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tutorial/gradients.py -------------------------------------------------------------------------------- /tutorial/logo_pb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tutorial/logo_pb.png -------------------------------------------------------------------------------- /tutorial/unicode.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tutorial/unicode.pdf -------------------------------------------------------------------------------- /attic/font/calligra.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/attic/font/calligra.ttf -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | 4 | [wheel] 5 | universal = 1 6 | 7 | -------------------------------------------------------------------------------- /tests/cover/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # -*- coding: utf-8 -*- 3 | 4 | from .common import * 5 | 6 | 7 | -------------------------------------------------------------------------------- /tests/cover/test_issue63.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tests/cover/test_issue63.py -------------------------------------------------------------------------------- /tests/dejavusanscondensed.cw.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reingart/pyfpdf/HEAD/tests/dejavusanscondensed.cw.dat -------------------------------------------------------------------------------- /tests/prepare_local.bat: -------------------------------------------------------------------------------- 1 | 2 | rem prepare local copy for tests 3 | 4 | mkdir fpdf_local 5 | mkdir fpdf_local/fpdf 6 | 7 | cp ../fpdf/*.py fpdf_local/fpdf/ 8 | 9 | -------------------------------------------------------------------------------- /tutorial/tuto1.py: -------------------------------------------------------------------------------- 1 | from fpdf import FPDF 2 | 3 | pdf = FPDF() 4 | pdf.add_page() 5 | pdf.set_font('Arial', 'B', 16) 6 | pdf.cell(40, 10, 'Hello World!') 7 | pdf.output('tuto1.pdf', 'F') 8 | 9 | -------------------------------------------------------------------------------- /docs/reference/page_no.md: -------------------------------------------------------------------------------- 1 | ## page_no ## 2 | 3 | ```python 4 | fpdf.page_no() 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Returns the current page number. 10 | 11 | ### See also ### 12 | 13 | [alias_nb_pages](alias_nb_pages.md). 14 | -------------------------------------------------------------------------------- /tests/prepare_local.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # prepare local copy for tests 4 | 5 | mkdir fpdf_local 6 | mkdir fpdf_local/fpdf 7 | 8 | cp ../fpdf/*.py fpdf_local/fpdf/ 9 | 10 | echo Now you can test: 11 | echo python runtest.py 12 | 13 | 14 | -------------------------------------------------------------------------------- /tutorial/tuto7.py: -------------------------------------------------------------------------------- 1 | from fpdf import * 2 | 3 | pdf = FPDF() 4 | pdf.add_font('Calligrapher', '', 'calligra') 5 | pdf.add_page() 6 | pdf.set_font('Calligrapher', '', 35) 7 | pdf.cell(0, 10, 'Enjoy new fonts with FPDF!') 8 | pdf.output('tuto7.pdf', 'F') 9 | 10 | -------------------------------------------------------------------------------- /docs/reference/get_x.md: -------------------------------------------------------------------------------- 1 | ## get_x ## 2 | 3 | ```python 4 | fpdf.get_x() 5 | ``` 6 | ### Description ### 7 | 8 | Returns the abscissa of the current position. 9 | 10 | 11 | ### See also ### 12 | 13 | [get_y](get_y.md), [set_x](set_x.md), [set_y](set_y.md), [set_xy](set_xy.md). 14 | -------------------------------------------------------------------------------- /docs/reference/get_y.md: -------------------------------------------------------------------------------- 1 | ## get_y ## 2 | 3 | ```python 4 | fpdf.get_y() 5 | ``` 6 | ### Description ### 7 | 8 | Returns the ordinate of the current position. 9 | 10 | 11 | ### See also ### 12 | 13 | [get_x](get_x.md), [set_x](set_x.md), [set_y](set_y.md), [set_xy](set_xy.md). 14 | -------------------------------------------------------------------------------- /attic/font/courier.py: -------------------------------------------------------------------------------- 1 | fpdf_charwidths['courier']={} 2 | 3 | for i in xrange(0,256): 4 | fpdf_charwidths['courier'][chr(i)]=600 5 | fpdf_charwidths['courierB']=fpdf_charwidths['courier'] 6 | fpdf_charwidths['courierI']=fpdf_charwidths['courier'] 7 | fpdf_charwidths['courierBI']=fpdf_charwidths['courier'] 8 | -------------------------------------------------------------------------------- /docs/reference/set_font_size.md: -------------------------------------------------------------------------------- 1 | ## set_font_size ## 2 | 3 | ```python 4 | fpdf.set_font_size(float size) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Defines the size of the current font. 10 | 11 | ### Parameters ### 12 | 13 | size: 14 | > The size (in points). 15 | 16 | 17 | ### See also ### 18 | 19 | [set_font](set_font.md). 20 | -------------------------------------------------------------------------------- /tests/HelloWorld.txt: -------------------------------------------------------------------------------- 1 | English: Hello World 2 | Greek: Γειά σου κόσμος 3 | Polish: Witaj świecie 4 | Portuguese: Olá mundo 5 | Russian: Здравствуй, Мир 6 | Vietnamese: Xin chào thế giới 7 | Arabic: مرحبا العالم 8 | Hebrew: שלום עולם 9 | Hindi: नमस्ते दुनिया 10 | Chinese: 你好世界 11 | Japanese: こんにちは世界 12 | Korean: 안녕하세요 13 | Thai: สวัสดีชาวโลก 14 | -------------------------------------------------------------------------------- /attic/utils/Fix3.py: -------------------------------------------------------------------------------- 1 | # Compress streams 2 | # Usage: Fix3 in.pdf [out.pdf] 3 | import sys 4 | from PDFRUUtils import * 5 | 6 | inPDF=outPDF=sys.argv[1] 7 | if len(sys.argv) > 2: 8 | outPDF=sys.argv[2] 9 | 10 | buf=CompressStreams(file(inPDF,'rb').read()) 11 | newbuf=ReplaceXRefsTable(buf, BuildXRefsTable(FindXRefs(buf))) 12 | file(outPDF,'wb').write(newbuf) 13 | -------------------------------------------------------------------------------- /attic/utils/Fix2.py: -------------------------------------------------------------------------------- 1 | # Decompress streams, to edit file 2 | # Usage: Fix2 in.pdf [out.pdf] 3 | import sys 4 | from PDFRUUtils import * 5 | 6 | inPDF=outPDF=sys.argv[1] 7 | if len(sys.argv) > 2: 8 | outPDF=sys.argv[2] 9 | 10 | buf=DecompressStreams(file(inPDF,'rb').read()) 11 | newbuf=ReplaceXRefsTable(buf, BuildXRefsTable(FindXRefs(buf))) 12 | file(outPDF,'wb').write(newbuf) 13 | -------------------------------------------------------------------------------- /docs/reference/set_title.md: -------------------------------------------------------------------------------- 1 | ## set_title ## 2 | 3 | ```python 4 | fpdf.set_title(title: str) 5 | ``` 6 | ### Description ### 7 | 8 | Defines the title of the document. 9 | 10 | ### Parameters ### 11 | 12 | title: 13 | > The title. 14 | 15 | ### See also ### 16 | 17 | [set_author](set_author.md), [set_creator](set_creator.md), [set_keywords](set_keywords.md), [set_subject](set_subject.md). 18 | -------------------------------------------------------------------------------- /docs/reference/open.md: -------------------------------------------------------------------------------- 1 | ## open ## 2 | 3 | ```python 4 | fpdf.open() 5 | ``` 6 | 7 | ### Description ### 8 | 9 | This method begins the generation of the PDF document. It is not necessary to call it explicitly because [add_page](add_page.md) does it automatically. 10 | 11 | Note: no page is created by this method. 12 | 13 | 14 | ### See also ### 15 | 16 | [add_page](add_page.md), [close](close.md). 17 | -------------------------------------------------------------------------------- /docs/reference/set_subject.md: -------------------------------------------------------------------------------- 1 | ## set_subject ## 2 | 3 | ```python 4 | fpdf.set_subject(subject: str) 5 | ``` 6 | ### Description ### 7 | 8 | Defines the subject of the document. 9 | 10 | ### Parameters ### 11 | 12 | subject: 13 | > The subject. 14 | 15 | ### See also ### 16 | 17 | [set_author](set_author.md), [set_creator](set_creator.md), [set_keywords](set_keywords.md), [set_title](set_title.md). 18 | -------------------------------------------------------------------------------- /docs/reference/set_author.md: -------------------------------------------------------------------------------- 1 | ## set_author ## 2 | 3 | ```python 4 | fpdf.set_author(author: str) 5 | ``` 6 | ### Description ### 7 | 8 | Defines the author of the document. 9 | 10 | ### Parameters ### 11 | 12 | author: 13 | > The name of the author. 14 | 15 | ### See also ### 16 | 17 | [set_creator](set_creator.md), [set_keywords](set_keywords.md), [set_subject](set_subject.md), [set_title](set_title.md). 18 | -------------------------------------------------------------------------------- /docs/reference/set_x.md: -------------------------------------------------------------------------------- 1 | ## set_x ## 2 | 3 | ```python 4 | fpdf.set_x(x: float) 5 | ``` 6 | ### Description ### 7 | 8 | Defines the abscissa of the current position. If the passed value is negative, it is relative to the right of the page. 9 | 10 | ### Parameters ### 11 | 12 | x: 13 | > The value of the abscissa. 14 | 15 | ### See also ### 16 | 17 | [get_x](get_x.md), [get_y](get_y.md), [set_y](set_y.md), [set_xy](set_xy.md). 18 | -------------------------------------------------------------------------------- /docs/reference/close.md: -------------------------------------------------------------------------------- 1 | ## close ## 2 | 3 | ```python 4 | fpdf.close() 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Terminates the PDF document. It is not necessary to call this method explicitly because [output](output.md) does it automatically. 10 | If the document contains no page, [add_page](add_page.md) is called to prevent from getting an invalid document. 11 | 12 | 13 | ### See also ### 14 | 15 | [open](open.md), [output](output.md). 16 | -------------------------------------------------------------------------------- /docs/reference/get_string_width.md: -------------------------------------------------------------------------------- 1 | ## get_string_width ## 2 | 3 | ```python 4 | self.get_string_width(s: str) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Returns the length of a string in user unit. A font must be selected. 10 | 11 | The value is calculated with stretching and spacing. 12 | 13 | ### Parameters ### 14 | 15 | s: 16 | > The string whose length is to be computed. 17 | 18 | ### See also ### 19 | 20 | [set_stretching](set_stretching.md). 21 | -------------------------------------------------------------------------------- /docs/reference/ln.md: -------------------------------------------------------------------------------- 1 | ## ln ## 2 | 3 | ```python 4 | fpdf.ln(h = '') 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Performs a line break. The current abscissa goes back to the left margin and the ordinate increases by the amount passed in the parameter. 10 | 11 | ### Parameters ### 12 | 13 | h: 14 | > The height of the break. 15 | 16 | > By default, the value equals the height of the last printed cell. 17 | 18 | ### See also ### 19 | 20 | [cell](cell.md). 21 | -------------------------------------------------------------------------------- /docs/reference/set_y.md: -------------------------------------------------------------------------------- 1 | ## set_y ## 2 | 3 | ```python 4 | fpdf.set_y(y: float) 5 | ``` 6 | ### Description ### 7 | 8 | Moves the current abscissa back to the left margin and sets the ordinate. If the passed value is negative, it is relative to the bottom of the page. 9 | 10 | ### Parameters ### 11 | 12 | y: 13 | > The value of the ordinate. 14 | 15 | ### See also ### 16 | 17 | [get_x](get_x.md), [get_y](get_y.md), [set_x](set_x.md), [set_xy](set_xy.md). 18 | -------------------------------------------------------------------------------- /tests/issue65.py: -------------------------------------------------------------------------------- 1 | "Test issue 65: twitter.png error (urlopen, transparency, internal regex error)" 2 | 3 | from fpdf import FPDF, FPDF_VERSION 4 | 5 | pdf=FPDF() 6 | pdf.compress = False 7 | pdf.add_page() 8 | png = "https://g.twimg.com/Twitter_logo_blue.png" 9 | pdf.image(png, x = 15, y = 15) 10 | 11 | fn = 'issue65.pdf' 12 | pdf.output(fn,'F') 13 | 14 | import os 15 | try: 16 | os.startfile(fn) 17 | except: 18 | os.system("xdg-open \"%s\"" % fn) 19 | -------------------------------------------------------------------------------- /docs/reference/set_keywords.md: -------------------------------------------------------------------------------- 1 | ## set_keywords ## 2 | 3 | ```python 4 | fpdf.set_keywords(keywords: str) 5 | ``` 6 | ### Description ### 7 | 8 | Associates keywords with the document, generally in the form 'keyword1 keyword2 ...'. 9 | 10 | ### Parameters ### 11 | 12 | keywords: 13 | > The list of keywords. 14 | 15 | ### See also ### 16 | 17 | [set_author](set_author.md), [set_creator](set_creator.md), [set_subject](set_subject.md), [set_title](set_title.md). 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | 21 | # Installer logs 22 | pip-log.txt 23 | 24 | # Unit test / coverage reports 25 | .coverage 26 | .tox 27 | nosetests.xml 28 | 29 | # Translations 30 | *.mo 31 | 32 | # Mr Developer 33 | .mr.developer.cfg 34 | .project 35 | .pydevproject 36 | -------------------------------------------------------------------------------- /attic/utils/Fix1.py: -------------------------------------------------------------------------------- 1 | # Updates the unique, final XREF table 2 | # Usage: Fix1 in.pdf [out.pdf] 3 | import sys 4 | from PDFRUUtils import * 5 | 6 | def Fix1(inPDF, outPDF): 7 | buf=UpdateStreamLengths(file(inPDF,'rb').read()) 8 | newbuf=ReplaceXRefsTable(buf, BuildXRefsTable(FindXRefs(buf))) 9 | file(outPDF,'wb').write(newbuf) 10 | 11 | if __name__=='__main__': 12 | inPDF=outPDF=sys.argv[1] 13 | if len(sys.argv) > 2: 14 | outPDF=sys.argv[2] 15 | Fix1(inPDF, outPDF) 16 | -------------------------------------------------------------------------------- /docs/reference/error.md: -------------------------------------------------------------------------------- 1 | ## error ## 2 | 3 | ```python 4 | fpdf.error(msg: str) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | This method is automatically called in case of fatal error; it simply outputs the message and halts the execution. An inherited class may override it to customize the error handling but should always halt the script, or the resulting document would probably be invalid. 10 | 11 | ### Parameters ### 12 | 13 | msg: 14 | > The error message. 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/reference/set_creator.md: -------------------------------------------------------------------------------- 1 | ## set_creator ## 2 | 3 | ```python 4 | fpdf.set_creator(creator: str) 5 | ``` 6 | ### Description ### 7 | 8 | Defines the creator of the document. This is typically the name of the application that generates the PDF. 9 | 10 | ### Parameters ### 11 | 12 | creator: 13 | > The name of the creator. 14 | 15 | ### See also ### 16 | 17 | [set_author](set_author.md), [set_keywords](set_keywords.md), [set_subject](set_subject.md), [set_title](set_title.md). 18 | -------------------------------------------------------------------------------- /fpdf/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | "FPDF for python" 5 | 6 | __license__ = "LGPL 3.0" 7 | __version__ = "1.7.2" 8 | 9 | from .fpdf import FPDF, FPDF_FONT_DIR, FPDF_VERSION, SYSTEM_TTFONTS, set_global, FPDF_CACHE_MODE, FPDF_CACHE_DIR 10 | try: 11 | from .html import HTMLMixin 12 | except ImportError: 13 | import warnings 14 | warnings.warn("web2py gluon package not installed, required for html2pdf") 15 | 16 | from .template import Template 17 | -------------------------------------------------------------------------------- /docs/reference/set_top_margin.md: -------------------------------------------------------------------------------- 1 | ## set_top_margin ## 2 | 3 | ```python 4 | fpdf.set_top_margin(margin: float) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Defines the top margin. The method can be called before creating the first page. 10 | 11 | ### Parameters ### 12 | 13 | margin: 14 | > The margin. 15 | 16 | ### See also ### 17 | 18 | [set_left_margin](set_left_margin.md), [set_right_margin](set_right_margin.md), [set_auto_page_break](set_auto_page_break.md), [set_margins](set_margins.md). 19 | -------------------------------------------------------------------------------- /docs/reference/set_compression.md: -------------------------------------------------------------------------------- 1 | ## set_compression ## 2 | 3 | ```python 4 | fpdf.set_compression(compress: bool) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Activates or deactivates page compression. When activated, the internal representation of each page is compressed, which leads to a compression ratio of about 2 for the resulting document. 10 | 11 | Compression is on by default. 12 | 13 | ### Parameters ### 14 | 15 | compress: 16 | > Boolean indicating if compression must be enabled. 17 | 18 | -------------------------------------------------------------------------------- /docs/reference/set_line_width.md: -------------------------------------------------------------------------------- 1 | ## set_line_width ## 2 | 3 | ```python 4 | fpdf.set_line_width(width: float) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Defines the line width. By default, the value equals 0.2 mm. The method can be called before the first page is created and the value is retained from page to page. 10 | 11 | ### Parameters ### 12 | 13 | width: 14 | > The width. 15 | 16 | ### See also ### 17 | 18 | [line](line.md), [rect](rect.md), [cell](cell.md), [multi_cell](multi_cell.md). 19 | -------------------------------------------------------------------------------- /docs/reference/set_right_margin.md: -------------------------------------------------------------------------------- 1 | ## set_right_margin ## 2 | 3 | ```python 4 | fpdf.set_right_margin(margin: float) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Defines the right margin. The method can be called before creating the first page. 10 | 11 | ### Parameters ### 12 | 13 | margin: 14 | > The margin. 15 | 16 | ### See also ### 17 | 18 | [set_top_margin](set_top_margin.md), [set_left_margin](set_left_margin.md), [set_auto_page_break](set_auto_page_break.md), [set_margins](set_margins.md). 19 | -------------------------------------------------------------------------------- /.hgtags: -------------------------------------------------------------------------------- 1 | 86e2be4e99090fbd25b372d2f29a5b20d6b22001 unicode 2 | 5ce4e5d8c7d812a005c684925578e8b7a098987a gif 3 | 6d269f7474c65d7d2616472ea800fa356d645e95 png_alpha 4 | 0dc26e5ee0b0c147f9b885722cfab2ccc6198322 1.7 5 | 90c1a762ab26e208f54eb1483f00a8c407cf89f3 1.7.1 6 | f99621069064f6126839a4831204ccd7be077b34 1.7.2 7 | f99621069064f6126839a4831204ccd7be077b34 1.7.2 8 | 88fafdc91cc38b7dc3afcbcf36496beedf5499b8 1.7.2 9 | 88fafdc91cc38b7dc3afcbcf36496beedf5499b8 1.7.2 10 | 49b35f298ec84db3995b49f63de501aca7d6d7ac 1.7.2 11 | -------------------------------------------------------------------------------- /tutorial/bookmark.py: -------------------------------------------------------------------------------- 1 | from FPDF.Bookmark import * 2 | 3 | pdf = Bookmark() 4 | pdf.Open() 5 | pdf.SetFont('Arial', '', 15) 6 | # Page 1 7 | pdf.AddPage() 8 | pdf.Bookmark('Page 1') 9 | pdf.Bookmark('Paragraph 1', 1, -1) 10 | pdf.Cell(0, 6, 'Paragraph 1') 11 | pdf.Ln(50) 12 | pdf.Bookmark('Paragraph 2', 1, -1) 13 | pdf.Cell(0, 6, 'Paragraph 2') 14 | # Page 2 15 | pdf.AddPage() 16 | pdf.Bookmark('Page 2') 17 | pdf.Bookmark('Paragraph 3', 1, -1) 18 | pdf.Cell(0, 6, 'Paragraph 3') 19 | pdf.Output('bookmark.pdf', 'F') 20 | 21 | -------------------------------------------------------------------------------- /docs/reference/set_xy.md: -------------------------------------------------------------------------------- 1 | ## set_xy ## 2 | 3 | ```python 4 | fpdf.set_xy(x: float, y: float) 5 | ``` 6 | ### Description ### 7 | 8 | Defines the abscissa and ordinate of the current position. If the passed values are negative, they are relative respectively to the right and bottom of the page. 9 | 10 | ### Parameters ### 11 | 12 | x: 13 | > The value of the abscissa. 14 | 15 | y: 16 | > The value of the ordinate. 17 | 18 | ### See also ### 19 | 20 | [get_x](get_x.md), [get_y](get_y.md), [set_x](set_x.md), [set_y](set_y.md). 21 | -------------------------------------------------------------------------------- /docs/reference/add_link.md: -------------------------------------------------------------------------------- 1 | ## add_link ## 2 | 3 | ```python 4 | fpdf.add_link() 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Creates a new internal link and returns its identifier. An internal link is a clickable area which directs to another place within the document. 10 | The identifier can then be passed to [cell](cell.md), [write](write.md), [image](image.md) or [link](link.md). The destination is defined with [set_link](set_link.md). 11 | 12 | ### See also ### 13 | 14 | [cell](cell.md), [write](write.md), [image](image.md), [link](link.md), [set_link](set_link.md). 15 | -------------------------------------------------------------------------------- /docs/reference/accept_page_break.md: -------------------------------------------------------------------------------- 1 | ## accept_page_break ## 2 | 3 | ```python 4 | fpdf.accept_page_break() 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Whenever a page break condition is met, this method is called, and the break is issued or not depending on the returned value. The default implementation returns a value according to the mode selected by [set_auto_page_break](set_auto_page_break.md). 10 | This method is called automatically and should not be called directly by the application. 11 | 12 | ### See also ### 13 | 14 | [set_auto_page_break](set_auto_page_break.md). 15 | -------------------------------------------------------------------------------- /docs/reference/set_left_margin.md: -------------------------------------------------------------------------------- 1 | ## set_left_margin ## 2 | 3 | ```python 4 | fpdf.set_left_margin(margin: float) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Defines the left margin. The method can be called before creating the first page. 10 | If the current abscissa goes out of the page, it is brought back to the margin. 11 | 12 | ### Parameters ### 13 | 14 | margin: 15 | > The margin. 16 | 17 | ### See also ### 18 | 19 | [set_top_margin](set_top_margin.md), [set_right_margin](set_right_margin.md), [set_auto_page_break](set_auto_page_break.md), [set_margins](set_margins.md). 20 | -------------------------------------------------------------------------------- /docs/reference/set_link.md: -------------------------------------------------------------------------------- 1 | ## set_link ## 2 | 3 | ```python 4 | fpdf.set_link(link, y = 0.0, page = -1) 5 | ``` 6 | ### Description ### 7 | 8 | Defines the page and position a link points to. 9 | 10 | ### Parameters ### 11 | 12 | link: 13 | > The link identifier returned by [add_link](add_link.md). 14 | 15 | y: 16 | > Ordinate of target position; -1 indicates the current position. The default value is 0 (top of page). 17 | 18 | page: 19 | > Number of target page; -1 indicates the current page, which is the default value. 20 | 21 | 22 | ### See also ### 23 | 24 | [add_link](add_link.md). 25 | -------------------------------------------------------------------------------- /docs/reference/line.md: -------------------------------------------------------------------------------- 1 | ## line ## 2 | 3 | ```python 4 | fpdf.line(x1, y1, x2, y2) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Draw a line between two points. 10 | 11 | ### Parameters ### 12 | 13 | x1: 14 | > Abscissa of first point 15 | 16 | y1: 17 | > Ordinate of first point 18 | 19 | x2: 20 | > Abscissa of second point 21 | 22 | y2: 23 | > Ordinate of second point 24 | 25 | ### Example ### 26 | 27 | ```python 28 | # Adds a line beginning at point (10,30) and ending at point (110,30) 29 | pdf.line(10, 30, 110, 30) 30 | ``` 31 | 32 | ### See also ### 33 | 34 | [dashed_line](dashed_line.md). 35 | -------------------------------------------------------------------------------- /docs/reference/set_doc_option.md: -------------------------------------------------------------------------------- 1 | ## set_doc_option ## 2 | 3 | ```python 4 | fpdf.set_doc_option(opt: str, value) 5 | ``` 6 | [TOC] 7 | 8 | ### Description ### 9 | 10 | Defines the document option. 11 | 12 | ### Parameters ### 13 | 14 | opt: 15 | > Option to set. 16 | 17 | value: 18 | > Value. 19 | 20 | ### Options ### 21 | 22 | #### core_fonts_encoding #### 23 | 24 | Specify encoding used for decoding unicode text for standard (non-unicode) 25 | fonts. Supported values are `latin-1` and `windows-1252`. Set this option 26 | before using any text writing. 27 | 28 | ### See also ### 29 | 30 | [set_font](set_font.md), [write](write.md). 31 | -------------------------------------------------------------------------------- /docs/reference/set_margins.md: -------------------------------------------------------------------------------- 1 | ## set_margins ## 2 | 3 | ```python 4 | fpdf.set_margins(left: float, top: float, right: float = -1) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Defines the left, top and right margins. By default, they equal 1 cm. Call this method to change them. 10 | 11 | ### Parameters ### 12 | 13 | left: 14 | > Left margin. 15 | 16 | top: 17 | > Top margin. 18 | 19 | right: 20 | > Right margin. Default value is the left one. 21 | 22 | ### See also ### 23 | 24 | [set_top_margin](set_top_margin.md), [set_left_margin](set_left_margin.md), [set_right_margin](set_right_margin.md), [set_auto_page_break](set_auto_page_break.md). 25 | -------------------------------------------------------------------------------- /tests/cover/checkenv.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Test environment 4 | 5 | import common 6 | 7 | def main(): 8 | common.log("CHECK") 9 | 10 | try: 11 | from fpdf import FPDF_VERSION 12 | except ImportError: 13 | FPDF_VERSION = None 14 | common.log("VER =", FPDF_VERSION) 15 | 16 | try: 17 | try: 18 | import Image 19 | except: 20 | from PIL import Image 21 | except ImportError: 22 | Image = None 23 | if Image: 24 | common.log("PIL = yes") 25 | else: 26 | common.log("PIL = no") 27 | 28 | 29 | 30 | if __name__ == "__main__": 31 | main() 32 | -------------------------------------------------------------------------------- /docs/reference/set_auto_page_break.md: -------------------------------------------------------------------------------- 1 | ## set_auto_page_break ## 2 | 3 | ```python 4 | fpdf.set_auto_page_break(auto: bool, margin = 0.0) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Enables or disables the automatic page breaking mode. When enabling, the second parameter is the distance from the bottom of the page that defines the triggering limit. By default, the mode is on and the margin is 2 cm. 10 | 11 | ### Parameters ### 12 | 13 | auto: 14 | > Boolean indicating if mode should be on or off. 15 | 16 | margin: 17 | > Distance from the bottom of the page. 18 | 19 | ### See also ### 20 | 21 | [cell](cell.md), [multi_cell](multi_cell.md), [accept_page_break](accept_page_break.md). 22 | -------------------------------------------------------------------------------- /docs/reference/rect.md: -------------------------------------------------------------------------------- 1 | ## rect ## 2 | 3 | ```python 4 | fpdf.rect(x: float, y: float, w: float, h: float, style = '') 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Outputs a rectangle. It can be drawn (border only), filled (with no border) or 10 | both. 11 | 12 | ### Parameters ### 13 | 14 | x: 15 | > Abscissa of upper-left corner. 16 | 17 | y: 18 | > Ordinate of upper-left corner. 19 | 20 | w: 21 | > Width. 22 | 23 | h: 24 | > Height. 25 | 26 | style: 27 | > Style of rendering. Possible values are: 28 | >> * `D` or empty string: draw. This is the default value. 29 | >> * `F`: fill 30 | >> * `DF` or `FD`: draw and fill 31 | 32 | ### See also ### 33 | 34 | [cell](cell.md), [ellipse](ellipse.md). 35 | -------------------------------------------------------------------------------- /examples/simple-csv-invoice.txt: -------------------------------------------------------------------------------- 1 | 100, 10, 'INVOICE' 2 | 10, 46, 'VAT:' 3 | 53, 46, customer['vat'] and 'X' or '' 4 | 63, 46, not customer['vat'] and 'X' or '' 5 | 10, 20, customer['name'] 6 | 100, 20, customer['tax_id'] 7 | 10, 60, items[0]['qty'] 8 | 40, 60, items[0]['description'] 9 | 150, 60, items[0]['price'] 10 | 190, 60, items[0]['qty']*items[0]['price'] 11 | 10, 65, items[1]['qty'] 12 | 40, 65, items[1]['description'] 13 | 150, 65, items[1]['price'] 14 | 190, 65, items[1]['qty']*items[1]['price'] 15 | 10, 70, items[2]['qty'] 16 | 40, 70, items[2]['description'] 17 | 150, 70, items[2]['price'] 18 | 190, 70, items[2]['qty']*items[2]['price'] 19 | 100,100, 'Total:' 20 | 120,100, sum([item['qty']*item['price'] for item in items]) 21 | -------------------------------------------------------------------------------- /docs/reference/set_stretching.md: -------------------------------------------------------------------------------- 1 | ## set_stretching ## 2 | 3 | ```python 4 | fpdf.set_stretching(stretching: float) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Sets horizontal font stretching. By default, if this method is not called, no stretching is set (equivalent to a value of 100). 10 | 11 | ### Version ### 12 | 13 | Since 1.7.3 14 | 15 | ### Parameters ### 16 | 17 | stretching: 18 | > Define horizontal stretching (scaling) in percents. 19 | 20 | ### Example ### 21 | 22 | ```python 23 | # Arial regular 14 24 | pdf.set_font('Arial') 25 | # Set stretching to 50%, narrow text 26 | pdf.set_stretching(50.0) 27 | ``` 28 | 29 | ### See also ### 30 | 31 | [set_font](set_font.md), [set_font_size](set_font_size.md), [get_string_width](get_string_width.md). 32 | -------------------------------------------------------------------------------- /tests/cover/test_issue35.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Tests new dashed line feature (issue 35)" 4 | 5 | #PyFPDF-cover-test:format=PDF 6 | #PyFPDF-cover-test:fn=issue_35.pdf 7 | #PyFPDF-cover-test:hash=e8f92b3210aea65caa72f70d0f898c04 8 | 9 | import common 10 | from fpdf import FPDF 11 | 12 | @common.add_unittest 13 | def dotest(outputname, nostamp): 14 | pdf = FPDF() 15 | if nostamp: 16 | pdf._putinfo = lambda: common.test_putinfo(pdf) 17 | 18 | pdf.add_page() 19 | 20 | pdf.dashed_line(10, 10, 110, 10) 21 | pdf.dashed_line(10, 20, 110, 20, 5, 5) 22 | pdf.dashed_line(10, 30, 110, 30, 1, 10) 23 | 24 | pdf.output(outputname, 'F') 25 | 26 | if __name__ == "__main__": 27 | common.testmain(__file__, dotest) 28 | 29 | -------------------------------------------------------------------------------- /docs/reference/load_resource.md: -------------------------------------------------------------------------------- 1 | ## load_resource ## 2 | 3 | ```python 4 | fpdf.load_resource(reason: string, filename: string) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | This method is used to load external resources, such as images. It is 10 | automatically called when resource added to document by [image](image.md). The 11 | implementation in library sre try to load resource from local file system or 12 | from network if filename starts with `http://` or `https://`. This method can 13 | be overrided within subclass if you want a specific processing. 14 | 15 | Returns file-like object. 16 | 17 | ### Parameters ### 18 | 19 | reason: 20 | > Resource type: `image`. 21 | 22 | filename: 23 | > filename or URL. 24 | 25 | ### See also ### 26 | 27 | [image](image.md). 28 | 29 | -------------------------------------------------------------------------------- /docs/reference/text.md: -------------------------------------------------------------------------------- 1 | ## text ## 2 | 3 | ```python 4 | fpdf.text(x: float, y: float, txt: str) 5 | ``` 6 | ### Description ### 7 | 8 | Prints a character string. The origin is on the left of the first character, on 9 | the baseline. This method allows placing a string precisely on the page, but it 10 | is usually easier to use [cell](cell.md), [multi_cell](multi_cell.md) or 11 | [write](write.md), which are the standard methods to print text. 12 | 13 | ### Parameters ### 14 | 15 | x: 16 | > Abscissa of the origin. 17 | 18 | y: 19 | > Ordinate of the origin. 20 | 21 | txt: 22 | > String to print. 23 | 24 | ### See also ### 25 | 26 | [set_doc_option](set_doc_option.md), [set_font](set_font.md), 27 | [set_text_color](set_text_color.md), [cell](cell.md), 28 | [multi_cell](multi_cell.md), [write](write.md). 29 | -------------------------------------------------------------------------------- /docs/reference/set_text_color.md: -------------------------------------------------------------------------------- 1 | ## set_text_color ## 2 | 3 | ```python 4 | fpdf.set_text_color(r: int, g: int = -1, b: int = -1) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Defines the color used for text. It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page. 10 | 11 | ### Parameters ### 12 | 13 | r: 14 | > If `g` and `b` are given, this indicates the red component; if not, this indicates the gray level. The value is between 0 and 255. 15 | 16 | g: 17 | > Green component (between 0 and 255). 18 | 19 | b: 20 | > Blue component (between 0 and 255). 21 | 22 | ### See also ### 23 | 24 | [set_draw_color](set_draw_color.md), [set_fill_color](set_fill_color.md), [text](text.md), [cell](cell.md), [multi_cell](multi_cell.md). 25 | -------------------------------------------------------------------------------- /docs/reference/alias_nb_pages.md: -------------------------------------------------------------------------------- 1 | ## alias_nb_pages ## 2 | 3 | ```python 4 | fpdf.alias_nb_pages() 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Defines an alias for the total number of pages. It will be substituted as the document is closed. 10 | 11 | ### Parameters ### 12 | 13 | alias: 14 | > The alias. Default value: {nb}. 15 | 16 | ### Example ### 17 | ```python 18 | class PDF(FPDF): 19 | def footer(self): 20 | # Go to 1.5 cm from bottom 21 | self.set_y(-15) 22 | # Select Arial italic 8 23 | self.set_font('Arial', 'I', 8) 24 | # Print current and total page numbers 25 | self.cell(0, 10, 'Page %s' % self.page_no() + '/{nb}', 0, 0, 'C') 26 | 27 | pdf = PDF() 28 | pdf.alias_nb_pages() 29 | 30 | ``` 31 | 32 | ### See also ### 33 | 34 | [page_no](page_no.md), [footer](footer.md). 35 | -------------------------------------------------------------------------------- /tests/respacks.txt: -------------------------------------------------------------------------------- 1 | # Where resources can be downloaded as for 2015-09-30 2 | 3 | pack=fonts 4 | name=Free Unicode TrueType font pack for FPDF 5 | #url=http://pyfpdf.googlecode.com/files/fpdf_unicode_font_pack.zip 6 | url=https://github.com/reingart/pyfpdf/releases/download/binary/fpdf_unicode_font_pack.zip 7 | valid=^font/[0-9a-zA-Z\-_]*\.(ttf|txt)$ 8 | 9 | pack=adobe-afm 10 | name=Font Metrics for PDF Core 14 Fonts 11 | url=http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/Core14_AFMs.zip 12 | filename=adobe_core14_afms.zip 13 | dest=adobe-afm 14 | valid=^[a-zA-Z\-]*\.(afm|html)$ 15 | 16 | pack=adobe-agl 17 | name=Adobe Glyph List 18 | url=https://github.com/adobe-type-tools/agl-aglfn/archive/master.zip 19 | filename=adobe_glyphlist.zip 20 | dest=adobe-agl 21 | valid=^agl-aglfn-master/[a-zA-Z-].*(.txt|.md)?$ 22 | strip=1 23 | -------------------------------------------------------------------------------- /docs/reference/link.md: -------------------------------------------------------------------------------- 1 | ## link ## 2 | 3 | ```python 4 | fpdf.link(x: float, y: float, w: float, h: float, link) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Puts a link on a rectangular area of the page. Text or image links are generally put via [cell](cell.md), [write](write.md) or [image](image.md), but this method can be useful for instance to define a clickable area inside an image. 10 | 11 | ### Parameters ### 12 | 13 | x: 14 | > Abscissa of the upper-left corner of the rectangle. 15 | 16 | y: 17 | > Ordinate of the upper-left corner of the rectangle. 18 | 19 | w: 20 | > Width of the rectangle. 21 | 22 | h: 23 | > Height of the rectangle. 24 | 25 | link: 26 | > URL or identifier returned by [add_link](add_link.md). 27 | 28 | ### See also ### 29 | 30 | [add_link](add_link.md), [cell](cell.md), [write](write.md), [image](image.md). 31 | -------------------------------------------------------------------------------- /docs/reference/header.md: -------------------------------------------------------------------------------- 1 | ## header ## 2 | 3 | ```python 4 | fdpf.header() 5 | ``` 6 | 7 | ### Description ### 8 | 9 | This method is used to render the page header. It is automatically called by [add_page](add_page.md) and should not be called directly by the application. The implementation in FPDF is empty, so you have to subclass it and override the method if you want a specific processing. 10 | 11 | ### Example ### 12 | 13 | ```python 14 | class PDF(FPDF): 15 | def header(self): 16 | # Select Arial bold 15 17 | self.set_font('Arial', 'B', 15) 18 | # Move to the right 19 | self.cell(80) 20 | # Framed title 21 | self.cell(30, 10, 'Title', 1, 0, 'C') 22 | # Line break 23 | self.ln(20) 24 | ``` 25 | 26 | ### See also ### 27 | 28 | [add_page](add_page.md), [footer](footer.md). 29 | -------------------------------------------------------------------------------- /docs/reference/footer.md: -------------------------------------------------------------------------------- 1 | ## footer ## 2 | 3 | ```python 4 | fpdf.footer() 5 | ``` 6 | 7 | ### Description ### 8 | 9 | This method is used to render the page footer. It is automatically called by [add_page](add_page.md) and [close](close.md) and should not be called directly by the application. The implementation in FPDF is empty, so you have to subclass it and override the method if you want a specific processing. 10 | 11 | ### Example ### 12 | ```python 13 | class PDF(FPDF): 14 | def footer(self): 15 | # Go to 1.5 cm from bottom 16 | self.set_y(-15) 17 | # Select Arial italic 8 18 | self.set_font('Arial', 'I', 8) 19 | # Print centered page number 20 | self.cell(0, 10, 'Page %s' % self.page_no(), 0, 0, 'C') 21 | ``` 22 | 23 | ### See also ### 24 | 25 | [add_page](add_page.md), [header](header.md). 26 | -------------------------------------------------------------------------------- /tests/cover/test_issue14.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Test images flow mode (cell-like, trigger page breaks)" 4 | 5 | #PyFPDF-cover-test:format=PDF 6 | #PyFPDF-cover-test:fn=issue_14.pdf 7 | #PyFPDF-cover-test:hash=7e4a5b0a77c4eaefa475bb7db655fcd9 8 | #PyFPDF-cover-test:res=../tutorial/logo_pb.png 9 | 10 | import common 11 | from fpdf import FPDF 12 | 13 | import os 14 | 15 | @common.add_unittest 16 | def dotest(outputname, nostamp): 17 | pdf = FPDF() 18 | if nostamp: 19 | pdf._putinfo = lambda: common.test_putinfo(pdf) 20 | 21 | pdf.add_page() 22 | 23 | for i in range(1,41): 24 | # for flow mode, do not pass x or y: 25 | pdf.image(os.path.join(common.basepath, '../tutorial/logo_pb.png')) 26 | 27 | pdf.output(outputname, 'F') 28 | 29 | if __name__ == "__main__": 30 | common.testmain(__file__, dotest) 31 | 32 | -------------------------------------------------------------------------------- /docs/reference/set_fill_color.md: -------------------------------------------------------------------------------- 1 | ## set_fill_color ## 2 | 3 | ```python 4 | fpdf.set_fill_color(r: int, g: int = -1, b: int = -1) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Defines the color used for all filling operations (filled rectangles and cell backgrounds). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page. 10 | 11 | ### Parameters ### 12 | 13 | r: 14 | > If `g` and `b` are given, this indicates the red component; if not, this indicates the gray level. The value is between 0 and 255. 15 | 16 | g: 17 | > Green component (between 0 and 255). 18 | 19 | b: 20 | > Blue component (between 0 and 255). 21 | 22 | ### See also ### 23 | 24 | [set_draw_color](set_draw_color.md), [set_text_color](set_text_color.md), [rect](rect.md), [cell](cell.md), [multi_cell](multi_cell). 25 | -------------------------------------------------------------------------------- /docs/reference/ellipse.md: -------------------------------------------------------------------------------- 1 | ## ellipse ## 2 | 3 | ```python 4 | fpdf.ellipse(x: float, y: float, w: float, h: float, style = '') 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Outputs an ellipse. It can be drawn (border only), filled (with no border) or 10 | both. Unlike the PHP version, this function uses the top-left position and 11 | width and height of the ellipse, like [rect](rect.md), not the center point and 12 | radius. 13 | 14 | ### Parameters ### 15 | 16 | x: 17 | > Abscissa of upper-left bounging box. 18 | 19 | y: 20 | > Ordinate of upper-left bounging box. 21 | 22 | w: 23 | > Width. 24 | 25 | h: 26 | > Height. 27 | 28 | style: 29 | > Style of rendering. Possible values are: 30 | >> * `D` or empty string: draw. This is the default value. 31 | >> * `F`: fill 32 | >> * `DF` or `FD`: draw and fill 33 | 34 | ### See also ### 35 | 36 | [cell](cell.md), [rect](rect.md). 37 | -------------------------------------------------------------------------------- /docs/reference/set_draw_color.md: -------------------------------------------------------------------------------- 1 | ## set_draw_color ## 2 | 3 | ```python 4 | fpdf.set_draw_color(r: int, g: int = -1, b: int = -1) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Defines the color used for all drawing operations (lines, rectangles and cell borders). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page. 10 | 11 | ### Parameters ### 12 | 13 | r: 14 | > If `g` and `b` are given, this indicates the red component; if not, this indicates the gray level. The value is between 0 and 255. 15 | 16 | g: 17 | > Green component (between 0 and 255). 18 | 19 | b: 20 | > Blue component (between 0 and 255). 21 | 22 | ### See also ### 23 | 24 | [set_fill_color](set_fill_color.md), [set_text_color](set_text_color.md), [line](line.md), [rect](rect.md), [cell](cell.md), [multi_cell](multi_cell.md). 25 | -------------------------------------------------------------------------------- /examples/simple-csv-invoice.py: -------------------------------------------------------------------------------- 1 | # -*- coding: iso-8859-1 -*- 2 | from __future__ import with_statement 3 | 4 | import sys, os 5 | sys.path.append("..") 6 | import fpdf 7 | 8 | customer = {'name':'John Doe','tax_id':'00-0000000-0','vat':True} 9 | items = [ 10 | {'qty':12,'description':'Eggs','price':1.00}, 11 | {'qty':20,'description':'Spam','price':3.00}, 12 | {'qty':1,'description':'Varios','price':0.50}, 13 | ] 14 | 15 | pdf = fpdf.FPDF() 16 | pdf.add_page(); 17 | pdf.set_font('Arial','B',16); 18 | with open("simple-csv-invoice.txt") as file: 19 | for line in file.readlines(): 20 | sys.stdout.write(line) 21 | args = eval(line.strip()) 22 | pdf.text(x=args[0],y=args[1],txt=str(args[2])); 23 | 24 | pdf.output(r"./invoice.pdf","F") 25 | import sys 26 | if sys.platform.startswith("linux"): 27 | os.system("xdg-open ./invoice.pdf") 28 | else: 29 | os.system("./invoice.pdf") 30 | -------------------------------------------------------------------------------- /tests/cover/test_issue41.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Test issue 41 (escape CR char)" 4 | 5 | from __future__ import with_statement 6 | 7 | #PyFPDF-cover-test:format=TXT 8 | #PyFPDF-cover-test:fn=issue_41.txt 9 | #PyFPDF-cover-test:hash=c576afec3362a7cc3b4b07a12feeefd3 10 | 11 | import common # common set of utilities 12 | import fpdf 13 | 14 | import sys 15 | 16 | @common.add_unittest 17 | def dotest(outputname, nostamp): 18 | txt = "This is test string for issue41 with special symbols \n" +\ 19 | "ln - \n\n" +\ 20 | "cr - \r\n" +\ 21 | "\\ ( ) abcdef..xyz 01234\n" +\ 22 | "| [ ] ABCDEF..XYZ 56789\n" 23 | 24 | pdf = fpdf.FPDF() 25 | with open(outputname, "wb") as f: 26 | f.write(pdf._escape(txt).encode("latin1")) 27 | 28 | def main(): 29 | return common.testmain(__file__, dotest) 30 | 31 | if __name__ == "__main__": 32 | main() 33 | 34 | -------------------------------------------------------------------------------- /docs/reference/dashed_line.md: -------------------------------------------------------------------------------- 1 | ## dashed_line ## 2 | 3 | ```python 4 | fpdf.dashed_line(x1, y1, x2, y2, dash_length = 1, space_length = 1) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Draw a dashed line between two points. Same interface as [line](line.md) except the two parameters dash\_length and space\_length. 10 | 11 | ### Parameters ### 12 | 13 | x1: 14 | > Abscissa of first point 15 | 16 | y1: 17 | > Ordinate of first point 18 | 19 | x2: 20 | > Abscissa of second point 21 | 22 | y2: 23 | > Ordinate of second point 24 | 25 | dash\_length: 26 | > Length of the dash 27 | 28 | space\_length: 29 | > Length of the space between dashes 30 | 31 | ### Example ### 32 | 33 | ```python 34 | # Adds a dashed line beginning at point (10,30), 35 | # ending at point (110,30) with a 36 | # dash length of 1 and a space length of 10. 37 | pdf.dashed_line(10, 30, 110, 30, 1, 10) 38 | ``` 39 | 40 | ### See also ### 41 | 42 | [line](line.md). 43 | -------------------------------------------------------------------------------- /tests/cover/test_py3k.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Basic example to test py3k conversion" 4 | 5 | #PyFPDF-cover-test:format=PDF 6 | #PyFPDF-cover-test:fn=py3k.pdf 7 | #PyFPDF-cover-test:hash=ecf5ec7b9a3bb6015b4c9f0546f62e84 8 | #PyFPDF-cover-test:python2=no 9 | 10 | import common # test utilities 11 | from fpdf import FPDF 12 | 13 | import sys 14 | 15 | @common.add_unittest 16 | def dotest(outputname, nostamp): 17 | pdf = FPDF() 18 | if nostamp: 19 | pdf._putinfo = lambda: common.test_putinfo(pdf) 20 | 21 | pdf.add_page() 22 | pdf.set_font('Arial', '', 14) 23 | pdf.ln(10) 24 | if nostamp: 25 | data = "TEST-TEST-TEST" 26 | else: 27 | data = sys.version 28 | 29 | #áéíóúüñ 30 | # This string converted with errors in py2.x 31 | pdf.write(5, ('hello world %s áéíóúüñ' % data)) 32 | 33 | pdf.output(outputname, 'F') 34 | 35 | if __name__ == "__main__": 36 | common.testmain(__file__, dotest) 37 | 38 | -------------------------------------------------------------------------------- /tutorial/tuto2.py: -------------------------------------------------------------------------------- 1 | from fpdf import FPDF 2 | 3 | class PDF(FPDF): 4 | def header(self): 5 | # Logo 6 | self.image('logo_pb.png', 10, 8, 33) 7 | # Arial bold 15 8 | self.set_font('Arial', 'B', 15) 9 | # Move to the right 10 | self.cell(80) 11 | # Title 12 | self.cell(30, 10, 'Title', 1, 0, 'C') 13 | # Line break 14 | self.ln(20) 15 | 16 | # Page footer 17 | def footer(self): 18 | # Position at 1.5 cm from bottom 19 | self.set_y(-15) 20 | # Arial italic 8 21 | self.set_font('Arial', 'I', 8) 22 | # Page number 23 | self.cell(0, 10, 'Page ' + str(self.page_no()) + '/{nb}', 0, 0, 'C') 24 | 25 | # Instantiation of inherited class 26 | pdf = PDF() 27 | pdf.alias_nb_pages() 28 | pdf.add_page() 29 | pdf.set_font('Times', '', 12) 30 | for i in range(1, 41): 31 | pdf.cell(0, 10, 'Printing line number ' + str(i), 0, 1) 32 | pdf.output('tuto2.pdf', 'F') 33 | 34 | -------------------------------------------------------------------------------- /tests/cover/test_page_orient.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Test page orientation" 4 | 5 | #PyFPDF-cover-test:format=PDF 6 | #PyFPDF-cover-test:fn=page_orient.pdf 7 | #PyFPDF-cover-test:hash=5adb1bc3a5c384e140c71e530f0f735a 8 | 9 | import os 10 | 11 | import common 12 | from fpdf import FPDF 13 | 14 | def page(pdf, text, orientation): 15 | pdf.add_page(orientation = orientation) 16 | pdf.write(8, text) 17 | pdf.ln(8) 18 | 19 | @common.add_unittest 20 | def dotest(outputname, nostamp): 21 | pdf = FPDF(orientation = "L", format = "A5") 22 | pdf.compress = False 23 | if nostamp: 24 | pdf._putinfo = lambda: common.test_putinfo(pdf) 25 | pdf.set_font('Arial', '', 14) 26 | for i in range(10): 27 | o = ["p", "L", "P", "l"][i % 4] 28 | page(pdf, "Page %d from 10\nOrientation: %s" % (i + 1, o), o) 29 | pdf.output(outputname, 'F') 30 | 31 | def main(): 32 | return common.testmain(__file__, dotest) 33 | 34 | if __name__ == "__main__": 35 | main() 36 | 37 | -------------------------------------------------------------------------------- /tests/cover/test_issue71.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Basic test to check issue 71: test Code39" 4 | 5 | #PyFPDF-cover-test:format=PDF 6 | #PyFPDF-cover-test:fn=issue_71.pdf 7 | #PyFPDF-cover-test:hash=1575947cac5b0a8cdceedf9b525ee6db 8 | # get res from http://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Code_3_of_9.svg/262px-Code_3_of_9.svg.png 9 | # PyFPDF-cover-test:res=.png 10 | 11 | import common 12 | from fpdf import FPDF 13 | 14 | import os 15 | 16 | @common.add_unittest 17 | def dotest(outputname, nostamp): 18 | # Portrait, millimeter units, A4 page size 19 | pdf = FPDF("P", "mm", "A4") 20 | if nostamp: 21 | pdf._putinfo = lambda: common.test_putinfo(pdf) 22 | # Set font: Times, normal, size 10 23 | pdf.add_page() 24 | if not nostamp: 25 | # do not show picture in batch 26 | url = "http://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/Code_3_of_9.svg/262px-Code_3_of_9.svg.png" 27 | pdf.image(url, 10, 10) 28 | 29 | pdf.code39("*wikipedia*", 12.75, 7, 1.49) 30 | 31 | pdf.output(outputname, 'F') 32 | 33 | if __name__ == "__main__": 34 | common.testmain(__file__, dotest) 35 | 36 | -------------------------------------------------------------------------------- /docs/reference/rotate.md: -------------------------------------------------------------------------------- 1 | ## rotate ## 2 | 3 | ```python 4 | rotate(angle: float, x = None, y = None) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | This method allows to perform a rotation around a given center. 10 | 11 | The rotation affects all elements which are printed after the method call 12 | (with the exception of clickable areas). 13 | 14 | Remarks: 15 | 16 | Only the display is altered. The get_x() and get_y() methods are not affected, 17 | nor the automatic page break mechanism. Rotation is not kept from page to page. 18 | Each page begins with a null rotation. Note: this behaviour are subject to 19 | change. 20 | 21 | ### Parameters ### 22 | 23 | angle: 24 | > Angle in degrees. 25 | 26 | x: 27 | > Abscissa of the rotation center. Default value: current position. 28 | 29 | y: 30 | > Ordinate of the rotation center. Default value: current position. 31 | 32 | ### Example ### 33 | ```python 34 | pdf.set_font('Arial', '', 14) 35 | pdf.add_page() 36 | # Rotate all consequenced operations 37 | pdf.rotate(-30) 38 | pdf.write(5, "Rotated") 39 | pdf.write(5, " text") 40 | ``` 41 | 42 | ### See also ### 43 | 44 | [set_x](set_x.md), [set_y](set_y.md), [write](write.md) 45 | 46 | -------------------------------------------------------------------------------- /tests/cover/test_page_size.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Test page sizes and orientation" 4 | 5 | #PyFPDF-cover-test:format=PDF 6 | #PyFPDF-cover-test:fn=page_size.pdf 7 | #PyFPDF-cover-test:hash=be021da05095336223c011d0a23bc40f 8 | 9 | import os 10 | 11 | import common 12 | from fpdf import FPDF 13 | 14 | def page(pdf, text, orientation, format): 15 | pdf.add_page(orientation = orientation, format = format) 16 | pdf.write(8, text) 17 | pdf.ln(8) 18 | 19 | @common.add_unittest 20 | def dotest(outputname, nostamp): 21 | pdf = FPDF(orientation = "L", format = (100, 250)) 22 | pdf.compress = False 23 | if nostamp: 24 | pdf._putinfo = lambda: common.test_putinfo(pdf) 25 | pdf.set_font('Arial', '', 14) 26 | for i in range(16): 27 | o = ["p", "l"][i % 2] 28 | f = ["a3", "a4", "a5", "letter", "legal", "", 29 | (100, 250), (320, 240)][i % 8] 30 | page(pdf, "Page %d from 16\nFormat: %s\nOrientation: %s" % 31 | (i + 1, f, o), o, f) 32 | pdf.output(outputname, 'F') 33 | 34 | def main(): 35 | return common.testmain(__file__, dotest) 36 | 37 | if __name__ == "__main__": 38 | main() 39 | 40 | -------------------------------------------------------------------------------- /docs/reference/output.md: -------------------------------------------------------------------------------- 1 | ## output ## 2 | 3 | ```python 4 | fpdf.output(name = '', dest = '') 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Send the document to some destination: standard output, a file or a byte string. 10 | 11 | The method first calls [close](close.md) if necessary to terminate the document. 12 | 13 | **NOTICE:** 14 | In Python 2 strings were raw data but in Python 3 strings are now unicode by default. If you are using Python 3.x you have to use `pdf.output(dest='S').encode('latin-1')` in order to get the output, if you don't do so the generated PDF will be invalid and depending on the viewer either not open at all or show up as some blank pages. 15 | 16 | ### Parameters ### 17 | 18 | name: 19 | > The name of the file. Only used when writing to a file. 20 | 21 | dest: 22 | > Destination to send the document. It can take one of the following values: 23 | >> * `I` or `D`: write the document to _sys.stdout_. This is the default if no file name is given. 24 | >> * `F`: save to a local file with the given name (may include a path). This is the default if a file name is given. 25 | >> * `S`: return the document as a byte string. 26 | 27 | ### See also ### 28 | 29 | [close](close.md). 30 | -------------------------------------------------------------------------------- /docs/reference/write.md: -------------------------------------------------------------------------------- 1 | ## write ## 2 | 3 | ```python 4 | write(h: float, txt: str, link) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | This method prints text from the current position. When the right margin is 10 | reached (or the \n character is met), a line break occurs and text continues 11 | from the left margin. Upon method exit, the current position is left just at 12 | the end of the text. 13 | 14 | It is possible to put a link on the text. 15 | 16 | ### Parameters ### 17 | 18 | h: 19 | > Line height. 20 | 21 | txt: 22 | > String to print. 23 | 24 | link: 25 | > URL or identifier returned by [add_link](add_link.md). 26 | 27 | ### Example ### 28 | ```python 29 | # Begin with regular font 30 | pdf.set_font('Arial', '', 14) 31 | pdf.write(5, 'Visit ') 32 | # Then put a blue underlined link 33 | pdf.set_text_color(0, 0, 255) 34 | pdf.set_font('', 'U') 35 | pdf.write(5, 'www.fpdf.org', 'http://www.fpdf.org') 36 | ``` 37 | 38 | ### See also ### 39 | 40 | [set_doc_option](set_doc_option.md), [set_font](set_font.md), 41 | [set_text_color](set_text_color.md), [add_link](add_link.md), 42 | [multi_cell](multi_cell.md), [set_auto_page_break](set_auto_page_break.md), 43 | [write_html](write_html.md) 44 | -------------------------------------------------------------------------------- /tests/cover/test_issue70.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Basic test to check issue 70: raise an exception if add_page was not called" 4 | 5 | import common 6 | from fpdf import FPDF 7 | 8 | import os, struct 9 | 10 | @common.add_unittest 11 | def dotest(outputname, nostamp): 12 | try: 13 | # Portrait, millimeter units, A4 page size 14 | pdf = FPDF("P", "mm", "A4") 15 | # Set font: Times, normal, size 10 16 | pdf.set_font('Times','', 12) 17 | ##pdf.add_page() 18 | # Layout cell: 0 x 5 mm, text, no border, Left 19 | pdf.cell(0,5,'Input 1 : ',border=0,align="L") 20 | pdf.cell(0,5,'Input 2 : ', border=0,align="L") 21 | pdf.cell(0,5,'Recomendation : ', border=0, align="L") 22 | pdf.cell(0,5,'Data 1 :', border=0, align="L" ) 23 | pdf.cell(0,5,'Data 2 :', border=0, align="L" ) 24 | pdf.output(outputname,'F') 25 | except RuntimeError as e: 26 | assert e.args[0] == "FPDF error: No page open, you need to call add_page() first" 27 | else: 28 | raise RuntimeError("Exception not raised!") 29 | 30 | if __name__ == "__main__": 31 | common.testmain(__file__, dotest) 32 | 33 | -------------------------------------------------------------------------------- /tests/cover/test_jpeg.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Test jpeg image embedding" 4 | 5 | # Note: img_cmyk.jpg has no color profile, PDF rendering may vary 6 | 7 | #PyFPDF-cover-test:format=PDF 8 | #PyFPDF-cover-test:fn=jpeg.pdf 9 | #PyFPDF-cover-test:hash=eb8db8f336226f6de671a3e515b9cc61 10 | #PyFPDF-cover-test:res=img_gray.jpg 11 | #PyFPDF-cover-test:res=img_rgb.jpg 12 | #PyFPDF-cover-test:res=img_cmyk.jpg 13 | 14 | import common # test utilities 15 | from fpdf import FPDF 16 | 17 | import os.path 18 | 19 | @common.add_unittest 20 | def dotest(outputname, nostamp): 21 | pdf = FPDF() 22 | if nostamp: 23 | pdf._putinfo = lambda: common.test_putinfo(pdf) 24 | 25 | pdf.add_page() 26 | pdf.set_font('Arial', '', 14) 27 | 28 | pdf.text(10, 57, 'DeviceGray') 29 | pdf.image(os.path.join(common.basepath, "img_gray.jpg"), 55, 5) 30 | 31 | pdf.text(10, 157, 'DeviceRGB') 32 | pdf.image(os.path.join(common.basepath, "img_rgb.jpg"), 55, 105) 33 | 34 | pdf.text(10, 257, 'DeviceCMYK') 35 | pdf.image(os.path.join(common.basepath, "img_cmyk.jpg"), 55, 205) 36 | 37 | pdf.output(outputname, 'F') 38 | 39 | if __name__ == "__main__": 40 | common.testmain(__file__, dotest) 41 | 42 | -------------------------------------------------------------------------------- /tests/cover/test_unicode.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Example of unicode support based on tfPDF http://www.fpdf.org/en/script/script92.php" 4 | 5 | from __future__ import with_statement 6 | 7 | #PyFPDF-cover-test:format=PDF 8 | #PyFPDF-cover-test:fn=ex.pdf 9 | #PyFPDF-cover-test:hash=e3c74fe7738fba7eed0cd489c597dc88 10 | #PyFPDF-cover-test:res=font/DejaVuSansCondensed.ttf 11 | #PyFPDF-cover-test:res=HelloWorld.txt 12 | 13 | import common 14 | from fpdf import FPDF 15 | 16 | import os 17 | 18 | @common.add_unittest 19 | def dotest(outputname, nostamp): 20 | pdf = FPDF() 21 | if nostamp: 22 | pdf._putinfo = lambda: common.test_putinfo(pdf) 23 | 24 | pdf.add_page() 25 | # Add a Unicode font (uses UTF-8) 26 | pdf.add_font('DejaVu', '', \ 27 | os.path.join(common.basepath, "font", 'DejaVuSansCondensed.ttf'), \ 28 | uni = True) 29 | pdf.set_font('DejaVu','',14) 30 | 31 | # Load a UTF-8 string from a file and print it 32 | with open(os.path.join(common.basepath, "HelloWorld.txt"), "rb") as file: 33 | txt = file.read().decode("UTF-8") 34 | pdf.write(8, txt) 35 | 36 | 37 | pdf.output(outputname, 'F') 38 | 39 | if __name__ == "__main__": 40 | common.testmain(__file__, dotest) 41 | 42 | -------------------------------------------------------------------------------- /tests/unifonts.py: -------------------------------------------------------------------------------- 1 | # try all ttf fonts 2 | 3 | from __future__ import with_statement 4 | 5 | from fpdf import FPDF 6 | import fpdf 7 | import sys 8 | import os 9 | import time 10 | 11 | base = os.path.dirname(__file__) 12 | 13 | pdf = FPDF() 14 | pdf.add_page() 15 | 16 | #font_dir = fpdf.FPDF_FONT_DIR 17 | font_dir = os.path.join(base, 'font') 18 | 19 | with open(os.path.join(base, 'HelloWorld.txt')) as file: 20 | txt = file.read() 21 | 22 | # Add a Unicode font (uses UTF-8) 23 | for font in os.listdir(font_dir): 24 | if font.lower().endswith('.ttf'): 25 | fontpath = os.path.join(font_dir, font) 26 | print(fontpath) 27 | t0 = time.time() 28 | pdf.add_font(font,'', fontpath, uni=True) 29 | t1 = time.time() 30 | pdf.set_font(font,'',14) 31 | t2 = time.time() 32 | pdf.write(8, font) 33 | pdf.ln() 34 | pdf.write(8, txt) 35 | pdf.ln() 36 | t3 = time.time() 37 | print("ttf loading time", t1-t0) 38 | print("ttf total time", t3-t0) 39 | print() 40 | 41 | fn = 'unifonts.pdf' 42 | pdf.output(fn,'F') 43 | import os 44 | try: 45 | os.startfile(fn) 46 | except: 47 | os.system("xdg-open \"%s\"" % fn) 48 | -------------------------------------------------------------------------------- /tests/cover/test_simple.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Basic example to test PyFPDF" 4 | 5 | #PyFPDF-cover-test:format=PDF 6 | #PyFPDF-cover-test:fn=simple.pdf 7 | #PyFPDF-cover-test:hash=1fd821a42cb5029a51727a6107b623ec 8 | #PyFPDF-cover-test:pil=yes 9 | #PyFPDF-cover-test:res=../tutorial/logo.png 10 | #PyFPDF-cover-test:res=flower2.jpg 11 | #PyFPDF-cover-test:res=lena.gif 12 | 13 | import common # test utilities 14 | from fpdf import FPDF 15 | 16 | import sys 17 | import os, os.path 18 | 19 | @common.add_unittest 20 | def dotest(outputname, nostamp): 21 | pdf = FPDF() 22 | if nostamp: 23 | pdf._putinfo = lambda: common.test_putinfo(pdf) 24 | 25 | pdf.add_page() 26 | pdf.set_font('Arial', '', 14) 27 | pdf.ln(10) 28 | if nostamp: 29 | data = "TEST-TEST-TEST" 30 | else: 31 | data = sys.version 32 | 33 | pdf.write(5, 'hello world %s' % data) 34 | path = os.path.join(common.basepath, os.pardir, "tutorial", "logo.png") 35 | pdf.image(path, 50, 50) 36 | pdf.image(os.path.join(common.basepath, "flower2.jpg"), 100, 50) 37 | pdf.image(os.path.join(common.basepath, "lena.gif"), 50, 75) 38 | pdf.output(outputname, 'F') 39 | 40 | if __name__ == "__main__": 41 | common.testmain(__file__, dotest) 42 | 43 | -------------------------------------------------------------------------------- /tests/cover/test_nbpages.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Simple test to check alias_nb_pages replacement under unicode fonts" 4 | 5 | #PyFPDF-cover-test:format=PDF 6 | #PyFPDF-cover-test:fn=nb_pages.pdf 7 | #PyFPDF-cover-test:hash=071fab0d32afcbe780e171c0da50865a 8 | #PyFPDF-cover-test:res=font/DejaVuSansCondensed.ttf 9 | 10 | import common 11 | import fpdf 12 | 13 | import os 14 | 15 | @common.add_unittest 16 | def dotest(outputname, nostamp): 17 | pdf = fpdf.FPDF() 18 | if nostamp: 19 | pdf._putinfo = lambda: common.test_putinfo(pdf) 20 | 21 | fpdf.set_global("FPDF_CACHE_MODE", 1) 22 | # set default alias: {nb} that will be replaced with total page count 23 | pdf.alias_nb_pages() 24 | 25 | # Add a Unicode font (uses UTF-8) 26 | pdf.add_font('DejaVu', '', \ 27 | os.path.join(common.basepath, "font", 'DejaVuSansCondensed.ttf'), \ 28 | uni = True) 29 | pdf.set_font('DejaVu', '', 14) 30 | 31 | for i in range(5): 32 | pdf.add_page() 33 | pdf.set_font('Arial','B',16) 34 | pdf.cell(40,10,'Hello World! Page %d from {nb}' % (i + 1)) 35 | pdf.set_font('DejaVu','',14) 36 | pdf.cell(40,30,'Hello World! unicode {nb}') 37 | 38 | 39 | pdf.output(outputname, 'F') 40 | 41 | if __name__ == "__main__": 42 | common.testmain(__file__, dotest) 43 | 44 | -------------------------------------------------------------------------------- /tests/unzlib.py: -------------------------------------------------------------------------------- 1 | from __future__ import with_statement 2 | 3 | import zlib 4 | import sys 5 | import pdb 6 | import os 7 | from binascii import hexlify 8 | 9 | print(sys.argv[1]) 10 | hex = '--hex' in sys.argv 11 | with open(sys.argv[1], 'rb') as r: 12 | i = 0 13 | length = None 14 | while True: 15 | l = r.readline().decode("ascii", "replace") # Avoid b". . ." in 2.5 16 | if not l: 17 | break 18 | if "/Length " in l: 19 | print(l) 20 | s = l[l.index("/Length ")+8:] 21 | if ' ' in s: 22 | s = s[:s.index(" ")] 23 | if '>' in s: 24 | s = s[:s.index(">")] 25 | length = int(s) 26 | print("%s%s" % (l, length)) 27 | if l.startswith('stream') and length: 28 | i += 1 29 | fn = "stream_%s_%s" % (i, sys.argv[1]) 30 | print("writing %s %s" % (length, fn)) 31 | s = r.read(length) 32 | with open(fn, 'wb') as w: 33 | try: 34 | s = zlib.decompress(s) 35 | except zlib.error: 36 | pass 37 | if hex: 38 | s = hexlify(s) 39 | w.write(s) 40 | 41 | os.system("windiff stream_1_ex_php.pdf stream_1_ex.pdf") 42 | -------------------------------------------------------------------------------- /tests/charmap.py: -------------------------------------------------------------------------------- 1 | "Print all charters" 2 | 3 | import os, sys 4 | 5 | from fpdf import FPDF, FPDF_VERSION 6 | from fpdf.ttfonts import TTFontFile 7 | 8 | print (FPDF_VERSION) 9 | 10 | class MyTTFontFile(TTFontFile): 11 | def getCMAP4(self, unicode_cmap_offset, glyphToChar, charToGlyph): 12 | TTFontFile.getCMAP4(self, unicode_cmap_offset, glyphToChar, charToGlyph) 13 | self.saveChar = charToGlyph 14 | 15 | def getCMAP12(self, unicode_cmap_offset, glyphToChar, charToGlyph): 16 | TTFontFile.getCMAP12(self, unicode_cmap_offset, glyphToChar, charToGlyph) 17 | self.saveChar = charToGlyph 18 | 19 | 20 | pdf=FPDF() 21 | pdf.compression = True 22 | pdf.add_page() 23 | 24 | #fontpath = "font/DroidSansFallback.ttf" 25 | fontpath = "font/DejaVuSans.ttf" 26 | pdf.add_font("font", '', fontpath, uni = True) 27 | ttf = MyTTFontFile() 28 | ttf.getMetrics(fontpath) 29 | 30 | if sys.version_info >= (3, 0): 31 | unichr = chr 32 | 33 | pdf.set_font("font", '', 10) 34 | 35 | # create PDF with first 999 charters in font 36 | cnt = 0 37 | for char in ttf.saveChar: 38 | cnt += 1 39 | pdf.write(8, u"%03d) %06x - %c" % (cnt, char, char)) 40 | pdf.ln() 41 | if cnt >= 999: 42 | break 43 | 44 | fn = 'charmap.pdf' 45 | pdf.output(fn,'F') 46 | 47 | 48 | try: 49 | os.startfile(fn) 50 | except: 51 | os.system("xdg-open \"%s\"" % fn) 52 | 53 | -------------------------------------------------------------------------------- /tests/cover/test_issue78.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Test RGB image with transparency" 4 | # https://github.com/reingart/pyfpdf/issues/78 5 | 6 | #PyFPDF-cover-test:format=PDF 7 | #PyFPDF-cover-test:fn=issue_78.pdf 8 | #PyFPDF-cover-test:hash=295ef37323b3115da64fcc47c1aca8dc 9 | #PyFPDF-cover-test:res=../tutorial/logo.png 10 | #PyFPDF-cover-test:pil=yes 11 | 12 | import common 13 | from fpdf import FPDF 14 | 15 | import os 16 | import tempfile 17 | try: 18 | try: 19 | import Image 20 | except: 21 | from PIL import Image 22 | except ImportError: 23 | Image = None 24 | 25 | @common.add_unittest 26 | def dotest(outputname, nostamp): 27 | pdf = FPDF(orientation = "L", unit = "in") 28 | if nostamp: 29 | pdf._putinfo = lambda: common.test_putinfo(pdf) 30 | 31 | pdf.add_page() 32 | 33 | img_path = os.path.join(common.basepath, '../tutorial/logo.png') 34 | img = Image.open(img_path) 35 | w, h = img.size 36 | width = 8 37 | height = width * (h // w) 38 | with tempfile.NamedTemporaryFile(delete = False, suffix = ".png") as f: 39 | img_new = f.name 40 | # convert to RGBA 41 | img2 = img.convert(mode = "RGBA") 42 | img2.save(img_new) 43 | # create pdf 44 | pdf.image(img_new, x = 1, y = 1, w = width, h = height) 45 | 46 | pdf.output(outputname, 'F') 47 | 48 | if __name__ == "__main__": 49 | common.testmain(__file__, dotest) 50 | 51 | -------------------------------------------------------------------------------- /docs/reference/set_display_mode.md: -------------------------------------------------------------------------------- 1 | ## set_display_mode ## 2 | 3 | ```python 4 | fpdf.set_display_mode(zoom, layout: str) 5 | ``` 6 | ### Description ### 7 | 8 | Defines the way the document is to be displayed by the viewer. The zoom level can be set: pages can be displayed entirely on screen, occupy the full width of the window, use the real size, be scaled by a specific zooming factor or use the viewer default (configured in the Preferences menu of Adobe Reader). The page layout can be specified too: single page at a time, continuous display, two columns or viewer default. 9 | 10 | If this method is not called, the zoom mode is set to _fullwidth_ and the layout is set to _continuous_ by default. 11 | 12 | ### Parameters ### 13 | 14 | zoom: 15 | > The zoom to use. It can be one of the following string values: 16 | >> * `fullpage`: displays the entire page on the screen 17 | >> * `fullwidth`: uses the maximum width of the window 18 | >> * `real`: uses the real size (equivalent to 100% zoom) 19 | >> * `default`: uses the viewer default mode 20 | > 21 | > or a number indicating the zooming factor to use, as a percentage. 22 | 23 | layout: 24 | > The page layout. Possible values are: 25 | >> * `single`: displays one page at a time 26 | >> * `continuous`: displays pages continuously 27 | >> * `two`: displays two pages in two columns 28 | >> * `default`: uses the viewer default mode 29 | > 30 | > The default value is `continuous`. 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /tests/cover/test_template.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "This is test template" 4 | 5 | # Lines below must not be separated by blank line 6 | # output formats PDF (can be auto-opened), TXT 7 | #PyFPDF-cover-test:format=PDF 8 | # default filename 9 | #PyFPDF-cover-test:fn=template.pdf 10 | # hash stamp for compare in --check mode (insert your hash) 11 | #PyFPDF-cover-test:hash=b1812fffdcf175976e80317b3766a0f0 12 | # use 2to3 tool (default - no) 13 | #PyFPDF-cover-test:2to3=no 14 | # can be used in python2 (default - yes) 15 | #PyFPDF-cover-test:python2=yes 16 | # can be used in python3 (default - yes) 17 | #PyFPDF-cover-test:python3=yes 18 | # is PIL required (default - no) 19 | #PyFPDF-cover-test:pil=no 20 | # only for platform (default all - *) 21 | #PyFPDF-cover-test:platform=* 22 | #... 23 | #...PyFPDF-cover-test:res=some_resource.ttf 24 | #...PyFPDF-cover-test:res=other_resource.txt 25 | #... 26 | 27 | import common # common set of utilities 28 | from fpdf import FPDF 29 | 30 | import sys 31 | 32 | @common.add_unittest 33 | def dotest(outputname, nostamp): 34 | # filename - output filename 35 | # nostamp - do no use stamp in result file 36 | pdf = FPDF() 37 | if nostamp: 38 | pdf._putinfo = lambda: common.test_putinfo(pdf) 39 | pdf.add_page() 40 | pdf.set_font('Arial', '', 16) 41 | pdf.write(8, "Test template") 42 | pdf.output(outputname, 'F') 43 | 44 | if __name__ == "__main__": 45 | common.testmain(__file__, dotest) 46 | 47 | -------------------------------------------------------------------------------- /docs/reference/FPDF.md: -------------------------------------------------------------------------------- 1 | ## FPDF ## 2 | 3 | ```python 4 | fpdf = FPDF(orientation = 'P', unit = 'mm', format='A4') 5 | ``` 6 | 7 | ### Description ### 8 | 9 | This is the class constructor. It allows setting up the page format, the orientation and the unit of measurement used in all methods (except for font sizes). 10 | 11 | ### Parameters ### 12 | 13 | orientation: 14 | > Default page orientation. Possible values are (case insensitive): 15 | >> * P or Portrait 16 | >> * L or Landscape 17 | > 18 | > The default value is P. 19 | 20 | unit: 21 | > User unit. Possible values are: 22 | >> * pt: point 23 | >> * mm: millimeter 24 | >> * cm: centimeter 25 | >> * in: inch 26 | 27 | > A point equals 1/72 of an inch, that is to say about 0.35 mm (an inch being 2.54 cm). This is a very common unit in typography; font sizes are expressed in this unit. 28 | > The default value is mm. 29 | 30 | format: 31 | > The format used for pages. It can be any one of the following values (case insensitive): 32 | >> * A3 33 | >> * A4 34 | >> * A5 35 | >> * Letter 36 | >> * Legal 37 | > 38 | > or a tuple containing the width and the height (expressed in the given unit). In portrait orientation, the tuple should be in the order (_width_, _height_), but in landscape orientation, the order should be (_height_, _width_). In either case, the first tuple element is usually less than the second. 39 | 40 | > The default value is A4. 41 | 42 | ### Example ### 43 | 44 | Example with a custom 100x150 mm page format: 45 | ```python 46 | pdf = FPDF('P', 'mm', (100, 150)) 47 | ``` 48 | -------------------------------------------------------------------------------- /tests/cover/test_issue82.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Test get_string_width for missing glyphs (issue 82)" 4 | 5 | #PyFPDF-cover-test:res=font/DejaVuSansCondensed.ttf 6 | #PyFPDF-cover-test:res=HelloWorld.txt 7 | 8 | import common 9 | import fpdf 10 | 11 | import os, shutil, time 12 | 13 | def check_width(req, new): 14 | return round(new, 4) == round(req, 4) 15 | 16 | @common.add_unittest 17 | def dotest(outputname, nostamp): 18 | fpdf.set_global("FPDF_CACHE_MODE", 1) 19 | pdf = fpdf.FPDF() 20 | pdf.add_font('DejaVu', '', \ 21 | os.path.join(common.basepath, "font", 'DejaVuSansCondensed.ttf'), \ 22 | uni = True) 23 | pdf.set_font('DejaVu','',14) 24 | 25 | with open(os.path.join(common.basepath, "HelloWorld.txt"), "rb") as file: 26 | txt = file.read().decode("UTF-8") 27 | std_ln = [27.0849, 37.9455, 30.4927, 25.7711, 41.0175, 38.7406, 30.3445, 28 | 22.1163, 34.8314, 12.0813, 20.0829, 14.7485, 33.4188] 29 | for line, reqw in zip(txt.split("\n"), std_ln): 30 | if line[-1:] == "\r": 31 | line = line[:-1] 32 | lang = line.split(":", 1) 33 | w = pdf.get_string_width(lang[1]) 34 | c = check_width(reqw, w) 35 | if not nostamp: 36 | s = lang[0] + ": " 37 | if c: 38 | s += "Ok" 39 | else: 40 | s += "%.4f != %.4f" % (w, reqw) 41 | common.log(s) 42 | assert c, "Glyph widths for \"" + lang[0] + "\" wrong!" 43 | 44 | if __name__ == "__main__": 45 | common.testmain(__file__, dotest) 46 | 47 | -------------------------------------------------------------------------------- /tests/cover/test_imgmask.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Test image masking" 4 | # https://github.com/reingart/pyfpdf/pull/80 5 | 6 | #PyFPDF-cover-test:format=PDF 7 | #PyFPDF-cover-test:fn=masking.pdf 8 | #PyFPDF-cover-test:hash=53abdb706882ecdedf5ee4c59852ae48 9 | #PyFPDF-cover-test:res=masking.png 10 | #PyFPDF-cover-test:res=lena.gif 11 | #PyFPDF-cover-test:res=img_gray.jpg 12 | #PyFPDF-cover-test:res=img_cmyk.jpg 13 | #PyFPDF-cover-test:res=img_rgb.jpg 14 | #PyFPDF-cover-test:pil=yes 15 | 16 | import common 17 | from fpdf import FPDF 18 | 19 | import os 20 | 21 | @common.add_unittest 22 | def dotest(outputname, nostamp): 23 | pdf = FPDF() 24 | if nostamp: 25 | pdf._putinfo = lambda: common.test_putinfo(pdf) 26 | 27 | pdf.add_page() 28 | pdf.set_font('Arial', '', 14) 29 | 30 | for i in range(0, 270, 5): 31 | pdf.text(i % 40 + 20, i + 20, "Image masking " * 4) 32 | mask = pdf.image(os.path.join(common.basepath, "masking.png"), 33 | is_mask = True) 34 | pdf.image(os.path.join(common.basepath, "lena.gif"), 35 | 40.0, 20.0, w = 120, mask_image = mask) 36 | 37 | pdf.image(os.path.join(common.basepath, "img_gray.jpg"), 38 | 20.0, 200.0, w = 50, mask_image = mask) 39 | pdf.image(os.path.join(common.basepath, "img_rgb.jpg"), 40 | 80.0, 200.0, w = 50, mask_image = mask) 41 | pdf.image(os.path.join(common.basepath, "img_cmyk.jpg"), 42 | 140.0, 200.0, w = 50, mask_image = mask) 43 | 44 | pdf.output(outputname, 'F') 45 | 46 | if __name__ == "__main__": 47 | common.testmain(__file__, dotest) 48 | 49 | -------------------------------------------------------------------------------- /tests/html_unicode.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "HTML Renderer for FPDF.py (unicode)" 4 | 5 | __author__ = "Mariano Reingart " 6 | __copyright__ = "Copyright (C) 2010 Mariano Reingart" 7 | __license__ = "LGPL 3.0" 8 | 9 | # Inspired by tuto5.py and several examples from fpdf.org, html2fpdf, etc. 10 | 11 | from fpdf import FPDF, HTMLMixin 12 | 13 | import os.path 14 | 15 | 16 | if __name__ == '__main__': 17 | 18 | 19 | class MyFPDF(FPDF, HTMLMixin): pass 20 | 21 | pdf=MyFPDF() 22 | 23 | # load the unicode font 24 | dir = os.path.dirname(__file__) 25 | font = os.path.join(dir, 'font', 'DejaVuSansCondensed.ttf') 26 | pdf.add_font('DejaVu', '', font, uni=True) 27 | 28 | pdf.add_page() 29 | 30 | # test the basic fonts 31 | pdf.write_html("""

hello world

""") 32 | pdf.write_html("""

hello world

""") 33 | pdf.write_html("""

hello world

""") 34 | pdf.write_html("""

hello world

""") 35 | 36 | # test the unicode (utf8) font: 37 | 38 | # greek 39 | pdf.write_html(u"""

Γειά σου κόσμος

""") 40 | # russian 41 | pdf.write_html(u"""

Здравствуй, Мир

""") 42 | 43 | fn = 'html_unicode.pdf' 44 | pdf.output(fn,'F') 45 | 46 | import os 47 | try: 48 | os.startfile(fn) 49 | except: 50 | os.system("xdg-open \"%s\"" % fn) 51 | -------------------------------------------------------------------------------- /tests/cover/test_issue62.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Test issue 62 (Can't render unicode character letter c with caron)" 4 | 5 | # This was issue to c with caron due 6 | # U+010C (uppercase Č) 7 | # U+010D (lowercase č). 8 | # and not properly escaping 9 | 10 | #PyFPDF-cover-test:format=PDF 11 | #PyFPDF-cover-test:fn=issue_62.pdf 12 | #PyFPDF-cover-test:hash=44624598b76bd4a18c6b14d3e00563e7 13 | #PyFPDF-cover-test:res=font/DejaVuSansCondensed.ttf 14 | 15 | import os 16 | 17 | import common 18 | from fpdf import FPDF 19 | 20 | @common.add_unittest 21 | def dotest(outputname, nostamp): 22 | pdf = FPDF() 23 | if nostamp: 24 | pdf._putinfo = lambda: common.test_putinfo(pdf) 25 | pdf.add_page() 26 | pdf.add_font('DejaVu', '', os.path.join(common.basepath, 27 | 'font/DejaVuSansCondensed.ttf'), uni = True) 28 | pdf.set_font('DejaVu', '', 14) 29 | 30 | # Note: this line cause syntax error in Python 3.0-3.2 31 | text = u""" 32 | Veľké písmená 33 | A Á Ä B C Č D Ď DZ DŽ E É F G H CH I Í J K L Ĺ Ľ 34 | Malé písmená 35 | a á ä b c č d ď dz dž e é f g h ch i í j k l ĺ ľ 36 | Veľké písmená 37 | M N Ň O Ó Ô P Q R Ŕ S Š T Ť U Ú V W X Y Ý Z Ž 38 | Malé písmená 39 | m n ň o ó ô p q r ŕ s š t ť u ú v w x y ý z ž 40 | """ 41 | 42 | pdf.write(8, text) 43 | pdf.ln(8) 44 | pdf.output(outputname, 'F') 45 | 46 | def main(): 47 | return common.testmain(__file__, dotest) 48 | 49 | if __name__ == "__main__": 50 | main() 51 | 52 | -------------------------------------------------------------------------------- /fpdf/php.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: latin-1 -*- 3 | 4 | from .py3k import PY3K, basestring, unicode 5 | 6 | # fpdf php helpers: 7 | 8 | def substr(s, start, length=-1): 9 | if length < 0: 10 | length=len(s)-start 11 | return s[start:start+length] 12 | 13 | def sprintf(fmt, *args): return fmt % args 14 | 15 | def print_r(array): 16 | if not isinstance(array, dict): 17 | array = dict([(k, k) for k in array]) 18 | for k, v in array.items(): 19 | print("[%s] => %s " % (k, v)) 20 | 21 | def UTF8ToUTF16BE(instr, setbom=True): 22 | "Converts UTF-8 strings to UTF16-BE." 23 | outstr = "".encode() 24 | if (setbom): 25 | outstr += "\xFE\xFF".encode("latin1") 26 | if not isinstance(instr, unicode): 27 | instr = instr.decode('UTF-8') 28 | outstr += instr.encode('UTF-16BE') 29 | # convert bytes back to fake unicode string until PEP461-like is implemented 30 | if PY3K: 31 | outstr = outstr.decode("latin1") 32 | return outstr 33 | 34 | def UTF8StringToArray(instr): 35 | "Converts UTF-8 strings to codepoints array" 36 | return [ord(c) for c in instr] 37 | 38 | # ttfints php helpers: 39 | 40 | def die(msg): 41 | raise RuntimeError(msg) 42 | 43 | def str_repeat(s, count): 44 | return s * count 45 | 46 | def str_pad(s, pad_length=0, pad_char= " ", pad_type= +1 ): 47 | if pad_type<0: # pad left 48 | return s.rjust(pad_length, pad_char) 49 | elif pad_type>0: # pad right 50 | return s.ljust(pad_length, pad_char) 51 | else: # pad both 52 | return s.center(pad_length, pad_char) 53 | 54 | strlen = count = lambda s: len(s) 55 | -------------------------------------------------------------------------------- /tests/cover/test_issue60.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Basic test to reproduce issue 60: RTL languages (arabian, hebrew, etc.)" 4 | 5 | #PyFPDF-cover-test:format=PDF 6 | #PyFPDF-cover-test:fn=issue_60.pdf 7 | #PyFPDF-cover-test:hash=ef5e4effbe67ced3b1fbb1a7db53d7da 8 | #PyFPDF-cover-test:res=font/DejaVuSans.ttf 9 | 10 | import common 11 | from fpdf import FPDF 12 | 13 | import sys, traceback, os 14 | 15 | @common.add_unittest 16 | def dotest(outputname, nostamp): 17 | try: 18 | from bidi.algorithm import get_display 19 | except ImportError: 20 | from unittest import SkipTest 21 | raise SkipTest("Need python-bidi") 22 | pdf = FPDF() 23 | if nostamp: 24 | pdf._putinfo = lambda: common.test_putinfo(pdf) 25 | 26 | pdf.compress = False 27 | pdf.add_page() 28 | pdf.add_font('DejaVu', '', \ 29 | os.path.join(common.basepath, 'font/DejaVuSans.ttf'), uni=True) 30 | pdf.set_font('DejaVu', '', 14) 31 | # this will be displayed wrong as actually it is stored LTR: 32 | text= u"این یک متن پارسی است. This is a Persian text !!" 33 | pdf.write(8, text) 34 | pdf.ln(8) 35 | # Reverse the RLT using the Bidirectional Algorithm to be displayed correctly: 36 | # (http://unicode.org/reports/tr9/) 37 | rtl_text = get_display(text) 38 | pdf.write(8, rtl_text) 39 | 40 | pdf.output(outputname, 'F') 41 | 42 | if __name__ == "__main__": 43 | try: 44 | from bidi.algorithm import get_display 45 | except ImportError: 46 | traceback.print_exc() 47 | common.err("This test requre PyBiDi (https://pypi.python.org/pypi/python-bidi)") 48 | common.log("SKIP") 49 | sys.exit(0) 50 | common.testmain(__file__, dotest) 51 | 52 | -------------------------------------------------------------------------------- /tests/cover/test_winfonts.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Example of unicode support winfonts based on tfPDF" 4 | # http://www.fpdf.org/en/script/script92.php 5 | 6 | from __future__ import with_statement 7 | 8 | #PyFPDF-cover-test:format=PDF 9 | #PyFPDF-cover-test:fn=winfonts.pdf 10 | #PyFPDF-cover-test:platform=win32 11 | #PyFPDF-cover-test:res=HelloWorld.txt 12 | 13 | # This test can't calc hash because TTF fonts can vary on systems 14 | 15 | import common 16 | import fpdf 17 | 18 | import os, time 19 | 20 | @common.add_unittest 21 | def dotest(outputname, nostamp): 22 | fpdf.set_global('SYSTEM_TTFONTS', "c:\\WINDOWS\\Fonts") 23 | 24 | pdf = fpdf.FPDF() 25 | if nostamp: 26 | pdf._putinfo = lambda: common.test_putinfo(pdf) 27 | 28 | pdf.add_page() 29 | # Add a Windows System font (uses UTF-8) 30 | t0 = time.time() 31 | pdf.add_font('sysfont','','arial.ttf',uni=True) 32 | pdf.set_font('sysfont','',14) 33 | t1 = time.time() 34 | if not nostamp: 35 | common.log("ttf loading time", t1-t0) 36 | 37 | # Load a UTF-8 string from a file and print it 38 | with open(os.path.join(common.basepath, "HelloWorld.txt"), "rb") as file: 39 | txt = file.read().decode("UTF-8") 40 | pdf.multi_cell(25, 5, txt) 41 | 42 | pdf.text(100, 5, '1234') 43 | 44 | pdf.write(5,'To find out what\'s new in self tutorial, click ') 45 | pdf.set_font('','U') 46 | link=pdf.add_link() 47 | pdf.write(5,'here',link) 48 | 49 | # Select a standard font (uses windows-1252) 50 | pdf.set_font('Arial','',14) 51 | pdf.ln(10) 52 | pdf.write(5, 'The file size of this PDF is only 12 KB.') 53 | 54 | pdf.output(outputname, 'F') 55 | 56 | if __name__ == "__main__": 57 | common.testmain(__file__, dotest) 58 | 59 | -------------------------------------------------------------------------------- /docs/reference/multi_cell.md: -------------------------------------------------------------------------------- 1 | ## multi_cell ## 2 | 3 | ```python 4 | fpdf.multi_cell(w: float, h: float, txt: str, border = 0, 5 | align: str = 'J', fill: bool = False) 6 | ``` 7 | 8 | ### Description ### 9 | 10 | This method allows printing text with line breaks. They can be automatic (as 11 | soon as the text reaches the right border of the cell) or explicit (via the 12 | `\n` character). As many cells as necessary are output, one below the other. 13 | Text can be aligned, centered or justified. The cell block can be framed and 14 | the background painted. 15 | 16 | ### Parameters ### 17 | 18 | w: 19 | > Width of cells. If 0, they extend up to the right margin of the page. 20 | 21 | h: 22 | > Height of cells. 23 | 24 | txt: 25 | > String to print. 26 | 27 | border: 28 | > Indicates if borders must be drawn around the cell block. The value can be 29 | either a number: 30 | >> * 0: no border 31 | >> * 1: frame 32 | > 33 | > or a string containing some or all of the following characters (in any 34 | order): 35 | >> * `L`: left 36 | >> * `T`: top 37 | >> * `R`: right 38 | >> * `B`: bottom 39 | > 40 | > Default value: 0. 41 | 42 | align: 43 | > Sets the text alignment. Possible values are: 44 | >> * `L`: left alignment 45 | >> * `C`: center 46 | >> * `R`: right alignment 47 | >> * `J`: justification (default value) 48 | 49 | fill 50 | > Indicates if the cell background must be painted (`True`) or transparent 51 | (`False`). Default value: False. 52 | 53 | ### See also ### 54 | 55 | [set_doc_option](set_doc_option.md), [set_font](set_font.md), 56 | [set_draw_color](set_draw_color.md), [set_fill_color](set_fill_color.md), 57 | [set_text_color](set_text_color.md), [set_line_width](set_line_width.md), 58 | [cell](cell.md), [write](write.md), 59 | [set_auto_page_break](set_auto_page_break.md). 60 | -------------------------------------------------------------------------------- /docs/reference/add_page.md: -------------------------------------------------------------------------------- 1 | ## add_page ## 2 | 3 | ```python 4 | fpdf.add_page(orientation = '', format = '', same = False) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Adds a new page to the document. If a page is already present, the 10 | [footer](footer.md) method is called first to output the footer. Then the page 11 | is added, the current position set to the top-left corner according to the left 12 | and top margins, and [header](header.md) is called to display the header. 13 | 14 | The font which was set before calling is automatically restored. There is no 15 | need to call [set_font](set_font.md) again if you want to continue with the same 16 | font. Colors and the line width are also preserved. 17 | 18 | The origin of the coordinate system is at the top-left corner and increasing 19 | ordinates go downwards. 20 | 21 | ### Parameters ### 22 | 23 | orientation: 24 | > Page orientation. Possible values are (case insensitive): 25 | >> * P or Portrait 26 | >> * L or Landscape 27 | > 28 | > The default value is the one passed to the constructor. 29 | 30 | format: 31 | > The format used for pages. It can be either one of the following values (case 32 | insensitive): 33 | >> * A3 34 | >> * A4 35 | >> * A5 36 | >> * Letter 37 | >> * Legal 38 | > 39 | > or a tuple containing the width and the height (expressed in the 40 | given unit). In portrait orientation, the tuple should be in the order 41 | (_width_, _height_), but in landscape orientation, the order should be 42 | (_height_, _width_). In either case, the first tuple element is usually less 43 | than the second. 44 | > 45 | > The default value is the one passed to the constructor. 46 | 47 | same: 48 | > True if page must be same as previous. In this case other parameters are 49 | ignored. 50 | 51 | ### See also ### 52 | 53 | [FPDF](FPDF.md), [header](header.md), [footer](footer.md), 54 | [set_margins](set_margins.md). 55 | -------------------------------------------------------------------------------- /attic/PHPutils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: iso-8859-1 -*- 2 | 3 | """ 4 | A few rough Python equivalents of PHP internal functions (=lazy port). 5 | 6 | NOTE: 7 | 1) PHP "array" object is mostly similar to a Python "dictionary", but some 8 | times a "list" (or "array": see Protection.py) may be required! 9 | 10 | 2) PHP "isset()" tests often wether an array has given key, or a variable 11 | is defined in global/local space; 12 | 13 | 3) PHP string functions have often different return values from Python (see below); 14 | 15 | 4) "for (x; a <[=]b; y)" loops become "for i in range(a,b[+1]):" in Python; 16 | 17 | 5) PHP emits automatically floats quotients when needed, Python don't: so add a 18 | ".0" to divisors when PDF expects decimal numbers. 19 | 20 | Actually, all FPDF tutorials (even from ported modules) work fine, but bugs 21 | or incompatibilities might be hidden somewhere: so, USE IT AT YOUR OWN RISK! 22 | """ 23 | import sys, os 24 | 25 | strlen = len 26 | filesize=os.path.getsize 27 | file_exists=os.path.exists 28 | count=len 29 | SEEK_CUR=1 30 | SEEK_SET=0 31 | 32 | def substr(s, start, length=-1): 33 | if length < 0: 34 | length=len(s)-start 35 | return s[start:start+length] 36 | 37 | def substr_count(haystack, needle, offset=0, length=None): 38 | return haystack.count(needle,offset) 39 | 40 | def die(s): 41 | sys.stderr.write(s) 42 | sys.exit(-1) 43 | 44 | def basename(p): 45 | return os.path.splitext(p)[0] 46 | 47 | def is_bool(x): return type(x)==type(bool()) 48 | def empty(s): return len(s)==0 49 | def is_string(s): return isinstance(s,basestring) 50 | def strtolower(s): return s.lower() 51 | def strtoupper(s): return s.upper() 52 | def str_replace(sc, rp, s): return s.replace(sc,rp) 53 | def sprintf(fmt, *args): return fmt % args 54 | def strpos(s, c): return s.find(c) # Python returns -1 instead of FALSE! 55 | def strrpos(s, c): return s.rfind(c) # Python returns -1 instead of FALSE! 56 | def hexdec(x): return int(x,16) 57 | def floor(x): return float(int(x)) 58 | def str_repeat(s,t): return s*int(t) 59 | -------------------------------------------------------------------------------- /tests/cover/test_output.py: -------------------------------------------------------------------------------- 1 | "Test the various PDF output modes" 2 | 3 | from __future__ import with_statement 4 | 5 | #PyFPDF-cover-test:format=PDF 6 | #PyFPDF-cover-test:fn=output.pdf 7 | #PyFPDF-cover-test:hash=3996992652a230c26ffe8b5b7525aeb3 8 | 9 | import common 10 | from fpdf import FPDF 11 | 12 | import sys 13 | 14 | try: # Python >= 2.6 15 | bytes 16 | except NameError: # Python 2.5 17 | bytes = str 18 | 19 | @common.add_unittest 20 | def dotest(outputname, nostamp=True): 21 | pdf = FPDF(unit="pt") 22 | pdf._putinfo = lambda: common.test_putinfo(pdf) 23 | pdf.add_page() 24 | pdf.set_font("Times", size=12) 25 | pdf.cell(0, 12, "Dummy content") 26 | 27 | # Get the PDF data the usual way via a real file 28 | pdf.output(outputname) 29 | with open(outputname, "rb") as file: 30 | data = file.read(1000) 31 | assert len(data) == 966, "Unexpected PDF file size" 32 | 33 | try: # Python < 3 (Python 2.5 does not have the "io" module) 34 | from cStringIO import StringIO 35 | capture = StringIO() 36 | detach = lambda: capture 37 | except ImportError: # Python >= 3.1 38 | from io import TextIOWrapper, BytesIO 39 | # Ensure that no text encoding is actually done 40 | capture = TextIOWrapper(BytesIO(), "undefined") 41 | detach = lambda: capture.detach() 42 | 43 | # Compare data when output() writes to stdout 44 | original_stdout = sys.stdout 45 | try: 46 | sys.stdout = capture 47 | pdf.output() 48 | capture = detach() 49 | finally: 50 | sys.stdout = original_stdout 51 | assert capture.getvalue() == data, "Unexpected stdout data" 52 | 53 | # Compare data when output() returns a byte string 54 | returned = pdf.output(dest="S") 55 | assert isinstance(returned, bytes), "output() should return bytes" 56 | assert returned == data, "Unexpected PDF data returned" 57 | 58 | if __name__ == "__main__": 59 | common.testmain(__file__, dotest) 60 | -------------------------------------------------------------------------------- /fpdf/py3k.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | "Special module to handle differences between Python 2 and 3 versions" 5 | 6 | import sys 7 | 8 | PY3K = sys.version_info >= (3, 0) 9 | 10 | try: 11 | import cPickle as pickle 12 | except ImportError: 13 | import pickle 14 | 15 | try: 16 | from urllib import urlopen 17 | except ImportError: 18 | from urllib.request import urlopen 19 | 20 | try: 21 | from io import BytesIO 22 | except ImportError: 23 | try: 24 | from cStringIO import StringIO as BytesIO 25 | except ImportError: 26 | from StringIO import StringIO as BytesIO 27 | 28 | try: 29 | from hashlib import md5 30 | except ImportError: 31 | try: 32 | from md5 import md5 33 | except ImportError: 34 | md5 = None 35 | def hashpath(fn): 36 | h = md5() 37 | if PY3K: 38 | h.update(fn.encode("UTF-8")) 39 | else: 40 | h.update(fn) 41 | return h.hexdigest() 42 | 43 | # Check if PIL is available (tries importing both pypi version and corrected or manually installed versions). 44 | # Necessary for JPEG and GIF support. 45 | # TODO: Pillow support 46 | try: 47 | from PIL import Image 48 | except ImportError: 49 | try: 50 | import Image 51 | except ImportError: 52 | Image = None 53 | 54 | try: 55 | from HTMLParser import HTMLParser 56 | except ImportError: 57 | from html.parser import HTMLParser 58 | 59 | if PY3K: 60 | basestring = str 61 | unicode = str 62 | ord = lambda x: x 63 | else: 64 | basestring = basestring 65 | unicode = unicode 66 | ord = ord 67 | 68 | # shortcut to bytes conversion (b prefix) 69 | def b(s): 70 | if isinstance(s, basestring): 71 | return s.encode("latin1") 72 | elif isinstance(s, int): 73 | if PY3K: 74 | return bytes([s]) # http://bugs.python.org/issue4588 75 | else: 76 | return chr(s) 77 | 78 | def exception(): 79 | "Return the current the exception instance currently being handled" 80 | # this is needed to support Python 2.5 that lacks "as" syntax 81 | return sys.exc_info()[1] 82 | 83 | 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | pyfpdf: FPDF for Python 2 | ======================= 3 | 4 | PyFPDF is a library for PDF document generation under Python, ported from PHP 5 | (see [FPDF][1]: "Free"-PDF, a well-known PDFlib-extension replacement with many 6 | examples, scripts and derivatives). 7 | 8 | Compared with other PDF libraries, PyFPDF is simple, small and versatile, with 9 | advanced capabilities, and is easy to learn, extend and maintain. 10 | 11 | [1]: http://www.fpdf.org/ 12 | 13 | Features: 14 | --------- 15 | 16 | * Python 2.5 to 3.4 support 17 | * Unicode (UTF-8) TrueType font subset embedding 18 | * Barcode I2of5 and code39, QR code coming soon ... 19 | * PNG, GIF and JPG support (including transparency and alpha channel) 20 | * Templates with a visual designer & basic html2pdf 21 | * Exceptions support, other minor fixes, improvements and PEP8 code cleanups 22 | 23 | Installation Instructions: 24 | -------------------------- 25 | 26 | To get the latest development version you can download the source code running: 27 | 28 | ``` 29 | git clone https://github.com/reingart/pyfpdf.git 30 | cd pyfpdf 31 | python setup.py install 32 | ``` 33 | 34 | You can also install PyFPDF from PyPI, with easyinstall or from Windows 35 | installers. For example, using pip: 36 | ``` 37 | pip install fpdf 38 | ``` 39 | 40 | **Note:** the [Python Imaging Library](http://www.pythonware.com/products/pil/) 41 | (PIL) is needed for GIF support. PNG and JPG support is built-in and doesn't 42 | require any external dependency. For Python 3, 43 | [Pillow - The friendly PIL fork](https://github.com/python-pillow/Pillow) is 44 | supported. 45 | 46 | Documentation: 47 | -------------- 48 | [![Documentation Status](https://readthedocs.org/projects/pyfpdf/badge/?version=latest)](http://pyfpdf.rtfd.org) 49 | 50 | * [Read the Docs](http://pyfpdf.readthedocs.org/en/latest/) 51 | * [FAQ](docs/FAQ.md) 52 | * [Tutorial](docs/Tutorial.md) (Spanish translation available) 53 | * [Reference Manual](docs/ReferenceManual.md) 54 | 55 | For further information, see the project site: 56 | https://github.com/reingart/pyfpdf or the old Google Code project page 57 | https://code.google.com/p/pyfpdf/. 58 | 59 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | try: 4 | from setuptools import setup 5 | except ImportError: 6 | from distutils.core import setup 7 | 8 | import os 9 | import sys 10 | import warnings 11 | import subprocess 12 | 13 | import fpdf 14 | package_dir = 'fpdf' 15 | 16 | # convert the README and format in restructured text (only when registering) 17 | long_desc = "" 18 | if os.path.exists("README.md"): 19 | try: 20 | cmd = ['pandoc', '--from=markdown', '--to=rst', 'README.md'] 21 | long_desc = subprocess.check_output(cmd).decode("utf8") 22 | except Exception as e: 23 | warnings.warn("Exception when converting the README format: %s" % e) 24 | 25 | setup(name='fpdf', 26 | version=fpdf.__version__, 27 | description='Simple PDF generation for Python', 28 | long_description=long_desc, 29 | author='Olivier PLATHEY ported by Max', 30 | author_email='maxpat78@yahoo.it', 31 | maintainer = "Mariano Reingart", 32 | maintainer_email = "reingart@gmail.com", 33 | url='http://code.google.com/p/pyfpdf', 34 | license='LGPLv3+', 35 | download_url="https://github.com/reingart/pyfpdf/tarball/%s" % fpdf.__version__, 36 | packages=['fpdf', ], 37 | package_dir={'fpdf': package_dir}, 38 | package_data={'fpdf': ['font/*.ttf', 'font/*.txt']}, 39 | classifiers = [ 40 | "Development Status :: 5 - Production/Stable", 41 | "Intended Audience :: Developers", 42 | "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", 43 | "Programming Language :: Python", 44 | "Programming Language :: Python :: 2.5", 45 | "Programming Language :: Python :: 2.6", 46 | "Programming Language :: Python :: 2.7", 47 | "Programming Language :: Python :: 3.2", 48 | "Programming Language :: Python :: 3.3", 49 | "Programming Language :: Python :: 3.4", 50 | "Operating System :: OS Independent", 51 | "Topic :: Software Development :: Libraries :: PHP Classes", 52 | "Topic :: Software Development :: Libraries :: Python Modules", 53 | "Topic :: Multimedia :: Graphics", 54 | ], 55 | keywords=["pdf", "unicode", "png", "jpg", "ttf"], 56 | ) 57 | 58 | -------------------------------------------------------------------------------- /tests/cover/test_stretching.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Example of font stretching and spacing" 4 | 5 | #PyFPDF-cover-test:format=PDF 6 | #PyFPDF-cover-test:fn=stretch.pdf 7 | #PyFPDF-cover-test:hash=5d4986d871e909b08bf69d0ed3050d83 8 | #PyFPDF-cover-test:res=font/DejaVuSans.ttf 9 | #PyFPDF-cover-test:res=HelloWorld.txt 10 | 11 | import common 12 | import fpdf 13 | from fpdf import FPDF 14 | 15 | import os 16 | 17 | def text(pdf, txt, stretching, nostamp): 18 | pdf.set_stretching(100) 19 | if not nostamp: 20 | pdf.write(8, "Text: stretching %.2f%%\n" %(stretching)) 21 | pdf.set_stretching(stretching) 22 | if not nostamp: 23 | pdf.write(8, txt) 24 | if not nostamp: 25 | txtc = "Cell example: stretching %.2f%%" %(stretching) 26 | for a in ["L", "C", "R"]: 27 | pdf.cell(w = 0, h = 8, txt = txtc, border = 1, align = a) 28 | pdf.write(8, "\n") 29 | pdf.write(8, "\n") 30 | if not nostamp: 31 | txtm = "MultiCell example: stretching %.2f%%" %(stretching) + " and words" * 50 + "\n" 32 | else: 33 | txtm = "Stretch=%.2f, Align=" % (stretching) 34 | for a in ["L", "C", "R", "J"]: 35 | if nostamp and a == "J": 36 | txtw = txt.replace("\n", " ") 37 | else: 38 | txtw = txt 39 | pdf.multi_cell(w = 0, h = 8, txt = txtm + a + "\n" + txtw, border = 1, align = a) 40 | pdf.write(8, "\n") 41 | pdf.write(8, "\n") 42 | 43 | 44 | @common.add_unittest 45 | def dotest(outputname, nostamp): 46 | fpdf.set_global("FPDF_CACHE_MODE", 1) 47 | pdf = FPDF() 48 | if nostamp: 49 | pdf._putinfo = lambda: common.test_putinfo(pdf) 50 | 51 | pdf.add_page() 52 | # Add a Unicode font (uses UTF-8) 53 | pdf.add_font('DejaVu', '', \ 54 | os.path.join(common.basepath, "font", 'DejaVuSans.ttf'), \ 55 | uni = True) 56 | pdf.set_font('DejaVu', '', 14) 57 | with open(os.path.join(common.basepath, "HelloWorld.txt"), "rb") as file: 58 | txt = file.read().decode("UTF-8") 59 | 60 | if not nostamp: 61 | text(pdf, txt, 100, nostamp) 62 | text(pdf, txt, 75, nostamp) 63 | text(pdf, txt, 125, nostamp) 64 | 65 | pdf.output(outputname, 'F') 66 | 67 | if __name__ == "__main__": 68 | common.testmain(__file__, dotest) 69 | 70 | -------------------------------------------------------------------------------- /tutorial/tuto3.py: -------------------------------------------------------------------------------- 1 | from __future__ import with_statement 2 | 3 | from fpdf import FPDF 4 | 5 | title = '20000 Leagues Under the Seas' 6 | 7 | class PDF(FPDF): 8 | def header(self): 9 | # Arial bold 15 10 | self.set_font('Arial', 'B', 15) 11 | # Calculate width of title and position 12 | w = self.get_string_width(title) + 6 13 | self.set_x((210 - w) / 2) 14 | # Colors of frame, background and text 15 | self.set_draw_color(0, 80, 180) 16 | self.set_fill_color(230, 230, 0) 17 | self.set_text_color(220, 50, 50) 18 | # Thickness of frame (1 mm) 19 | self.set_line_width(1) 20 | # Title 21 | self.cell(w, 9, title, 1, 1, 'C', 1) 22 | # Line break 23 | self.ln(10) 24 | 25 | def footer(self): 26 | # Position at 1.5 cm from bottom 27 | self.set_y(-15) 28 | # Arial italic 8 29 | self.set_font('Arial', 'I', 8) 30 | # Text color in gray 31 | self.set_text_color(128) 32 | # Page number 33 | self.cell(0, 10, 'Page ' + str(self.page_no()), 0, 0, 'C') 34 | 35 | def chapter_title(self, num, label): 36 | # Arial 12 37 | self.set_font('Arial', '', 12) 38 | # Background color 39 | self.set_fill_color(200, 220, 255) 40 | # Title 41 | self.cell(0, 6, 'Chapter %d : %s' % (num, label), 0, 1, 'L', 1) 42 | # Line break 43 | self.ln(4) 44 | 45 | def chapter_body(self, name): 46 | # Read text file 47 | with open(name, 'rb') as fh: 48 | txt = fh.read().decode('latin-1') 49 | # Times 12 50 | self.set_font('Times', '', 12) 51 | # Output justified text 52 | self.multi_cell(0, 5, txt) 53 | # Line break 54 | self.ln() 55 | # Mention in italics 56 | self.set_font('', 'I') 57 | self.cell(0, 5, '(end of excerpt)') 58 | 59 | def print_chapter(self, num, title, name): 60 | self.add_page() 61 | self.chapter_title(num, title) 62 | self.chapter_body(name) 63 | 64 | pdf = PDF() 65 | pdf.set_title(title) 66 | pdf.set_author('Jules Verne') 67 | pdf.print_chapter(1, 'A RUNAWAY REEF', '20k_c1.txt') 68 | pdf.print_chapter(2, 'THE PROS AND CONS', '20k_c2.txt') 69 | pdf.output('tuto3.pdf', 'F') 70 | 71 | -------------------------------------------------------------------------------- /attic/Bookmark.py: -------------------------------------------------------------------------------- 1 | from FPDF import * 2 | 3 | class Bookmark(FPDF): 4 | def __init__(this,orientation='P',unit='mm',format='A4'): 5 | FPDF.__init__(this,orientation,unit,format) 6 | this.outlines=[] 7 | this.OutlineRoot=None 8 | 9 | def Bookmark(this,txt,level=0,y=0): 10 | if(y==-1): 11 | y=this.GetY() 12 | this.outlines+=[{'t':txt,'l':level,'y':y,'p':this.PageNo()}] 13 | 14 | def _putbookmarks(this): 15 | nb=count(this.outlines) 16 | if(nb==0): 17 | return 18 | lru={} 19 | level=0 20 | for i in range(len(this.outlines)): 21 | o=this.outlines[i] 22 | if(o['l']>0): 23 | parent=lru[o['l']-1] 24 | #Set parent and last pointers 25 | this.outlines[i]['parent']=parent 26 | this.outlines[parent]['last']=i 27 | if(o['l']>level): 28 | #Level increasing: set first pointer 29 | this.outlines[parent]['first']=i 30 | else: 31 | this.outlines[i]['parent']=nb 32 | if(o['l']<=level and i>0): 33 | #Set prev and next pointers 34 | prev=lru[o['l']] 35 | this.outlines[prev]['next']=i 36 | this.outlines[i]['prev']=prev 37 | lru[o['l']]=i 38 | level=o['l'] 39 | #Outline items 40 | n=this.n+1 41 | for i in range(len(this.outlines)): 42 | o=this.outlines[i] 43 | this._newobj() 44 | this._out('<>') 56 | this._out('endobj') 57 | #Outline root 58 | this._newobj() 59 | this.OutlineRoot=this.n 60 | this._out('<>') 62 | this._out('endobj') 63 | 64 | 65 | def _putresources(this): 66 | FPDF._putresources(this) 67 | this._putbookmarks() 68 | 69 | def _putcatalog(this): 70 | FPDF._putcatalog(this) 71 | if(count(this.outlines)>0): 72 | this._out('/Outlines '+str(this.OutlineRoot)+' 0 R') 73 | this._out('/PageMode /UseOutlines') 74 | -------------------------------------------------------------------------------- /tests/cover/test_ttfonts.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Basic test of TrueType Unicode font handling" 4 | 5 | from __future__ import with_statement 6 | 7 | #PyFPDF-cover-test:res=font/DejaVuSansCondensed.ttf 8 | #PyFPDF-cover-test:res=dejavusanscondensed.cw.dat 9 | 10 | import common 11 | from fpdf.ttfonts import TTFontFile 12 | 13 | import os, struct 14 | 15 | @common.add_unittest 16 | def dotest(outputname, nostamp): 17 | ttf = TTFontFile() 18 | ttffile = os.path.join(common.basepath, "font", "DejaVuSansCondensed.ttf"); 19 | ttf.getMetrics(ttffile) 20 | # test basic metrics: 21 | assert round(ttf.descent, 0) == -236, "Check descent" 22 | assert round(ttf.capHeight, 0) == 928, "Chech capHeight" 23 | assert ttf.flags == 4, "Check flags" 24 | assert [round(i, 0) for i in ttf.bbox] == [-918, -415, 1513, 1167], "Check bbox" 25 | assert ttf.italicAngle == 0, "Check italicAngle==0" 26 | assert ttf.stemV == 87, "Check stemV" 27 | assert round(ttf.defaultWidth, 0) == 540, "Check defaultWidth" 28 | assert round(ttf.underlinePosition, 0) == -63, "Check underlinePosition" 29 | assert round(ttf.underlineThickness, 0) == 44, "Check underlineThickness" 30 | # test char widths (against binary file generated by tfpdf.php): 31 | # note: after fixing issue 82 this raw data started to be wrong 32 | # 1. total length - 65536, DejaVuSansCondensed.ttf maximal char is 65533, round to nearest 1024 size 33 | # 2. missing char width should be 540 instead of zero 34 | with open(os.path.join(common.basepath, "dejavusanscondensed.cw.dat"),\ 35 | "rb") as file: 36 | data = file.read() 37 | char_widths = struct.unpack(">%dH" % (len(data) // 2), data) 38 | assert len(char_widths) == 65536, "Check cw.dat char_widths 65536" 39 | assert len(ttf.charWidths) == 65536, "Check ttf char_widths 65536" 40 | diff = [] 41 | for i, (x, y) in enumerate(zip(char_widths, ttf.charWidths)): 42 | if x == 0 and y == ttf.defaultWidth: continue 43 | if x != y:# compare each char width, but not 0 44 | diff.append(i) 45 | assert not diff, "Check char widths" 46 | # for checking assertion works ttf.charWidths[1] = 600 47 | ## assert tuple(ttf.charWidths) == tuple(char_widths) 48 | 49 | if __name__ == "__main__": 50 | common.testmain(__file__, dotest) 51 | 52 | -------------------------------------------------------------------------------- /tutorial/unicode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf8 -*- 3 | 4 | from fpdf import FPDF 5 | import sys 6 | 7 | fn = 'unicode.pdf' 8 | 9 | pdf = FPDF() 10 | pdf.add_page() 11 | 12 | # Add a DejaVu Unicode font (uses UTF-8) 13 | # Supports more than 200 languages. For a coverage status see: 14 | # http://dejavu.svn.sourceforge.net/viewvc/dejavu/trunk/dejavu-fonts/langcover.txt 15 | pdf.add_font('DejaVu', '', 'DejaVuSansCondensed.ttf', uni=True) 16 | pdf.set_font('DejaVu', '', 14) 17 | 18 | text = u""" 19 | English: Hello World 20 | Greek: Γειά σου κόσμος 21 | Polish: Witaj świecie 22 | Portuguese: Olá mundo 23 | Russian: Здравствуй, Мир 24 | Vietnamese: Xin chào thế giới 25 | Arabic: مرحبا العالم 26 | Hebrew: שלום עולם 27 | """ 28 | 29 | for txt in text.split('\n'): 30 | pdf.write(8, txt) 31 | pdf.ln(8) 32 | 33 | # Add a Indic Unicode font (uses UTF-8) 34 | # Supports: Bengali, Devanagari, Gujarati, 35 | # Gurmukhi (including the variants for Punjabi) 36 | # Kannada, Malayalam, Oriya, Tamil, Telugu, Tibetan 37 | pdf.add_font('gargi', '', 'gargi.ttf', uni=True) 38 | pdf.set_font('gargi', '', 14) 39 | pdf.write(8, u'Hindi: नमस्ते दुनिया') 40 | pdf.ln(20) 41 | 42 | # Add a AR PL New Sung Unicode font (uses UTF-8) 43 | # The Open Source Chinese Font (also supports other east Asian languages) 44 | pdf.add_font('fireflysung', '','fireflysung.ttf', uni=True) 45 | pdf.set_font('fireflysung', '', 14) 46 | pdf.write(8, u'Chinese: 你好世界\n') 47 | pdf.write(8, u'Japanese: こんにちは世界\n') 48 | pdf.ln(10) 49 | 50 | # Add a Alee Unicode font (uses UTF-8) 51 | # General purpose Hangul truetype fonts that contain Korean syllable 52 | # and Latin9 (iso8859-15) characters. 53 | pdf.add_font('eunjin', '', 'Eunjin.ttf', uni=True) 54 | pdf.set_font('eunjin','', 14) 55 | pdf.write(8, u'Korean: 안녕하세요') 56 | pdf.ln(20) 57 | 58 | # Add a Fonts-TLWG (formerly ThaiFonts-Scalable) (uses UTF-8) 59 | pdf.add_font('waree', '', 'Waree.ttf', uni=True) 60 | pdf.set_font('waree', '', 14) 61 | pdf.write(8, u'Thai: สวัสดีชาวโลก') 62 | pdf.ln(20) 63 | 64 | # Select a standard font (uses windows-1252) 65 | pdf.set_font('Arial', '', 14) 66 | pdf.ln(10) 67 | pdf.write(5, 'This is standard built-in font') 68 | 69 | pdf.output(fn, 'F') 70 | import os 71 | try: 72 | os.startfile(fn) 73 | except: 74 | os.system("xdg-open \"%s\"" % fn) 75 | 76 | -------------------------------------------------------------------------------- /attic/font/symbol.py: -------------------------------------------------------------------------------- 1 | fpdf_charwidths['symbol']={ 2 | '\x00':250,'\x01':250,'\x02':250,'\x03':250,'\x04':250,'\x05':250,'\x06':250,'\x07':250,'\x08':250,'\t':250,'\n':250,'\x0b':250,'\x0c':250,'\r':250,'\x0e':250,'\x0f':250,'\x10':250,'\x11':250,'\x12':250,'\x13':250,'\x14':250,'\x15':250, 3 | '\x16':250,'\x17':250,'\x18':250,'\x19':250,'\x1a':250,'\x1b':250,'\x1c':250,'\x1d':250,'\x1e':250,'\x1f':250,' ':250,'!':333,'"':713,'#':500,'$':549,'%':833,'&':778,'\'':439,'(':333,')':333,'*':500,'+':549, 4 | ',':250,'-':549,'.':250,'/':278,'0':500,'1':500,'2':500,'3':500,'4':500,'5':500,'6':500,'7':500,'8':500,'9':500,':':278,';':278,'<':549,'=':549,'>':549,'?':444,'@':549,'A':722, 5 | 'B':667,'C':722,'D':612,'E':611,'F':763,'G':603,'H':722,'I':333,'J':631,'K':722,'L':686,'M':889,'N':722,'O':722,'P':768,'Q':741,'R':556,'S':592,'T':611,'U':690,'V':439,'W':768, 6 | 'X':645,'Y':795,'Z':611,'[':333,'\\':863,']':333,'^':658,'_':500,'`':500,'a':631,'b':549,'c':549,'d':494,'e':439,'f':521,'g':411,'h':603,'i':329,'j':603,'k':549,'l':549,'m':576, 7 | 'n':521,'o':549,'p':549,'q':521,'r':549,'s':603,'t':439,'u':576,'v':713,'w':686,'x':493,'y':686,'z':494,'{':480,'|':200,'}':480,'~':549,'\x7f':0,'\x80':0,'\x81':0,'\x82':0,'\x83':0, 8 | '\x84':0,'\x85':0,'\x86':0,'\x87':0,'\x88':0,'\x89':0,'\x8a':0,'\x8b':0,'\x8c':0,'\x8d':0,'\x8e':0,'\x8f':0,'\x90':0,'\x91':0,'\x92':0,'\x93':0,'\x94':0,'\x95':0,'\x96':0,'\x97':0,'\x98':0,'\x99':0, 9 | '\x9a':0,'\x9b':0,'\x9c':0,'\x9d':0,'\x9e':0,'\x9f':0,'\xa0':750,'\xa1':620,'\xa2':247,'\xa3':549,'\xa4':167,'\xa5':713,'\xa6':500,'\xa7':753,'\xa8':753,'\xa9':753,'\xaa':753,'\xab':1042,'\xac':987,'\xad':603,'\xae':987,'\xaf':603, 10 | '\xb0':400,'\xb1':549,'\xb2':411,'\xb3':549,'\xb4':549,'\xb5':713,'\xb6':494,'\xb7':460,'\xb8':549,'\xb9':549,'\xba':549,'\xbb':549,'\xbc':1000,'\xbd':603,'\xbe':1000,'\xbf':658,'\xc0':823,'\xc1':686,'\xc2':795,'\xc3':987,'\xc4':768,'\xc5':768, 11 | '\xc6':823,'\xc7':768,'\xc8':768,'\xc9':713,'\xca':713,'\xcb':713,'\xcc':713,'\xcd':713,'\xce':713,'\xcf':713,'\xd0':768,'\xd1':713,'\xd2':790,'\xd3':790,'\xd4':890,'\xd5':823,'\xd6':549,'\xd7':250,'\xd8':713,'\xd9':603,'\xda':603,'\xdb':1042, 12 | '\xdc':987,'\xdd':603,'\xde':987,'\xdf':603,'\xe0':494,'\xe1':329,'\xe2':790,'\xe3':790,'\xe4':786,'\xe5':713,'\xe6':384,'\xe7':384,'\xe8':384,'\xe9':384,'\xea':384,'\xeb':384,'\xec':494,'\xed':494,'\xee':494,'\xef':494,'\xf0':0,'\xf1':329, 13 | '\xf2':274,'\xf3':686,'\xf4':686,'\xf5':686,'\xf6':384,'\xf7':384,'\xf8':384,'\xf9':384,'\xfa':384,'\xfb':384,'\xfc':494,'\xfd':494,'\xfe':494,'\xff':0} -------------------------------------------------------------------------------- /docs/reference/image.md: -------------------------------------------------------------------------------- 1 | ## image ## 2 | 3 | ```python 4 | fpdf.image(name, x = None, y = None, w = 0, h = 0, type = '', link = '') 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Puts an image. The size it will take on the page can be specified in different 10 | ways: 11 | 12 | * explicit width and height (expressed in user units) 13 | * one explicit dimension, the other being calculated automatically in order to 14 | keep the original proportions 15 | * no explicit dimension, in which case the image is put at 72 dpi. 16 | 17 | Supported formats are JPEG, PNG and GIF. 18 | 19 | For JPEGs, all flavors are allowed: 20 | 21 | * gray scales 22 | * true colors (24 bits) 23 | * CMYK (32 bits) 24 | 25 | For PNGs, these are allowed: 26 | 27 | * gray scales of at most 8 bits (256 levels) 28 | * indexed colors 29 | * true colors (24 bits) 30 | * alpha channel (_version 1.7 and up_) 31 | 32 | but this is not supported: 33 | 34 | * interlacing 35 | 36 | For GIFs: in case of an animated GIF, only the first frame is used. 37 | 38 | If a transparent color is defined, it is taken into account. 39 | 40 | The format can be specified explicitly or inferred from the file extension. 41 | 42 | It is possible to put a link on the image. 43 | 44 | **Remark**: if an image is used several times, only one copy is embedded in the 45 | file. 46 | 47 | ### Parameters ### 48 | 49 | name: 50 | > Path or URL of the image. 51 | 52 | x: 53 | > Abscissa of the upper-left corner. If not specified or equal to None, the 54 | > current abscissa is used (_version 1.7.1 and up_). 55 | 56 | y: 57 | > Ordinate of the upper-left corner. If not specified or equal to None, the 58 | > current ordinate is used; moreover, a page break is triggered first if 59 | > necessary (in case automatic page breaking is enabled) and, after the call, 60 | > the current ordinate is moved to the bottom of the image 61 | > (_version 1.7.1 and up_). 62 | 63 | w: 64 | > Width of the image in the page. If not specified or equal to zero, it is 65 | > automatically calculated. 66 | 67 | h: 68 | > Height of the image in the page. If not specified or equal to zero, it is 69 | > automatically calculated. 70 | 71 | type: 72 | > Image format. Possible values are (case insensitive): JPG, JPEG, PNG and GIF. 73 | > If not specified, the type is inferred from the file extension. 74 | 75 | link: 76 | > URL or identifier returned by [add_link](add_link.md). 77 | 78 | ### See also ### 79 | 80 | [add_link](add_link.md), [load_resource](load_resource.md). 81 | 82 | -------------------------------------------------------------------------------- /attic/TOC.py: -------------------------------------------------------------------------------- 1 | from FPDF import * 2 | 3 | class TOC(FPDF): 4 | def __init__(this, orientation='P',unit='mm',format='A4'): 5 | this._toc=[] 6 | this._numbering=0 7 | this._numberingFooter=0 8 | this._numPageNum=1 9 | FPDF.__init__(this,orientation,unit,format) 10 | 11 | def AddPage(this,orientation=''): 12 | FPDF.AddPage(this,orientation) 13 | if(this._numbering): 14 | this._numPageNum+=1 15 | 16 | def startPageNums(this): 17 | this._numbering=1 18 | this._numberingFooter=1 19 | 20 | def stopPageNums(this): 21 | this._numbering=0 22 | 23 | def numPageNo(this): 24 | return this._numPageNum 25 | 26 | def TOC_Entry(this,txt,level=0): 27 | this._toc+=[{'t':txt,'l':level,'p':this.numPageNo()}] 28 | 29 | def insertTOC(this,location=1,labelSize=20,entrySize=10,tocfont='Times',label='Table of Contents'): 30 | #make toc at end 31 | this.stopPageNums() 32 | this.AddPage() 33 | tocstart=this.page 34 | 35 | this.SetFont(tocfont,'B',labelSize) 36 | this.Cell(0,5,label,0,1,'C') 37 | this.Ln(10) 38 | 39 | for t in this._toc: 40 | #Offset 41 | level=t['l'] 42 | if(level>0): 43 | this.Cell(level*8) 44 | weight='' 45 | if(level==0): 46 | weight='B' 47 | Str=t['t'] 48 | this.SetFont(tocfont,weight,entrySize) 49 | strsize=this.GetStringWidth(Str) 50 | this.Cell(strsize+2,this.FontSize+2,Str) 51 | 52 | #Filling dots 53 | this.SetFont(tocfont,'',entrySize) 54 | PageCellSize=this.GetStringWidth(str(t['p']))+2 55 | w=this.w-this.lMargin-this.rMargin-PageCellSize-(level*8)-(strsize+2) 56 | nb=w/this.GetStringWidth('.') 57 | dots=str_repeat('.',nb) 58 | this.Cell(w,this.FontSize+2,dots,0,0,'R') 59 | 60 | #Page number 61 | this.Cell(PageCellSize,this.FontSize+2,str(t['p']),0,1,'R') 62 | 63 | #grab it and move to selected location 64 | n=this.page 65 | n_toc = n - tocstart + 1 66 | last = [] 67 | 68 | #store toc pages 69 | for i in xrange(tocstart,n+1): 70 | last+=[this.pages[i]] 71 | 72 | #move pages 73 | for i in xrange(tocstart-1,location-1,-1): 74 | #~ for(i=tocstart - 1;i>=location-1;i--) 75 | this.pages[i+n_toc]=this.pages[i] 76 | 77 | #Put toc pages at insert point 78 | for i in xrange(0,n_toc): 79 | this.pages[location + i]=last[i] 80 | 81 | def Footer(this): 82 | if(this._numberingFooter==0): 83 | return 84 | #Go to 1.5 cm from bottom 85 | this.SetY(-15) 86 | #Select Arial italic 8 87 | this.SetFont('Arial','I',8) 88 | this.Cell(0,7,str(this.numPageNo()),0,0,'C'); 89 | if(this._numbering==0): 90 | this._numberingFooter=0 91 | -------------------------------------------------------------------------------- /attic/font/times.py: -------------------------------------------------------------------------------- 1 | fpdf_charwidths['times']={ 2 | '\x00':250,'\x01':250,'\x02':250,'\x03':250,'\x04':250,'\x05':250,'\x06':250,'\x07':250,'\x08':250,'\t':250,'\n':250,'\x0b':250,'\x0c':250,'\r':250,'\x0e':250,'\x0f':250,'\x10':250,'\x11':250,'\x12':250,'\x13':250,'\x14':250,'\x15':250, 3 | '\x16':250,'\x17':250,'\x18':250,'\x19':250,'\x1a':250,'\x1b':250,'\x1c':250,'\x1d':250,'\x1e':250,'\x1f':250,' ':250,'!':333,'"':408,'#':500,'$':500,'%':833,'&':778,'\'':180,'(':333,')':333,'*':500,'+':564, 4 | ',':250,'-':333,'.':250,'/':278,'0':500,'1':500,'2':500,'3':500,'4':500,'5':500,'6':500,'7':500,'8':500,'9':500,':':278,';':278,'<':564,'=':564,'>':564,'?':444,'@':921,'A':722, 5 | 'B':667,'C':667,'D':722,'E':611,'F':556,'G':722,'H':722,'I':333,'J':389,'K':722,'L':611,'M':889,'N':722,'O':722,'P':556,'Q':722,'R':667,'S':556,'T':611,'U':722,'V':722,'W':944, 6 | 'X':722,'Y':722,'Z':611,'[':333,'\\':278,']':333,'^':469,'_':500,'`':333,'a':444,'b':500,'c':444,'d':500,'e':444,'f':333,'g':500,'h':500,'i':278,'j':278,'k':500,'l':278,'m':778, 7 | 'n':500,'o':500,'p':500,'q':500,'r':333,'s':389,'t':278,'u':500,'v':500,'w':722,'x':500,'y':500,'z':444,'{':480,'|':200,'}':480,'~':541,'\x7f':350,'\x80':500,'\x81':350,'\x82':333,'\x83':500, 8 | '\x84':444,'\x85':1000,'\x86':500,'\x87':500,'\x88':333,'\x89':1000,'\x8a':556,'\x8b':333,'\x8c':889,'\x8d':350,'\x8e':611,'\x8f':350,'\x90':350,'\x91':333,'\x92':333,'\x93':444,'\x94':444,'\x95':350,'\x96':500,'\x97':1000,'\x98':333,'\x99':980, 9 | '\x9a':389,'\x9b':333,'\x9c':722,'\x9d':350,'\x9e':444,'\x9f':722,'\xa0':250,'\xa1':333,'\xa2':500,'\xa3':500,'\xa4':500,'\xa5':500,'\xa6':200,'\xa7':500,'\xa8':333,'\xa9':760,'\xaa':276,'\xab':500,'\xac':564,'\xad':333,'\xae':760,'\xaf':333, 10 | '\xb0':400,'\xb1':564,'\xb2':300,'\xb3':300,'\xb4':333,'\xb5':500,'\xb6':453,'\xb7':250,'\xb8':333,'\xb9':300,'\xba':310,'\xbb':500,'\xbc':750,'\xbd':750,'\xbe':750,'\xbf':444,'\xc0':722,'\xc1':722,'\xc2':722,'\xc3':722,'\xc4':722,'\xc5':722, 11 | '\xc6':889,'\xc7':667,'\xc8':611,'\xc9':611,'\xca':611,'\xcb':611,'\xcc':333,'\xcd':333,'\xce':333,'\xcf':333,'\xd0':722,'\xd1':722,'\xd2':722,'\xd3':722,'\xd4':722,'\xd5':722,'\xd6':722,'\xd7':564,'\xd8':722,'\xd9':722,'\xda':722,'\xdb':722, 12 | '\xdc':722,'\xdd':722,'\xde':556,'\xdf':500,'\xe0':444,'\xe1':444,'\xe2':444,'\xe3':444,'\xe4':444,'\xe5':444,'\xe6':667,'\xe7':444,'\xe8':444,'\xe9':444,'\xea':444,'\xeb':444,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':500,'\xf1':500, 13 | '\xf2':500,'\xf3':500,'\xf4':500,'\xf5':500,'\xf6':500,'\xf7':564,'\xf8':500,'\xf9':500,'\xfa':500,'\xfb':500,'\xfc':500,'\xfd':500,'\xfe':500,'\xff':500} -------------------------------------------------------------------------------- /attic/font/timesi.py: -------------------------------------------------------------------------------- 1 | fpdf_charwidths['timesI']={ 2 | '\x00':250,'\x01':250,'\x02':250,'\x03':250,'\x04':250,'\x05':250,'\x06':250,'\x07':250,'\x08':250,'\t':250,'\n':250,'\x0b':250,'\x0c':250,'\r':250,'\x0e':250,'\x0f':250,'\x10':250,'\x11':250,'\x12':250,'\x13':250,'\x14':250,'\x15':250, 3 | '\x16':250,'\x17':250,'\x18':250,'\x19':250,'\x1a':250,'\x1b':250,'\x1c':250,'\x1d':250,'\x1e':250,'\x1f':250,' ':250,'!':333,'"':420,'#':500,'$':500,'%':833,'&':778,'\'':214,'(':333,')':333,'*':500,'+':675, 4 | ',':250,'-':333,'.':250,'/':278,'0':500,'1':500,'2':500,'3':500,'4':500,'5':500,'6':500,'7':500,'8':500,'9':500,':':333,';':333,'<':675,'=':675,'>':675,'?':500,'@':920,'A':611, 5 | 'B':611,'C':667,'D':722,'E':611,'F':611,'G':722,'H':722,'I':333,'J':444,'K':667,'L':556,'M':833,'N':667,'O':722,'P':611,'Q':722,'R':611,'S':500,'T':556,'U':722,'V':611,'W':833, 6 | 'X':611,'Y':556,'Z':556,'[':389,'\\':278,']':389,'^':422,'_':500,'`':333,'a':500,'b':500,'c':444,'d':500,'e':444,'f':278,'g':500,'h':500,'i':278,'j':278,'k':444,'l':278,'m':722, 7 | 'n':500,'o':500,'p':500,'q':500,'r':389,'s':389,'t':278,'u':500,'v':444,'w':667,'x':444,'y':444,'z':389,'{':400,'|':275,'}':400,'~':541,'\x7f':350,'\x80':500,'\x81':350,'\x82':333,'\x83':500, 8 | '\x84':556,'\x85':889,'\x86':500,'\x87':500,'\x88':333,'\x89':1000,'\x8a':500,'\x8b':333,'\x8c':944,'\x8d':350,'\x8e':556,'\x8f':350,'\x90':350,'\x91':333,'\x92':333,'\x93':556,'\x94':556,'\x95':350,'\x96':500,'\x97':889,'\x98':333,'\x99':980, 9 | '\x9a':389,'\x9b':333,'\x9c':667,'\x9d':350,'\x9e':389,'\x9f':556,'\xa0':250,'\xa1':389,'\xa2':500,'\xa3':500,'\xa4':500,'\xa5':500,'\xa6':275,'\xa7':500,'\xa8':333,'\xa9':760,'\xaa':276,'\xab':500,'\xac':675,'\xad':333,'\xae':760,'\xaf':333, 10 | '\xb0':400,'\xb1':675,'\xb2':300,'\xb3':300,'\xb4':333,'\xb5':500,'\xb6':523,'\xb7':250,'\xb8':333,'\xb9':300,'\xba':310,'\xbb':500,'\xbc':750,'\xbd':750,'\xbe':750,'\xbf':500,'\xc0':611,'\xc1':611,'\xc2':611,'\xc3':611,'\xc4':611,'\xc5':611, 11 | '\xc6':889,'\xc7':667,'\xc8':611,'\xc9':611,'\xca':611,'\xcb':611,'\xcc':333,'\xcd':333,'\xce':333,'\xcf':333,'\xd0':722,'\xd1':667,'\xd2':722,'\xd3':722,'\xd4':722,'\xd5':722,'\xd6':722,'\xd7':675,'\xd8':722,'\xd9':722,'\xda':722,'\xdb':722, 12 | '\xdc':722,'\xdd':556,'\xde':611,'\xdf':500,'\xe0':500,'\xe1':500,'\xe2':500,'\xe3':500,'\xe4':500,'\xe5':500,'\xe6':667,'\xe7':444,'\xe8':444,'\xe9':444,'\xea':444,'\xeb':444,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':500,'\xf1':500, 13 | '\xf2':500,'\xf3':500,'\xf4':500,'\xf5':500,'\xf6':500,'\xf7':675,'\xf8':500,'\xf9':500,'\xfa':500,'\xfb':500,'\xfc':500,'\xfd':444,'\xfe':500,'\xff':444} -------------------------------------------------------------------------------- /attic/font/timesb.py: -------------------------------------------------------------------------------- 1 | fpdf_charwidths['timesB']={ 2 | '\x00':250,'\x01':250,'\x02':250,'\x03':250,'\x04':250,'\x05':250,'\x06':250,'\x07':250,'\x08':250,'\t':250,'\n':250,'\x0b':250,'\x0c':250,'\r':250,'\x0e':250,'\x0f':250,'\x10':250,'\x11':250,'\x12':250,'\x13':250,'\x14':250,'\x15':250, 3 | '\x16':250,'\x17':250,'\x18':250,'\x19':250,'\x1a':250,'\x1b':250,'\x1c':250,'\x1d':250,'\x1e':250,'\x1f':250,' ':250,'!':333,'"':555,'#':500,'$':500,'%':1000,'&':833,'\'':278,'(':333,')':333,'*':500,'+':570, 4 | ',':250,'-':333,'.':250,'/':278,'0':500,'1':500,'2':500,'3':500,'4':500,'5':500,'6':500,'7':500,'8':500,'9':500,':':333,';':333,'<':570,'=':570,'>':570,'?':500,'@':930,'A':722, 5 | 'B':667,'C':722,'D':722,'E':667,'F':611,'G':778,'H':778,'I':389,'J':500,'K':778,'L':667,'M':944,'N':722,'O':778,'P':611,'Q':778,'R':722,'S':556,'T':667,'U':722,'V':722,'W':1000, 6 | 'X':722,'Y':722,'Z':667,'[':333,'\\':278,']':333,'^':581,'_':500,'`':333,'a':500,'b':556,'c':444,'d':556,'e':444,'f':333,'g':500,'h':556,'i':278,'j':333,'k':556,'l':278,'m':833, 7 | 'n':556,'o':500,'p':556,'q':556,'r':444,'s':389,'t':333,'u':556,'v':500,'w':722,'x':500,'y':500,'z':444,'{':394,'|':220,'}':394,'~':520,'\x7f':350,'\x80':500,'\x81':350,'\x82':333,'\x83':500, 8 | '\x84':500,'\x85':1000,'\x86':500,'\x87':500,'\x88':333,'\x89':1000,'\x8a':556,'\x8b':333,'\x8c':1000,'\x8d':350,'\x8e':667,'\x8f':350,'\x90':350,'\x91':333,'\x92':333,'\x93':500,'\x94':500,'\x95':350,'\x96':500,'\x97':1000,'\x98':333,'\x99':1000, 9 | '\x9a':389,'\x9b':333,'\x9c':722,'\x9d':350,'\x9e':444,'\x9f':722,'\xa0':250,'\xa1':333,'\xa2':500,'\xa3':500,'\xa4':500,'\xa5':500,'\xa6':220,'\xa7':500,'\xa8':333,'\xa9':747,'\xaa':300,'\xab':500,'\xac':570,'\xad':333,'\xae':747,'\xaf':333, 10 | '\xb0':400,'\xb1':570,'\xb2':300,'\xb3':300,'\xb4':333,'\xb5':556,'\xb6':540,'\xb7':250,'\xb8':333,'\xb9':300,'\xba':330,'\xbb':500,'\xbc':750,'\xbd':750,'\xbe':750,'\xbf':500,'\xc0':722,'\xc1':722,'\xc2':722,'\xc3':722,'\xc4':722,'\xc5':722, 11 | '\xc6':1000,'\xc7':722,'\xc8':667,'\xc9':667,'\xca':667,'\xcb':667,'\xcc':389,'\xcd':389,'\xce':389,'\xcf':389,'\xd0':722,'\xd1':722,'\xd2':778,'\xd3':778,'\xd4':778,'\xd5':778,'\xd6':778,'\xd7':570,'\xd8':778,'\xd9':722,'\xda':722,'\xdb':722, 12 | '\xdc':722,'\xdd':722,'\xde':611,'\xdf':556,'\xe0':500,'\xe1':500,'\xe2':500,'\xe3':500,'\xe4':500,'\xe5':500,'\xe6':722,'\xe7':444,'\xe8':444,'\xe9':444,'\xea':444,'\xeb':444,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':500,'\xf1':556, 13 | '\xf2':500,'\xf3':500,'\xf4':500,'\xf5':500,'\xf6':500,'\xf7':570,'\xf8':500,'\xf9':556,'\xfa':556,'\xfb':556,'\xfc':556,'\xfd':500,'\xfe':556,'\xff':500} -------------------------------------------------------------------------------- /attic/font/timesbi.py: -------------------------------------------------------------------------------- 1 | fpdf_charwidths['timesBI']={ 2 | '\x00':250,'\x01':250,'\x02':250,'\x03':250,'\x04':250,'\x05':250,'\x06':250,'\x07':250,'\x08':250,'\t':250,'\n':250,'\x0b':250,'\x0c':250,'\r':250,'\x0e':250,'\x0f':250,'\x10':250,'\x11':250,'\x12':250,'\x13':250,'\x14':250,'\x15':250, 3 | '\x16':250,'\x17':250,'\x18':250,'\x19':250,'\x1a':250,'\x1b':250,'\x1c':250,'\x1d':250,'\x1e':250,'\x1f':250,' ':250,'!':389,'"':555,'#':500,'$':500,'%':833,'&':778,'\'':278,'(':333,')':333,'*':500,'+':570, 4 | ',':250,'-':333,'.':250,'/':278,'0':500,'1':500,'2':500,'3':500,'4':500,'5':500,'6':500,'7':500,'8':500,'9':500,':':333,';':333,'<':570,'=':570,'>':570,'?':500,'@':832,'A':667, 5 | 'B':667,'C':667,'D':722,'E':667,'F':667,'G':722,'H':778,'I':389,'J':500,'K':667,'L':611,'M':889,'N':722,'O':722,'P':611,'Q':722,'R':667,'S':556,'T':611,'U':722,'V':667,'W':889, 6 | 'X':667,'Y':611,'Z':611,'[':333,'\\':278,']':333,'^':570,'_':500,'`':333,'a':500,'b':500,'c':444,'d':500,'e':444,'f':333,'g':500,'h':556,'i':278,'j':278,'k':500,'l':278,'m':778, 7 | 'n':556,'o':500,'p':500,'q':500,'r':389,'s':389,'t':278,'u':556,'v':444,'w':667,'x':500,'y':444,'z':389,'{':348,'|':220,'}':348,'~':570,'\x7f':350,'\x80':500,'\x81':350,'\x82':333,'\x83':500, 8 | '\x84':500,'\x85':1000,'\x86':500,'\x87':500,'\x88':333,'\x89':1000,'\x8a':556,'\x8b':333,'\x8c':944,'\x8d':350,'\x8e':611,'\x8f':350,'\x90':350,'\x91':333,'\x92':333,'\x93':500,'\x94':500,'\x95':350,'\x96':500,'\x97':1000,'\x98':333,'\x99':1000, 9 | '\x9a':389,'\x9b':333,'\x9c':722,'\x9d':350,'\x9e':389,'\x9f':611,'\xa0':250,'\xa1':389,'\xa2':500,'\xa3':500,'\xa4':500,'\xa5':500,'\xa6':220,'\xa7':500,'\xa8':333,'\xa9':747,'\xaa':266,'\xab':500,'\xac':606,'\xad':333,'\xae':747,'\xaf':333, 10 | '\xb0':400,'\xb1':570,'\xb2':300,'\xb3':300,'\xb4':333,'\xb5':576,'\xb6':500,'\xb7':250,'\xb8':333,'\xb9':300,'\xba':300,'\xbb':500,'\xbc':750,'\xbd':750,'\xbe':750,'\xbf':500,'\xc0':667,'\xc1':667,'\xc2':667,'\xc3':667,'\xc4':667,'\xc5':667, 11 | '\xc6':944,'\xc7':667,'\xc8':667,'\xc9':667,'\xca':667,'\xcb':667,'\xcc':389,'\xcd':389,'\xce':389,'\xcf':389,'\xd0':722,'\xd1':722,'\xd2':722,'\xd3':722,'\xd4':722,'\xd5':722,'\xd6':722,'\xd7':570,'\xd8':722,'\xd9':722,'\xda':722,'\xdb':722, 12 | '\xdc':722,'\xdd':611,'\xde':611,'\xdf':500,'\xe0':500,'\xe1':500,'\xe2':500,'\xe3':500,'\xe4':500,'\xe5':500,'\xe6':722,'\xe7':444,'\xe8':444,'\xe9':444,'\xea':444,'\xeb':444,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':500,'\xf1':556, 13 | '\xf2':500,'\xf3':500,'\xf4':500,'\xf5':500,'\xf6':500,'\xf7':570,'\xf8':500,'\xf9':556,'\xfa':556,'\xfb':556,'\xfc':556,'\xfd':444,'\xfe':500,'\xff':444} -------------------------------------------------------------------------------- /attic/font/helvetica.py: -------------------------------------------------------------------------------- 1 | fpdf_charwidths['helvetica']={ 2 | '\x00':278,'\x01':278,'\x02':278,'\x03':278,'\x04':278,'\x05':278,'\x06':278,'\x07':278,'\x08':278,'\t':278,'\n':278,'\x0b':278,'\x0c':278,'\r':278,'\x0e':278,'\x0f':278,'\x10':278,'\x11':278,'\x12':278,'\x13':278,'\x14':278,'\x15':278, 3 | '\x16':278,'\x17':278,'\x18':278,'\x19':278,'\x1a':278,'\x1b':278,'\x1c':278,'\x1d':278,'\x1e':278,'\x1f':278,' ':278,'!':278,'"':355,'#':556,'$':556,'%':889,'&':667,'\'':191,'(':333,')':333,'*':389,'+':584, 4 | ',':278,'-':333,'.':278,'/':278,'0':556,'1':556,'2':556,'3':556,'4':556,'5':556,'6':556,'7':556,'8':556,'9':556,':':278,';':278,'<':584,'=':584,'>':584,'?':556,'@':1015,'A':667, 5 | 'B':667,'C':722,'D':722,'E':667,'F':611,'G':778,'H':722,'I':278,'J':500,'K':667,'L':556,'M':833,'N':722,'O':778,'P':667,'Q':778,'R':722,'S':667,'T':611,'U':722,'V':667,'W':944, 6 | 'X':667,'Y':667,'Z':611,'[':278,'\\':278,']':278,'^':469,'_':556,'`':333,'a':556,'b':556,'c':500,'d':556,'e':556,'f':278,'g':556,'h':556,'i':222,'j':222,'k':500,'l':222,'m':833, 7 | 'n':556,'o':556,'p':556,'q':556,'r':333,'s':500,'t':278,'u':556,'v':500,'w':722,'x':500,'y':500,'z':500,'{':334,'|':260,'}':334,'~':584,'\x7f':350,'\x80':556,'\x81':350,'\x82':222,'\x83':556, 8 | '\x84':333,'\x85':1000,'\x86':556,'\x87':556,'\x88':333,'\x89':1000,'\x8a':667,'\x8b':333,'\x8c':1000,'\x8d':350,'\x8e':611,'\x8f':350,'\x90':350,'\x91':222,'\x92':222,'\x93':333,'\x94':333,'\x95':350,'\x96':556,'\x97':1000,'\x98':333,'\x99':1000, 9 | '\x9a':500,'\x9b':333,'\x9c':944,'\x9d':350,'\x9e':500,'\x9f':667,'\xa0':278,'\xa1':333,'\xa2':556,'\xa3':556,'\xa4':556,'\xa5':556,'\xa6':260,'\xa7':556,'\xa8':333,'\xa9':737,'\xaa':370,'\xab':556,'\xac':584,'\xad':333,'\xae':737,'\xaf':333, 10 | '\xb0':400,'\xb1':584,'\xb2':333,'\xb3':333,'\xb4':333,'\xb5':556,'\xb6':537,'\xb7':278,'\xb8':333,'\xb9':333,'\xba':365,'\xbb':556,'\xbc':834,'\xbd':834,'\xbe':834,'\xbf':611,'\xc0':667,'\xc1':667,'\xc2':667,'\xc3':667,'\xc4':667,'\xc5':667, 11 | '\xc6':1000,'\xc7':722,'\xc8':667,'\xc9':667,'\xca':667,'\xcb':667,'\xcc':278,'\xcd':278,'\xce':278,'\xcf':278,'\xd0':722,'\xd1':722,'\xd2':778,'\xd3':778,'\xd4':778,'\xd5':778,'\xd6':778,'\xd7':584,'\xd8':778,'\xd9':722,'\xda':722,'\xdb':722, 12 | '\xdc':722,'\xdd':667,'\xde':667,'\xdf':611,'\xe0':556,'\xe1':556,'\xe2':556,'\xe3':556,'\xe4':556,'\xe5':556,'\xe6':889,'\xe7':500,'\xe8':556,'\xe9':556,'\xea':556,'\xeb':556,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':556,'\xf1':556, 13 | '\xf2':556,'\xf3':556,'\xf4':556,'\xf5':556,'\xf6':556,'\xf7':584,'\xf8':611,'\xf9':556,'\xfa':556,'\xfb':556,'\xfc':556,'\xfd':500,'\xfe':556,'\xff':500} 14 | -------------------------------------------------------------------------------- /attic/font/helveticabi.py: -------------------------------------------------------------------------------- 1 | fpdf_charwidths['helveticaBI']={ 2 | '\x00':278,'\x01':278,'\x02':278,'\x03':278,'\x04':278,'\x05':278,'\x06':278,'\x07':278,'\x08':278,'\t':278,'\n':278,'\x0b':278,'\x0c':278,'\r':278,'\x0e':278,'\x0f':278,'\x10':278,'\x11':278,'\x12':278,'\x13':278,'\x14':278,'\x15':278, 3 | '\x16':278,'\x17':278,'\x18':278,'\x19':278,'\x1a':278,'\x1b':278,'\x1c':278,'\x1d':278,'\x1e':278,'\x1f':278,' ':278,'!':333,'"':474,'#':556,'$':556,'%':889,'&':722,'\'':238,'(':333,')':333,'*':389,'+':584, 4 | ',':278,'-':333,'.':278,'/':278,'0':556,'1':556,'2':556,'3':556,'4':556,'5':556,'6':556,'7':556,'8':556,'9':556,':':333,';':333,'<':584,'=':584,'>':584,'?':611,'@':975,'A':722, 5 | 'B':722,'C':722,'D':722,'E':667,'F':611,'G':778,'H':722,'I':278,'J':556,'K':722,'L':611,'M':833,'N':722,'O':778,'P':667,'Q':778,'R':722,'S':667,'T':611,'U':722,'V':667,'W':944, 6 | 'X':667,'Y':667,'Z':611,'[':333,'\\':278,']':333,'^':584,'_':556,'`':333,'a':556,'b':611,'c':556,'d':611,'e':556,'f':333,'g':611,'h':611,'i':278,'j':278,'k':556,'l':278,'m':889, 7 | 'n':611,'o':611,'p':611,'q':611,'r':389,'s':556,'t':333,'u':611,'v':556,'w':778,'x':556,'y':556,'z':500,'{':389,'|':280,'}':389,'~':584,'\x7f':350,'\x80':556,'\x81':350,'\x82':278,'\x83':556, 8 | '\x84':500,'\x85':1000,'\x86':556,'\x87':556,'\x88':333,'\x89':1000,'\x8a':667,'\x8b':333,'\x8c':1000,'\x8d':350,'\x8e':611,'\x8f':350,'\x90':350,'\x91':278,'\x92':278,'\x93':500,'\x94':500,'\x95':350,'\x96':556,'\x97':1000,'\x98':333,'\x99':1000, 9 | '\x9a':556,'\x9b':333,'\x9c':944,'\x9d':350,'\x9e':500,'\x9f':667,'\xa0':278,'\xa1':333,'\xa2':556,'\xa3':556,'\xa4':556,'\xa5':556,'\xa6':280,'\xa7':556,'\xa8':333,'\xa9':737,'\xaa':370,'\xab':556,'\xac':584,'\xad':333,'\xae':737,'\xaf':333, 10 | '\xb0':400,'\xb1':584,'\xb2':333,'\xb3':333,'\xb4':333,'\xb5':611,'\xb6':556,'\xb7':278,'\xb8':333,'\xb9':333,'\xba':365,'\xbb':556,'\xbc':834,'\xbd':834,'\xbe':834,'\xbf':611,'\xc0':722,'\xc1':722,'\xc2':722,'\xc3':722,'\xc4':722,'\xc5':722, 11 | '\xc6':1000,'\xc7':722,'\xc8':667,'\xc9':667,'\xca':667,'\xcb':667,'\xcc':278,'\xcd':278,'\xce':278,'\xcf':278,'\xd0':722,'\xd1':722,'\xd2':778,'\xd3':778,'\xd4':778,'\xd5':778,'\xd6':778,'\xd7':584,'\xd8':778,'\xd9':722,'\xda':722,'\xdb':722, 12 | '\xdc':722,'\xdd':667,'\xde':667,'\xdf':611,'\xe0':556,'\xe1':556,'\xe2':556,'\xe3':556,'\xe4':556,'\xe5':556,'\xe6':889,'\xe7':556,'\xe8':556,'\xe9':556,'\xea':556,'\xeb':556,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':611,'\xf1':611, 13 | '\xf2':611,'\xf3':611,'\xf4':611,'\xf5':611,'\xf6':611,'\xf7':584,'\xf8':611,'\xf9':611,'\xfa':611,'\xfb':611,'\xfc':611,'\xfd':556,'\xfe':611,'\xff':556} -------------------------------------------------------------------------------- /attic/font/helveticai.py: -------------------------------------------------------------------------------- 1 | fpdf_charwidths['helveticaI']={ 2 | '\x00':278,'\x01':278,'\x02':278,'\x03':278,'\x04':278,'\x05':278,'\x06':278,'\x07':278,'\x08':278,'\t':278,'\n':278,'\x0b':278,'\x0c':278,'\r':278,'\x0e':278,'\x0f':278,'\x10':278,'\x11':278,'\x12':278,'\x13':278,'\x14':278,'\x15':278, 3 | '\x16':278,'\x17':278,'\x18':278,'\x19':278,'\x1a':278,'\x1b':278,'\x1c':278,'\x1d':278,'\x1e':278,'\x1f':278,' ':278,'!':278,'"':355,'#':556,'$':556,'%':889,'&':667,'\'':191,'(':333,')':333,'*':389,'+':584, 4 | ',':278,'-':333,'.':278,'/':278,'0':556,'1':556,'2':556,'3':556,'4':556,'5':556,'6':556,'7':556,'8':556,'9':556,':':278,';':278,'<':584,'=':584,'>':584,'?':556,'@':1015,'A':667, 5 | 'B':667,'C':722,'D':722,'E':667,'F':611,'G':778,'H':722,'I':278,'J':500,'K':667,'L':556,'M':833,'N':722,'O':778,'P':667,'Q':778,'R':722,'S':667,'T':611,'U':722,'V':667,'W':944, 6 | 'X':667,'Y':667,'Z':611,'[':278,'\\':278,']':278,'^':469,'_':556,'`':333,'a':556,'b':556,'c':500,'d':556,'e':556,'f':278,'g':556,'h':556,'i':222,'j':222,'k':500,'l':222,'m':833, 7 | 'n':556,'o':556,'p':556,'q':556,'r':333,'s':500,'t':278,'u':556,'v':500,'w':722,'x':500,'y':500,'z':500,'{':334,'|':260,'}':334,'~':584,'\x7f':350,'\x80':556,'\x81':350,'\x82':222,'\x83':556, 8 | '\x84':333,'\x85':1000,'\x86':556,'\x87':556,'\x88':333,'\x89':1000,'\x8a':667,'\x8b':333,'\x8c':1000,'\x8d':350,'\x8e':611,'\x8f':350,'\x90':350,'\x91':222,'\x92':222,'\x93':333,'\x94':333,'\x95':350,'\x96':556,'\x97':1000,'\x98':333,'\x99':1000, 9 | '\x9a':500,'\x9b':333,'\x9c':944,'\x9d':350,'\x9e':500,'\x9f':667,'\xa0':278,'\xa1':333,'\xa2':556,'\xa3':556,'\xa4':556,'\xa5':556,'\xa6':260,'\xa7':556,'\xa8':333,'\xa9':737,'\xaa':370,'\xab':556,'\xac':584,'\xad':333,'\xae':737,'\xaf':333, 10 | '\xb0':400,'\xb1':584,'\xb2':333,'\xb3':333,'\xb4':333,'\xb5':556,'\xb6':537,'\xb7':278,'\xb8':333,'\xb9':333,'\xba':365,'\xbb':556,'\xbc':834,'\xbd':834,'\xbe':834,'\xbf':611,'\xc0':667,'\xc1':667,'\xc2':667,'\xc3':667,'\xc4':667,'\xc5':667, 11 | '\xc6':1000,'\xc7':722,'\xc8':667,'\xc9':667,'\xca':667,'\xcb':667,'\xcc':278,'\xcd':278,'\xce':278,'\xcf':278,'\xd0':722,'\xd1':722,'\xd2':778,'\xd3':778,'\xd4':778,'\xd5':778,'\xd6':778,'\xd7':584,'\xd8':778,'\xd9':722,'\xda':722,'\xdb':722, 12 | '\xdc':722,'\xdd':667,'\xde':667,'\xdf':611,'\xe0':556,'\xe1':556,'\xe2':556,'\xe3':556,'\xe4':556,'\xe5':556,'\xe6':889,'\xe7':500,'\xe8':556,'\xe9':556,'\xea':556,'\xeb':556,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':556,'\xf1':556, 13 | '\xf2':556,'\xf3':556,'\xf4':556,'\xf5':556,'\xf6':556,'\xf7':584,'\xf8':611,'\xf9':556,'\xfa':556,'\xfb':556,'\xfc':556,'\xfd':500,'\xfe':556,'\xff':500} -------------------------------------------------------------------------------- /attic/font/helveticab.py: -------------------------------------------------------------------------------- 1 | fpdf_charwidths['helveticaB']={ 2 | '\x00':278,'\x01':278,'\x02':278,'\x03':278,'\x04':278,'\x05':278,'\x06':278,'\x07':278,'\x08':278,'\t':278,'\n':278,'\x0b':278,'\x0c':278,'\r':278,'\x0e':278,'\x0f':278,'\x10':278,'\x11':278,'\x12':278,'\x13':278,'\x14':278,'\x15':278, 3 | '\x16':278,'\x17':278,'\x18':278,'\x19':278,'\x1a':278,'\x1b':278,'\x1c':278,'\x1d':278,'\x1e':278,'\x1f':278,' ':278,'!':333,'"':474,'#':556,'$':556,'%':889,'&':722,'\'':238,'(':333,')':333,'*':389,'+':584, 4 | ',':278,'-':333,'.':278,'/':278,'0':556,'1':556,'2':556,'3':556,'4':556,'5':556,'6':556,'7':556,'8':556,'9':556,':':333,';':333,'<':584,'=':584,'>':584,'?':611,'@':975,'A':722, 5 | 'B':722,'C':722,'D':722,'E':667,'F':611,'G':778,'H':722,'I':278,'J':556,'K':722,'L':611,'M':833,'N':722,'O':778,'P':667,'Q':778,'R':722,'S':667,'T':611,'U':722,'V':667,'W':944, 6 | 'X':667,'Y':667,'Z':611,'[':333,'\\':278,']':333,'^':584,'_':556,'`':333,'a':556,'b':611,'c':556,'d':611,'e':556,'f':333,'g':611,'h':611,'i':278,'j':278,'k':556,'l':278,'m':889, 7 | 'n':611,'o':611,'p':611,'q':611,'r':389,'s':556,'t':333,'u':611,'v':556,'w':778,'x':556,'y':556,'z':500,'{':389,'|':280,'}':389,'~':584,'\x7f':350,'\x80':556,'\x81':350,'\x82':278,'\x83':556, 8 | '\x84':500,'\x85':1000,'\x86':556,'\x87':556,'\x88':333,'\x89':1000,'\x8a':667,'\x8b':333,'\x8c':1000,'\x8d':350,'\x8e':611,'\x8f':350,'\x90':350,'\x91':278,'\x92':278,'\x93':500,'\x94':500,'\x95':350,'\x96':556,'\x97':1000,'\x98':333,'\x99':1000, 9 | '\x9a':556,'\x9b':333,'\x9c':944,'\x9d':350,'\x9e':500,'\x9f':667,'\xa0':278,'\xa1':333,'\xa2':556,'\xa3':556,'\xa4':556,'\xa5':556,'\xa6':280,'\xa7':556,'\xa8':333,'\xa9':737,'\xaa':370,'\xab':556,'\xac':584,'\xad':333,'\xae':737,'\xaf':333, 10 | '\xb0':400,'\xb1':584,'\xb2':333,'\xb3':333,'\xb4':333,'\xb5':611,'\xb6':556,'\xb7':278,'\xb8':333,'\xb9':333,'\xba':365,'\xbb':556,'\xbc':834,'\xbd':834,'\xbe':834,'\xbf':611,'\xc0':722,'\xc1':722,'\xc2':722,'\xc3':722,'\xc4':722,'\xc5':722, 11 | '\xc6':1000,'\xc7':722,'\xc8':667,'\xc9':667,'\xca':667,'\xcb':667,'\xcc':278,'\xcd':278,'\xce':278,'\xcf':278,'\xd0':722,'\xd1':722,'\xd2':778,'\xd3':778,'\xd4':778,'\xd5':778,'\xd6':778,'\xd7':584,'\xd8':778,'\xd9':722,'\xda':722,'\xdb':722, 12 | '\xdc':722,'\xdd':667,'\xde':667,'\xdf':611,'\xe0':556,'\xe1':556,'\xe2':556,'\xe3':556,'\xe4':556,'\xe5':556,'\xe6':889,'\xe7':556,'\xe8':556,'\xe9':556,'\xea':556,'\xeb':556,'\xec':278,'\xed':278,'\xee':278,'\xef':278,'\xf0':611,'\xf1':611, 13 | '\xf2':611,'\xf3':611,'\xf4':611,'\xf5':611,'\xf6':611,'\xf7':584,'\xf8':611,'\xf9':611,'\xfa':611,'\xfb':611,'\xfc':611,'\xfd':556,'\xfe':611,'\xff':556 14 | } 15 | -------------------------------------------------------------------------------- /docs/reference/cell.md: -------------------------------------------------------------------------------- 1 | ## cell ## 2 | 3 | ```python 4 | fpdf.cell(w, h = 0, txt = '', border = 0, ln = 0, 5 | align = '', fill = False, link = '') 6 | ``` 7 | 8 | ### Description ### 9 | 10 | Prints a cell (rectangular area) with optional borders, background color and 11 | character string. The upper-left corner of the cell corresponds to the current 12 | position. The text can be aligned or centered. After the call, the current 13 | position moves to the right or to the next line. It is possible to put a link 14 | on the text. 15 | 16 | If automatic page breaking is enabled and the cell goes beyond the limit, a 17 | page break is done before outputting. 18 | 19 | ### Parameters ### 20 | 21 | w: 22 | > Cell width. If 0, the cell extends up to the right margin. 23 | 24 | h: 25 | > Cell height. Default value: 0. 26 | 27 | txt: 28 | > String to print. Default value: empty string. 29 | 30 | border: 31 | > Indicates if borders must be drawn around the cell. The value can be either a 32 | number: 33 | >> * 0: no border 34 | >> * 1: frame 35 | > 36 | > or a string containing some or all of the following characters (in any order): 37 | >> * `L`: left 38 | >> * `T`: top 39 | >> * `R`: right 40 | >> * `B`: bottom 41 | > 42 | > Default value: 0. 43 | 44 | ln: 45 | > Indicates where the current position should go after the call. Possible 46 | values are: 47 | >> * 0: to the right 48 | >> * 1: to the beginning of the next line 49 | >> * 2: below 50 | > 51 | > Putting 1 is equivalent to putting 0 and calling [ln](ln.md) just after. 52 | Default value: 0. 53 | 54 | align: 55 | > Allows to center or align the text. Possible values are: 56 | >> * `L` or empty string: left align (default value) 57 | >> * `C`: center 58 | >> * `R`: right align 59 | 60 | fill: 61 | > Indicates if the cell background must be painted (`True`) or transparent 62 | (`False`). Default value: False. 63 | 64 | link: 65 | > URL or identifier returned by [add_link](add_link.md). 66 | 67 | ### Example ### 68 | 69 | ```python 70 | # Set font 71 | pdf.set_font('Arial', 'B', 16) 72 | # Move to 8 cm to the right 73 | pdf.cell(80) 74 | # Centered text in a framed 20*10 mm cell and line break 75 | pdf.cell(20, 10, 'Title', 1, 1, 'C') 76 | ``` 77 | 78 | ### See also ### 79 | 80 | [set_font](set_font.md), [set_doc_option](set_doc_option.md), 81 | [set_draw_color](set_draw_color.md), [set_fill_color](set_fill_color.md), 82 | [set_text_color](set_text_color.md), [set_line_width](set_line_width.md), 83 | [add_link](add_link.md), [ln](ln.md), [multi_cell](multi_cell.md), 84 | [write](write.md), [set_auto_page_break](set_auto_page_break.md). 85 | -------------------------------------------------------------------------------- /attic/font/zapfdingbats.py: -------------------------------------------------------------------------------- 1 | 0,'\x01'=>0,'\x02'=>0,'\x03'=>0,'\x04'=>0,'\x05'=>0,'\x06'=>0,'\x07'=>0,'\x08'=>0,'\t'=>0,'\n'=>0,'\x0b'=>0,'\x0c'=>0,'\r'=>0,'\x0e'=>0,'\x0f'=>0,'\x10'=>0,'\x11'=>0,'\x12'=>0,'\x13'=>0,'\x14'=>0,'\x15'=>0, 4 | '\x16'=>0,'\x17'=>0,'\x18'=>0,'\x19'=>0,'\x1a'=>0,'\x1b'=>0,'\x1c'=>0,'\x1d'=>0,'\x1e'=>0,'\x1f'=>0,' '=>278,'!'=>974,'"'=>961,'#'=>974,'$'=>980,'%'=>719,'&'=>789,'\''=>790,'('=>791,')'=>690,'*'=>960,'+'=>939, 5 | ','=>549,'-'=>855,'.'=>911,'/'=>933,'0'=>911,'1'=>945,'2'=>974,'3'=>755,'4'=>846,'5'=>762,'6'=>761,'7'=>571,'8'=>677,'9'=>763,':'=>760,';'=>759,'<'=>754,'='=>494,'>'=>552,'?'=>537,'@'=>577,'A'=>692, 6 | 'B'=>786,'C'=>788,'D'=>788,'E'=>790,'F'=>793,'G'=>794,'H'=>816,'I'=>823,'J'=>789,'K'=>841,'L'=>823,'M'=>833,'N'=>816,'O'=>831,'P'=>923,'Q'=>744,'R'=>723,'S'=>749,'T'=>790,'U'=>792,'V'=>695,'W'=>776, 7 | 'X'=>768,'Y'=>792,'Z'=>759,'['=>707,'\\'=>708,']'=>682,'^'=>701,'_'=>826,'`'=>815,'a'=>789,'b'=>789,'c'=>707,'d'=>687,'e'=>696,'f'=>689,'g'=>786,'h'=>787,'i'=>713,'j'=>791,'k'=>785,'l'=>791,'m'=>873, 8 | 'n'=>761,'o'=>762,'p'=>762,'q'=>759,'r'=>759,'s'=>892,'t'=>892,'u'=>788,'v'=>784,'w'=>438,'x'=>138,'y'=>277,'z'=>415,'{'=>392,'|'=>392,'}'=>668,'~'=>668,'\x7f'=>0,'\x80'=>390,'\x81'=>390,'\x82'=>317,'\x83'=>317, 9 | '\x84'=>276,'\x85'=>276,'\x86'=>509,'\x87'=>509,'\x88'=>410,'\x89'=>410,'\x8a'=>234,'\x8b'=>234,'\x8c'=>334,'\x8d'=>334,'\x8e'=>0,'\x8f'=>0,'\x90'=>0,'\x91'=>0,'\x92'=>0,'\x93'=>0,'\x94'=>0,'\x95'=>0,'\x96'=>0,'\x97'=>0,'\x98'=>0,'\x99'=>0, 10 | '\x9a'=>0,'\x9b'=>0,'\x9c'=>0,'\x9d'=>0,'\x9e'=>0,'\x9f'=>0,'\xa0'=>0,'\xa1'=>732,'\xa2'=>544,'\xa3'=>544,'\xa4'=>910,'\xa5'=>667,'\xa6'=>760,'\xa7'=>760,'\xa8'=>776,'\xa9'=>595,'\xaa'=>694,'\xab'=>626,'\xac'=>788,'\xad'=>788,'\xae'=>788,'\xaf'=>788, 11 | '\xb0'=>788,'\xb1'=>788,'\xb2'=>788,'\xb3'=>788,'\xb4'=>788,'\xb5'=>788,'\xb6'=>788,'\xb7'=>788,'\xb8'=>788,'\xb9'=>788,'\xba'=>788,'\xbb'=>788,'\xbc'=>788,'\xbd'=>788,'\xbe'=>788,'\xbf'=>788,'\xc0'=>788,'\xc1'=>788,'\xc2'=>788,'\xc3'=>788,'\xc4'=>788,'\xc5'=>788, 12 | '\xc6'=>788,'\xc7'=>788,'\xc8'=>788,'\xc9'=>788,'\xca'=>788,'\xcb'=>788,'\xcc'=>788,'\xcd'=>788,'\xce'=>788,'\xcf'=>788,'\xd0'=>788,'\xd1'=>788,'\xd2'=>788,'\xd3'=>788,'\xd4'=>894,'\xd5'=>838,'\xd6'=>1016,'\xd7'=>458,'\xd8'=>748,'\xd9'=>924,'\xda'=>748,'\xdb'=>918, 13 | '\xdc'=>927,'\xdd'=>928,'\xde'=>928,'\xdf'=>834,'\xe0'=>873,'\xe1'=>828,'\xe2'=>924,'\xe3'=>924,'\xe4'=>917,'\xe5'=>930,'\xe6'=>931,'\xe7'=>463,'\xe8'=>883,'\xe9'=>836,'\xea'=>836,'\xeb'=>867,'\xec'=>867,'\xed'=>696,'\xee'=>696,'\xef'=>874,'\xf0'=>0,'\xf1'=>874, 14 | '\xf2'=>760,'\xf3'=>946,'\xf4'=>771,'\xf5'=>865,'\xf6'=>771,'\xf7'=>888,'\xf8'=>967,'\xf9'=>888,'\xfa'=>831,'\xfb'=>873,'\xfc'=>927,'\xfd'=>970,'\xfe'=>918,'\xff'=>0); 15 | ?> 16 | -------------------------------------------------------------------------------- /tutorial/tuto5.py: -------------------------------------------------------------------------------- 1 | from __future__ import with_statement 2 | 3 | from fpdf import * 4 | 5 | class PDF(FPDF): 6 | # Load data 7 | def load_data(self, name): 8 | # Read file lines 9 | data = [] 10 | with open(name) as file: 11 | for line in file: 12 | data += [line[:-1].split(';')] 13 | return data 14 | 15 | # Simple table 16 | def basic_table(self, header, data): 17 | # Header 18 | for col in header: 19 | self.cell(40, 7, col, 1) 20 | self.ln() 21 | # Data 22 | for row in data: 23 | for col in row: 24 | self.cell(40, 6, col, 1) 25 | self.ln() 26 | 27 | # Better table 28 | def improved_table(self, header, data): 29 | # Column widths 30 | w = [40, 35, 40, 45] 31 | # Header 32 | for i in range(0, len(header)): 33 | self.cell(w[i], 7, header[i], 1, 0, 'C') 34 | self.ln() 35 | # Data 36 | for row in data: 37 | self.cell(w[0], 6, row[0], 'LR') 38 | self.cell(w[1], 6, row[1], 'LR') 39 | self.cell(w[2], 6, row[2], 'LR', 0, 'R') 40 | self.cell(w[3], 6, row[3], 'LR', 0, 'R') 41 | self.ln() 42 | # Closure line 43 | self.cell(sum(w), 0, '', 'T') 44 | 45 | # Colored table 46 | def fancy_table(self, header, data): 47 | # Colors, line width and bold font 48 | self.set_fill_color(255, 0, 0) 49 | self.set_text_color(255) 50 | self.set_draw_color(128, 0, 0) 51 | self.set_line_width(0.3) 52 | self.set_font('', 'B') 53 | # Header 54 | w = [40, 35, 40, 45] 55 | for i in range(0, len(header)): 56 | self.cell(w[i], 7, header[i], 1, 0, 'C', 1) 57 | self.ln() 58 | # Color and font restoration 59 | self.set_fill_color(224, 235, 255) 60 | self.set_text_color(0) 61 | self.set_font('') 62 | # Data 63 | fill=0 64 | for row in data: 65 | self.cell(w[0], 6, row[0], 'LR', 0, 'L', fill) 66 | self.cell(w[1], 6, row[1], 'LR', 0, 'L', fill) 67 | self.cell(w[2], 6, row[2], 'LR', 0, 'R', fill) 68 | self.cell(w[3], 6, row[3], 'LR', 0, 'R', fill) 69 | self.ln() 70 | fill = not fill 71 | self.cell(sum(w), 0, '', 'T') 72 | 73 | pdf = PDF() 74 | # Column titles 75 | header = ['Country', 'Capital', 'Area (sq km)', 'Pop. (thousands)'] 76 | # Data loading 77 | data = pdf.load_data('countries.txt') 78 | pdf.set_font('Arial', '', 14) 79 | pdf.add_page() 80 | pdf.basic_table(header, data) 81 | pdf.add_page() 82 | pdf.improved_table(header, data) 83 | pdf.add_page() 84 | pdf.fancy_table(header, data) 85 | pdf.output('tuto5.pdf', 'F') 86 | 87 | -------------------------------------------------------------------------------- /attic/font/calligra.py: -------------------------------------------------------------------------------- 1 | 2 | type='TrueType' 3 | name='Calligrapher-Regular' 4 | desc={'Ascent':899,'Descent':-234,'CapHeight':731,'Flags':32,'FontBBox':'[-50 -234 1328 899]','ItalicAngle':0,'StemV':70,'MissingWidth':800} 5 | up=-200 6 | ut=20 7 | cw={ 8 | '\x00':800,'\x01':800,'\x02':800,'\x03':800,'\x04':800,'\x05':800,'\x06':800,'\x07':800,'\x08':800,'\t':800,'\n':800,'\x0b':800,'\x0c':800,'\r':800,'\x0e':800,'\x0f':800,'\x10':800,'\x11':800,'\x12':800,'\x13':800,'\x14':800,'\x15':800, 9 | '\x16':800,'\x17':800,'\x18':800,'\x19':800,'\x1a':800,'\x1b':800,'\x1c':800,'\x1d':800,'\x1e':800,'\x1f':800,' ':282,'!':324,'"':405,'#':584,'$':632,'%':980,'&':776,'\'':259,'(':299,')':299,'*':377,'+':600, 10 | ',':259,'-':432,'.':254,'/':597,'0':529,'1':298,'2':451,'3':359,'4':525,'5':423,'6':464,'7':417,'8':457,'9':479,':':275,';':282,'<':600,'=':600,'>':600,'?':501,'@':800,'A':743, 11 | 'B':636,'C':598,'D':712,'E':608,'F':562,'G':680,'H':756,'I':308,'J':314,'K':676,'L':552,'M':1041,'N':817,'O':729,'P':569,'Q':698,'R':674,'S':618,'T':673,'U':805,'V':753,'W':1238, 12 | 'X':716,'Y':754,'Z':599,'[':315,'\\':463,']':315,'^':600,'_':547,'`':278,'a':581,'b':564,'c':440,'d':571,'e':450,'f':347,'g':628,'h':611,'i':283,'j':283,'k':560,'l':252,'m':976, 13 | 'n':595,'o':508,'p':549,'q':540,'r':395,'s':441,'t':307,'u':614,'v':556,'w':915,'x':559,'y':597,'z':452,'{':315,'|':222,'}':315,'~':600,'\x7f':800,'\x80':800,'\x81':800,'\x82':0,'\x83':0, 14 | '\x84':0,'\x85':780,'\x86':0,'\x87':0,'\x88':278,'\x89':0,'\x8a':0,'\x8b':0,'\x8c':1064,'\x8d':800,'\x8e':800,'\x8f':800,'\x90':800,'\x91':259,'\x92':259,'\x93':470,'\x94':470,'\x95':500,'\x96':300,'\x97':600,'\x98':278,'\x99':990, 15 | '\x9a':0,'\x9b':0,'\x9c':790,'\x9d':800,'\x9e':800,'\x9f':754,'\xa0':282,'\xa1':324,'\xa2':450,'\xa3':640,'\xa4':518,'\xa5':603,'\xa6':0,'\xa7':519,'\xa8':254,'\xa9':800,'\xaa':349,'\xab':0,'\xac':0,'\xad':432,'\xae':800,'\xaf':278, 16 | '\xb0':0,'\xb1':0,'\xb2':0,'\xb3':0,'\xb4':278,'\xb5':614,'\xb6':0,'\xb7':254,'\xb8':278,'\xb9':0,'\xba':305,'\xbb':0,'\xbc':0,'\xbd':0,'\xbe':0,'\xbf':501,'\xc0':743,'\xc1':743,'\xc2':743,'\xc3':743,'\xc4':743,'\xc5':743, 17 | '\xc6':1060,'\xc7':598,'\xc8':608,'\xc9':608,'\xca':608,'\xcb':608,'\xcc':308,'\xcd':308,'\xce':308,'\xcf':308,'\xd0':0,'\xd1':817,'\xd2':729,'\xd3':729,'\xd4':729,'\xd5':729,'\xd6':729,'\xd7':0,'\xd8':729,'\xd9':805,'\xda':805,'\xdb':805, 18 | '\xdc':805,'\xdd':0,'\xde':0,'\xdf':688,'\xe0':581,'\xe1':581,'\xe2':581,'\xe3':581,'\xe4':581,'\xe5':581,'\xe6':792,'\xe7':440,'\xe8':450,'\xe9':450,'\xea':450,'\xeb':450,'\xec':283,'\xed':283,'\xee':283,'\xef':283,'\xf0':800,'\xf1':595, 19 | '\xf2':508,'\xf3':508,'\xf4':508,'\xf5':508,'\xf6':508,'\xf7':0,'\xf8':508,'\xf9':614,'\xfa':614,'\xfb':614,'\xfc':614,'\xfd':0,'\xfe':0,'\xff':597} 20 | enc='cp1252' 21 | diff='' 22 | filename='calligra.z' 23 | originalsize=40120 24 | 25 | -------------------------------------------------------------------------------- /docs/reference/write_html.md: -------------------------------------------------------------------------------- 1 | ## write_html ## 2 | 3 | ```python 4 | HTMLMixin.write_html(text: str, image_map = None) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | PyFPDF supports basic HTML, mainly intended to write reports from web frameworks. 10 | 11 | It understands a limited subset of the HTML language, and it doesn't support advanced features nor CSS (look below). 12 | 13 | HTMLMixin could be used along with FPDF class to implement this functionality (see the example). 14 | 15 | Sample: [html.pdf](http://pyfpdf.googlecode.com/files/html.pdf) 16 | 17 | ### Parameters ### 18 | 19 | test: 20 | > string with HTML markup 21 | 22 | image_map: 23 | > dictionary with image map 24 | 25 | ### Details ### 26 | 27 | HTML tags and attributes supported: 28 | 29 | * H1 to H8: headings (align attribute) 30 | * P: paragraphs (align attributes) 31 | * B, I, U: bold, italic, underline 32 | * FONT: (face, size, color attributes) 33 | * CENTER for aligning 34 | * A: links (href attribute) 35 | * IMG: images (src, width, height attributes) 36 | * OL, UL, LI: ordered, unordered and list items (can be nested) 37 | * TABLE: (border, width attributes) 38 | * THEAD: header (opens each page) 39 | * TFOOT: footer (closes each page) 40 | * TBODY: actual rows 41 | * TR: rows (bgcolor attribute) 42 | * TH: highlight cells (align, bgcolor, width attributes) 43 | * TD: rows (align, bgcolor, width attributes) 44 | 45 | Note: Tables should have at least a first TH row with a width attribute. 46 | 47 | ### Example ### 48 | 49 | ```python 50 | html = """ 51 |

html2fpdf

52 |

Basic usage

53 |

You can now easily print text mixing different 54 | styles : bold, italic, underlined, or 55 | all at once!
You can also insert links 56 | on text, such as www.fpdf.org, 57 | or on an image: click on the logo.
58 |

59 | 60 |
61 |

Sample List

62 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
Header 1header 2
cell 1cell 2
cell 2cell 3
73 | """ 74 | 75 | from pyfpdf import FPDF, HTMLMixin 76 | 77 | class MyFPDF(FPDF, HTMLMixin): 78 | pass 79 | 80 | pdf = MyFPDF() 81 | #First page 82 | pdf.add_page() 83 | pdf.write_html(html) 84 | pdf.output('html.pdf', 'F') 85 | ``` 86 | See html.py or [Web2Py](../Web2Py.md) for a complete example. 87 | 88 | ### See also ### 89 | [write](write.md), [add_font](add_font.md), [image](image.md). 90 | 91 | -------------------------------------------------------------------------------- /docs/reference/add_font.md: -------------------------------------------------------------------------------- 1 | ## add_font ## 2 | 3 | ```python 4 | fpdf.add_font(family: str, style = '', fname = '', uni = False) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Imports a TrueType, OpenType or Type1 font and makes it available. 10 | 11 | **Warning:** for Type1 and legacy fonts it is necessary to generate a font definition file first with the `MakeFont` utility. This feature is currently deprecated in favour of TrueType Unicode font support (whose fonts are automatically processed with the included `ttfonts.py` utility). 12 | 13 | **Note**: the font source files must be accessible. They are searched successively in (if these constants are defined): 14 | 15 | * `FPDF_FONTPATH` (by default, the `font` folder in the fpdf package directory) 16 | * `SYSTEM_TTFONTS` (e.g. `C:\WINDOWS\FONTS`) 17 | 18 | If the file corresponding to the requested font is not found, the runtime exception "TTF Font file not found: ..." is raised. 19 | 20 | For more information, see the [Unicode](../Unicode.md) support page. 21 | 22 | This method should be called before the [set_font](set_font.md) method is used, and the font will be available for the whole document. 23 | 24 | **Note**: due to the fact that font processing can occupy large amount of time, some data are cached. 25 | 26 | Cache files are created in same folder by default. This can be changed by setting the `FPDF_CACHE_MODE` constant: 27 | 28 | * 0 - (by default), store the cache in the same folder as the font file 29 | * 1 - disable all caching 30 | * 2 - store cache files in the `FPDF_CACHE_DIR` directory with cryptic names 31 | 32 | ### Parameters ### 33 | 34 | family: 35 | > Font family. Used as a reference for [set_font](set_font.md), for example: `'dejavu'`. 36 | 37 | style: 38 | > Font style. Deprecated, maintained only for backward compatibility. 39 | 40 | fname: 41 | > Font file name (e.g. `'DejaVuSansCondensed.ttf'`). You can specify a full path; if not, the file will be searched in `FPDF_FONTPATH` or `SYSTEM_TTFONTS`. 42 | 43 | uni: 44 | > TTF Unicode flag (if set to `True`, TrueType font subset embedding will be enabled and text will be treated as `utf8` by default). 45 | 46 | You must _not_ call _add_font_ for the standard PDF Latin-1 fonts (Courier, Helvetica, Times, Symbol, Zapfdingbats); use [set_font](set_font.md) directly in that case. 47 | 48 | Calling this method with uni=False is discouraged as legacy font support is complex and deprecated. 49 | 50 | 51 | ### Example ### 52 | 53 | ```python 54 | # Add a Unicode free font 55 | pdf.add_font('DejaVu', '', 'DejaVuSansCondensed.ttf', uni=True) 56 | 57 | # Add a Unicode system font (using full path) 58 | pdf.add_font('sysfont', '', r"c:\WINDOWS\Fonts\arial.ttf", uni=True) 59 | ``` 60 | 61 | ### See also ### 62 | 63 | [set_font](set_font.md), [set_font_size](set_font_size.md), [cell](cell.md), [multi_cell](multi_cell.md), [write](write.md). 64 | -------------------------------------------------------------------------------- /tutorial/tuto4.py: -------------------------------------------------------------------------------- 1 | from __future__ import with_statement 2 | 3 | from fpdf import * 4 | 5 | class PDF(FPDF): 6 | # Current column 7 | col = 0 8 | # Ordinate of column start 9 | y0 = 0 10 | 11 | def header(self): 12 | # Page header 13 | self.set_font('Arial', 'B', 15) 14 | w = self.get_string_width(title) + 6 15 | self.set_x((210 - w) / 2.0) 16 | self.set_draw_color(0, 80, 180) 17 | self.set_fill_color(230, 230, 0) 18 | self.set_text_color(220, 50, 50) 19 | self.set_line_width(1) 20 | self.cell(w, 9, title, 1, 1, 'C', 1) 21 | self.ln(10) 22 | # Save ordinate 23 | self.y0 = self.get_y() 24 | 25 | def footer(self): 26 | # Page footer 27 | self.set_y(-15) 28 | self.set_font('Arial', 'I', 8) 29 | self.set_text_color(128) 30 | self.cell(0, 10, 'Page ' + str(self.page_no()), 0, 0, 'C') 31 | 32 | def set_col(self, col): 33 | # Set position at a given column 34 | self.col = col 35 | x=10 + col * 65.0 36 | self.set_left_margin(x) 37 | self.set_x(x) 38 | 39 | def accept_page_break(self): 40 | # Method accepting or not automatic page break 41 | if self.col < 2: 42 | # Go to next column 43 | self.set_col(self.col + 1) 44 | # Set ordinate to top 45 | self.set_y(self.y0) 46 | # Keep on page 47 | return 0 48 | else: 49 | # Go back to first column 50 | self.set_col(0) 51 | # Page break 52 | return 1 53 | 54 | def chapter_title(self, num, label): 55 | # Title 56 | self.set_font('Arial', '', 12) 57 | self.set_fill_color(200, 220, 255) 58 | self.cell(0, 6, 'Chapter %d : %s' % (num, label), 0, 1, 'L', 1) 59 | self.ln(4) 60 | # Save ordinate 61 | self.y0 = self.get_y() 62 | 63 | def chapter_body(self, name): 64 | # Read text file 65 | with open(name, 'rb') as fh: 66 | txt = fh.read().decode('latin-1') 67 | # Font 68 | self.set_font('Times', '', 12) 69 | # Output text in a 6 cm width column 70 | self.multi_cell(60, 5, txt) 71 | self.ln() 72 | # Mention 73 | self.set_font('', 'I') 74 | self.cell(0, 5, '(end of excerpt)') 75 | # Go back to first column 76 | self.set_col(0) 77 | 78 | def print_chapter(self, num, title, name): 79 | # Add chapter 80 | self.add_page() 81 | self.chapter_title(num, title) 82 | self.chapter_body(name) 83 | 84 | pdf = PDF() 85 | title = '20000 Leagues Under the Seas' 86 | pdf.set_title(title) 87 | pdf.set_author('Jules Verne') 88 | pdf.print_chapter(1, 'A RUNAWAY REEF','20k_c1.txt') 89 | pdf.print_chapter(2, 'THE PROS AND CONS','20k_c2.txt') 90 | pdf.output('tuto4.pdf', 'F') 91 | 92 | -------------------------------------------------------------------------------- /docs/Development.md: -------------------------------------------------------------------------------- 1 | # Development # 2 | 3 | [TOC] 4 | 5 | ## Introduction ## 6 | 7 | This page has summary information about developing the PyPDF library. 8 | 9 | This project started as Python fork of the [FPDF](http://fpdf.org/) PHP library. 10 | Later, code for native reading TTF fonts was added. FPDF has not been updated since 11 | 2011. See also the [TCPDF](http://www.tcpdf.org/) library. 12 | 13 | Until 2015 the code was developed at [Google Code](https://code.google.com/p/pyfpdf/). 14 | Now the main repository is at [Github](https://github.com/reingart/pyfpdf). 15 | 16 | You can also view the 17 | [old repository](https://github.com/reingart/pyfpdf_googlecode), 18 | [old issues](https://github.com/reingart/pyfpdf_googlecode/issues), and 19 | [old wiki](https://github.com/reingart/pyfpdf_googlecode/tree/wiki). 20 | 21 | After being committed to the master branch, code documentation is automatically uploaded to 22 | the [Read the Docs](http://pyfpdf.rtfd.org/) site. 23 | 24 | ## Repository structure ## 25 | 26 | * `[attic]` - folder with old code and useful, but unsupported things 27 | * `[docs]` - documenation folder 28 | * `[examples]` - some examples 29 | * `[fpdf]` - library source 30 | * `[test]` - test suite (see [Testing](Testing.md)) 31 | * `[tools]` - some utilities 32 | * `[tutorial]` - tutorials (see also [Tutorial](Tutorial.md)) 33 | * `LICENSE` - license information 34 | * `setup.cfg` - wheel configuration (see [wheel](https://wheel.rtfd.org)) 35 | * `setup.py` - distutils installer (see [Python Packaging User Guide](https://python-packaging-user-guide.rtfd.org)) 36 | * `mkdocs.yml` - config for [MkDocs](http://www.mkdocs.org/) 37 | 38 | ## Tips ## 39 | 40 | ### Code ### 41 | 42 | To get the master branch of the code: 43 | ```shell 44 | git clone https://github.com/reingart/pyfpdf.git 45 | ``` 46 | 47 | You can also use issues and pull requests at Github. 48 | 49 | ### Testing ### 50 | 51 | Testing described in the standalone page [Testing](Testing.md). 52 | 53 | ### Documentation ### 54 | 55 | Documentation is in the `docs` subfolder in 56 | [Markdown](http://daringfireball.net/projects/markdown/) format. To build it, 57 | the `mkdocs` utility is used, which is directed by `mkdocs.yml`. 58 | 59 | To build documentation, run in the repository root: 60 | 61 | ``` 62 | mkdocs build 63 | ``` 64 | HTML files are generated in a `html` subfolder. 65 | 66 | To continiously rebuild docs on changing any `.md` files use: 67 | 68 | ``` 69 | mkdocs serve 70 | ``` 71 | 72 | Then open a browser at . (The port and address can be changed.) 73 | 74 | **Note**: `mkdocs` internally checks the consistency of internal links. But somehow 75 | code like this: 76 | 77 | ``` 78 | [Page Name][refe/PageName,md] 79 | ``` 80 | 81 | leads to nowhere and gives no error. To avoid this use: 82 | 83 | ``` 84 | grep -r * -e ',md' 85 | ``` 86 | 87 | And output should link to this page only. 88 | 89 | ## See also ## 90 | [Project Home](index.md), [Frequently asked questions](FAQ.md), 91 | [Unicode](Unicode.md), [Python 3](Python3.md), [Testing](Testing.md). 92 | 93 | -------------------------------------------------------------------------------- /docs/reference/set_font.md: -------------------------------------------------------------------------------- 1 | ## set_font ## 2 | 3 | ```python 4 | fpdf.set_font(family, style = '', size = 0) 5 | ``` 6 | 7 | ### Description ### 8 | 9 | Sets the font used to print character strings. It is mandatory to call this 10 | method at least once before printing text or the resulting document would not 11 | be valid. 12 | 13 | The font can be either a standard one or a font added via the 14 | [add_font](add_font.md) method. 15 | 16 | Default encoding is not specified, but all text writing methods accept only 17 | unicode for external fonts and one byte encoding for standard. 18 | 19 | Standard fonts use `Latin-1` encoding by default, but Windows 20 | encoding `cp1252` (Western Europe) can be used with 21 | [set_doc_option](set_doc_option.md) ("core_fonts_encoding", encoding). 22 | 23 | The method can be called before the first page is created and the font is 24 | retained from page to page. 25 | 26 | If you just wish to change the current font size, it is simpler to call 27 | [set_font_size](set_font_size.md). 28 | 29 | **Note**: the font metric files must be accessible. They are searched 30 | successively in: 31 | 32 | * The directory defined by the FPDF\_FONTPATH constant (if this constant is 33 | defined) 34 | * The font directory located in the directory containing fpdf.py (if it 35 | exists) 36 | 37 | The directories accessible through include() 38 | Example defining FPDF_FONTPATH (note the mandatory trailing slash): 39 | define("FPDF_FONTPATH","/home/www/font/"); 40 | require("fpdf.php"); 41 | If the file corresponding to the requested font is not found, the error "Could 42 | not include font metric file" is issued. 43 | 44 | 45 | ### Parameters ### 46 | 47 | family: 48 | > Font family. It can be either a name defined by [add_font](add_font.md) or 49 | one of the standard families (case insensitive): 50 | >> * Courier (fixed-width) 51 | >> * Helvetica or Arial (synonymous; sans serif) 52 | >> * Times (serif) 53 | >> * Symbol (symbolic) 54 | >> * ZapfDingbats (symbolic) 55 | > 56 | > It is also possible to pass an empty string. In that case, the current 57 | family is retained. 58 | 59 | style: 60 | > Font style. Possible values are (case insensitive): 61 | >> * empty string: regular 62 | >> * B: bold 63 | >> * I: italic 64 | >> * U: underline 65 | > 66 | > or any combination. The default value is regular. Bold and italic styles do 67 | not apply to Symbol and ZapfDingbats. 68 | 69 | size: 70 | > Font size in points. 71 | > The default value is the current size. If no size has been specified since 72 | the beginning of the document, the value taken is 12. 73 | 74 | ### Example ### 75 | 76 | ```python 77 | # Times regular 12 78 | pdf.set_font('Times') 79 | # Arial bold 14 80 | pdf.set_font('Arial', 'B', 14) 81 | # Removes bold 82 | pdf.set_font('') 83 | # Times bold, italic and underlined 14 84 | pdf.set_font('Times', 'BIU') 85 | ``` 86 | 87 | ### See also ### 88 | 89 | [add_font](add_font.md), [set_doc_option](set_doc_option.md), 90 | [set_font_size](set_font_size.md), [cell](cell.md), 91 | [multi_cell](multi_cell.md), [write](write.md), 92 | [set_stretching](set_stretching.md). 93 | -------------------------------------------------------------------------------- /attic/utils/PDFRUUtils.py: -------------------------------------------------------------------------------- 1 | # Utilities to Re-Use PDF files generated by FPDF for Python 2 | # (Probably, more memory-wasting than it should) 3 | import re, zlib 4 | 5 | def UpdateStreamLengths(pdf): 6 | "Updates the streams /Length in a modified, uncompressed PDF file" 7 | L, Lengths=[],{} 8 | for m in re.finditer('<>)\nstream\n(.+?)\nendstream',pdf,re.S): 9 | oldlen, newlen = m.group(1), len(m.group(3)) 10 | if newlen!=oldlen: 11 | L+=[m.start(1)] 12 | # length_start=old_len, next_content 13 | Lengths[str(m.start(1))]=(str(newlen), m.start(2)) 14 | if not L: 15 | return pdf 16 | newpdf='' 17 | i=0 18 | for j in L: 19 | newpdf+=pdf[i:j] 20 | i=Lengths[str(j)][1] 21 | newpdf+=Lengths[str(j)][0] 22 | newpdf+=pdf[i:] 23 | return newpdf 24 | 25 | def FindXRefs(pdf): 26 | "Returns a dictionary of {PDF object:position} found" 27 | XRefs={} 28 | for m in re.finditer('^(\d+) 0 obj',pdf,re.M): 29 | XRefs[int(m.group(1))] = m.start() 30 | return XRefs 31 | 32 | def BuildXRefsTable(XRefs): 33 | "Constructs the PDF xref table from a dictionary returned by FindXRefs" 34 | s='xref\n' 35 | s+='0 '+str(len(XRefs)+1)+'\n' 36 | s+='0000000000 65535 f \n' 37 | for i in xrange(1,len(XRefs)+1): 38 | s+='%010d 00000 n \n'%XRefs[i] 39 | return s 40 | 41 | def ReplaceXRefsTable(pdf, newtable): 42 | "Replaces the unique XRef table in a PDF file with the updated one" 43 | startxref=pdf.find('xref') 44 | newbuf=pdf[:startxref] + newtable + re.sub('\d+(?=\n%%EOF)',str(startxref), pdf[pdf.find('trailer'):]) 45 | return newbuf 46 | 47 | def DecompressStreams(pdf): 48 | "Decompresses all deflated streams and returns the updated PDF file" 49 | L, streams=[], {} 50 | for m in re.finditer('^<>\n(stream)',pdf,re.M): 51 | start=m.start(2)+7 52 | # stream_start: filter_start, stream_end 53 | streams[start]=(m.start(), start+int(m.group(1))) 54 | L+=[start] 55 | delta=0 56 | for i in L: 57 | start=i+delta 58 | end=streams[i][1]+delta 59 | stream=zlib.decompress(pdf[start:end]) 60 | before=len(pdf) 61 | pdf=pdf.replace(pdf[streams[i][0]+delta:end], '<>\nstream\n'%len(stream)+stream) 62 | delta+=len(pdf)-before 63 | return pdf 64 | 65 | def CompressStreams(pdf): 66 | "Compresses all plain streams and returns the updated PDF file" 67 | L, streams=[], {} 68 | for m in re.finditer('^<>\n(stream)',pdf,re.M): 69 | start=m.start(2)+7 70 | # stream_start: filter_start, stream_end 71 | streams[start]=(m.start(), start+int(m.group(1))) 72 | L+=[start] 73 | delta=0 74 | for i in L: 75 | start=i+delta 76 | end=streams[i][1]+delta 77 | stream=zlib.compress(pdf[start:end]) 78 | before=len(pdf) 79 | pdf=pdf.replace(pdf[streams[i][0]+delta:end], '<>\nstream\n'%len(stream)+stream) 80 | delta+=len(pdf)-before 81 | return pdf 82 | 83 | if __name__=='__main__': 84 | buf=file('b.pdf','rb').read() 85 | newbuf=DecompressStreams(buf) 86 | newbuf=ReplaceXRefsTable(newbuf, BuildXRefsTable(FindXRefs(newbuf))) 87 | 88 | newbuf=UpdateStreamLengths(newbuf) # does nothing here: test purpose only! 89 | file('b0.pdf','wb').write(newbuf) 90 | 91 | newbuf=CompressStreams(newbuf) 92 | newbuf=ReplaceXRefsTable(newbuf, BuildXRefsTable(FindXRefs(newbuf))) 93 | 94 | file('b1.pdf','wb').write(newbuf) #should be identical 95 | -------------------------------------------------------------------------------- /tests/html_.py: -------------------------------------------------------------------------------- 1 | # -*- coding: latin-1 -*- 2 | 3 | "HTML Renderer for FPDF.py" 4 | 5 | __author__ = "Mariano Reingart " 6 | __copyright__ = "Copyright (C) 2010 Mariano Reingart" 7 | __license__ = "LGPL 3.0" 8 | 9 | # Inspired by tuto5.py and several examples from fpdf.org, html2fpdf, etc. 10 | 11 | from fpdf import FPDF, HTMLMixin 12 | 13 | 14 | if __name__=='__main__': 15 | html=""" 16 |

html2fpdf

17 |

Basic usage

18 |

You can now easily print text mixing different 19 | styles : bold, italic, underlined, or 20 | all at once!
You can also insert links 21 | on text, such as www.fpdf.org, 22 | or on an image: click on the logo.
23 |

24 | 25 |
26 |

Sample List

27 |
  • option 1
  • 28 |
    1. option 2
    29 |
  • option 3
30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
Header 1header 2
cell 1cell 2
cell 2cell 3
38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | """ + """ 52 | 53 | 54 | 55 | """ * 200 + """ 56 | 57 |
Header 1header 2
footer 1footer 2
cell 1cell 2
cell 1cell 2
cell spanned
cell 3cell 4
cell 5cell 6
58 | 59 | Font example: Arial 40pt 60 | 61 | 62 | """ 63 | 64 | class MyFPDF(FPDF, HTMLMixin): 65 | def header(self): 66 | self.image('../tutorial/logo_pb.png',10,8,33) 67 | self.set_font('Arial','B',15) 68 | self.cell(80) 69 | self.cell(30,10,'Title',1,0,'C') 70 | self.ln(20) 71 | 72 | def footer(self): 73 | self.set_y(-15) 74 | self.set_font('Arial','I',8) 75 | txt = 'Page %s of %s' % (self.page_no(), self.alias_nb_pages()) 76 | self.cell(0,10,txt,0,0,'C') 77 | 78 | pdf=MyFPDF() 79 | #First page 80 | pdf.add_page() 81 | pdf.write_html(html) 82 | 83 | # this will fail (tables without width are not supported): 84 | try: 85 | pdf.write_html("""
""") 86 | except RuntimeError: 87 | pass 88 | 89 | # this may be rendered incorrectly as currently there is no two pass auto-layout: 90 | pdf.write_html("""
100%
""") 91 | 92 | fn = 'html.pdf' 93 | pdf.output(fn,'F') 94 | 95 | import os 96 | try: 97 | os.startfile(fn) 98 | except: 99 | os.system("xdg-open \"%s\"" % fn) 100 | -------------------------------------------------------------------------------- /tests/cover/test_issue33.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | "Test issue 33 (Cannot import GIF files that don't have transparency)" 4 | 5 | from __future__ import with_statement 6 | 7 | #PyFPDF-cover-test:format=PDF 8 | #PyFPDF-cover-test:fn=issue_33.pdf 9 | #PyFPDF-cover-test:hash=be95c7ef3a5b14b5a54a52f7eaf3a9e4 10 | #PyFPDF-cover-test:2to3=no 11 | #PyFPDF-cover-test:pil=yes 12 | 13 | import common 14 | from fpdf import FPDF 15 | 16 | import os, sys, tempfile 17 | try: 18 | try: 19 | import Image 20 | except: 21 | from PIL import Image 22 | except ImportError: 23 | Image = None 24 | 25 | 26 | def genbar(): 27 | # bg 28 | bg = Image.new("L", (112, 1), 1) 29 | bg = bg.resize((112, 11)) 30 | # stripes 31 | vbarnum = [0x4F43484B, 0xEE90D642, 0xF11A2735, 0xD71A] 32 | vbar = Image.new("L", (112, 1), 1) 33 | pix = vbar.load() 34 | pos = 0 35 | for b in vbarnum: 36 | for i in range(32): 37 | pix[pos, 0] = 0 if (b & 1) else 1 38 | b = b >> 1 39 | pos += 1 40 | if pos >= 112: break 41 | vbar = vbar.resize((112, 31), Image.NEAREST) 42 | # digit 43 | dignum = [0x398, 0x6dc, 0x61a, 0x31b, 0x1bf, 0x6d8, 0x7d8] 44 | dbar = Image.new("L", (16, 7), 1) 45 | pix = dbar.load() 46 | pos = 0 47 | ypos = 0 48 | for b in dignum: 49 | for i in range(16): 50 | pix[pos, ypos] = 0 if (b & 1) else 1 51 | b = b >> 1 52 | pos += 1 53 | ypos += 1 54 | pos = 0 55 | # result 56 | bar = Image.new("L", (114, 44), 2) 57 | bar.paste(vbar, (1, 1)) 58 | bar.paste(bg, (1, 32)) 59 | for i in range(4): 60 | bar.paste(dbar, (35 + i * 12, 34)) 61 | return bar 62 | 63 | 64 | @common.add_unittest 65 | def dotest(outputname, nostamp): 66 | plane = genbar() 67 | palette = (0,0,0, 255,255,255) + (128,128,128)*254 68 | try: 69 | img = Image.frombytes("P", plane.size, plane.tobytes()) 70 | except AttributeError: 71 | # note: https://github.com/python-pillow/Pillow/issues/63 72 | img = Image.fromstring("P", plane.size, plane.tostring()) 73 | img.putpalette(palette) 74 | 75 | with tempfile.NamedTemporaryFile(delete = False, suffix = ".gif") as f: 76 | gif1 = f.name 77 | with tempfile.NamedTemporaryFile(delete = False, suffix = ".gif") as f: 78 | gif2 = f.name 79 | 80 | img.save(gif1, "GIF", optimize = 0) 81 | img.save(gif2, "GIF", transparency = 1, optimize = 0) 82 | 83 | pdf = FPDF() 84 | if nostamp: 85 | pdf._putinfo = lambda: common.test_putinfo(pdf) 86 | pdf.add_page() 87 | pdf.set_font('Arial', '', 16) 88 | pdf.write(8, "Transparency") 89 | pdf.ln() 90 | pdf.write(8, " Transparency") 91 | pdf.ln() 92 | pdf.write(8, " Transparency") 93 | pdf.ln() 94 | pdf.image(gif1, x = 15, y = 15) 95 | 96 | pdf.write(8, "Transparency") 97 | pdf.ln() 98 | pdf.write(8, " Transparency") 99 | pdf.ln() 100 | pdf.write(8, " Transparency") 101 | pdf.ln() 102 | pdf.image(gif2, x = 15, y = 39) 103 | 104 | pdf.output(outputname, 'F') 105 | 106 | os.unlink(gif1) 107 | os.unlink(gif2) 108 | 109 | def main(): 110 | return common.testmain(__file__, dotest) 111 | 112 | if __name__ == "__main__": 113 | main() 114 | 115 | -------------------------------------------------------------------------------- /tutorial/tuto6.py: -------------------------------------------------------------------------------- 1 | from fpdf import * 2 | import re 3 | 4 | class PDF(FPDF): 5 | def __init__(self, orientation = 'P', unit = 'mm', format = 'A4'): 6 | # Call parent constructor 7 | FPDF.__init__(self, orientation, unit, format) 8 | # Initialization 9 | self.b = 0 10 | self.i = 0 11 | self.u = 0 12 | self.href = '' 13 | self.page_links = {} 14 | 15 | def write_html(self, html): 16 | # HTML parser 17 | html = html.replace("\n",' ') 18 | a = re.split('<(.*?)>', html) 19 | for i, e in enumerate(a): 20 | if i % 2 ==0: 21 | # Text 22 | if self.href: 23 | self.put_link(self.href, e) 24 | else: 25 | self.write(5, e) 26 | else: 27 | # Tag 28 | if e[0] == '/': 29 | self.close_tag(e[1:].upper()) 30 | else: 31 | # Extract attributes 32 | attr = {} 33 | a2 = e.split(' ') 34 | tag = a2.pop(0).upper() 35 | for v in a2: 36 | a3 = re.findall('''^([^=]*)=["']?([^"']*)["']?''', v)[0] 37 | if a3: 38 | attr[a3[0].upper()] = a3[1] 39 | self.open_tag(tag, attr) 40 | 41 | def open_tag(self, tag, attr): 42 | # Opening tag 43 | if tag in ('B', 'I', 'U'): 44 | self.set_style(tag, 1) 45 | if tag == 'A': 46 | self.href = attr['HREF'] 47 | if tag == 'BR': 48 | self.ln(5) 49 | 50 | def close_tag(self, tag): 51 | # Closing tag 52 | if tag in ('B', 'I', 'U'): 53 | self.set_style(tag, 0) 54 | if tag == 'A': 55 | self.href = '' 56 | 57 | def set_style(self, tag, enable): 58 | # Modify style and select corresponding font 59 | t = getattr(self, tag.lower()) 60 | if enable: 61 | t += 1 62 | else: 63 | t += -1 64 | setattr(self, tag.lower(), t) 65 | style = '' 66 | for s in ('B','I','U'): 67 | if(getattr(self, s.lower()) > 0): 68 | style += s 69 | self.set_font('', style) 70 | 71 | def put_link(self, url, txt): 72 | # Put a hyperlink 73 | self.set_text_color(0, 0, 255) 74 | self.set_style('U', 1) 75 | self.write(5, txt, url) 76 | self.set_style('U', 0) 77 | self.set_text_color(0) 78 | 79 | html = """You can now easily print text mixing different 80 | styles: bold, italic, underlined, or 81 | all at once!
You can also insert links 82 | on text, such as www.fpdf.org, 83 | or on an image: click on the logo.""" 84 | 85 | pdf = PDF() 86 | # First page 87 | pdf.add_page() 88 | pdf.set_font('Arial', '', 20) 89 | pdf.write(5, 'To find out what\'s new in self tutorial, click ') 90 | pdf.set_font('', 'U') 91 | link = pdf.add_link() 92 | pdf.write(5, 'here', link) 93 | pdf.set_font('') 94 | # Second page 95 | pdf.add_page() 96 | pdf.set_link(link) 97 | pdf.image('logo.png', 10, 10, 30, 0, '', 'http://www.fpdf.org') 98 | pdf.set_left_margin(45) 99 | pdf.set_font_size(14) 100 | pdf.write_html(html) 101 | pdf.output('tuto6.pdf', 'F') 102 | 103 | -------------------------------------------------------------------------------- /docs/Python3.md: -------------------------------------------------------------------------------- 1 | # Python 3000 # 2 | 3 | [TOC] 4 | 5 | Python 3.x is a new version of the language, with some backward compatibility issues. 6 | 7 | In general, Python 2.x code does not run unmodified under Python 3.x, mostly because the "unicode/string/buffer issue", so some steps are taking place to port this library to the new version. 8 | 9 | # Chosen Path # 10 | 11 | There will not be a manual py3k repository; all py3k changes will be back-ported to the trunk ~~in order to enable 2to3 conversion automatically~~ (unified codebase, compatible with both Python 2 and Python 3, without needing the 2to3 converter in the latest revisions). 12 | 13 | As this library is pure Python and has no dependencies (beside PIL optionally), there is no need to do a huge re-factor. 14 | BTW, initial py3k support took a few changes, see changeset c2f3bae9b379 (just 8 changes). More changes are coming to fix Unicode TTF and image support. 15 | 16 | Most string and buffering methods are encapsulated in well-known places (like the `_out` and `sprintf` functions), so they should not cause a big impact. 17 | 18 | Also, the library is Unicode aware since version 1.7, so also that impact could be mitigated. 19 | 20 | **NOTE:** Until [PEP 461](http://www.python.org/dev/peps/pep-0461/) (add % formatting to bytes) is officialy accepted in Python or a suitable alternative is implemented, internal formatting is done using latin1 Unicode strings instead of raw bytes, as this feature is extensively used in the code and allows it to be clean and compact. 21 | 22 | # Conversion Script # 23 | 24 | **IMPORTANT NOTE**: since version 1.7.2 (revision ca2968763421) the codebase has been unified, so there is no need to run any conversion script. (Please skip this section.) 25 | 26 | In Windows, you can use `py3k.bat`, which just calls `2to3.py`, install the package and run the basic test: 27 | 28 | ``` 29 | mkdir fpdf_py3k 30 | c:\python32\tools\Scripts\2to3.py -f all -w -o fpdf_py3k -n fpdf 31 | c:\Python32\python.exe setup.py install 32 | c:\Python32\python.exe tests\py3k.py 33 | ``` 34 | 35 | `setup.py` has the logic to detect the interpreter version and install the correct version of the library. 36 | 37 | # Status # 38 | 39 | Currently (version 1.7.2, January 2014) there is early experimental support for Python 3: 40 | 41 | * most directives are supported (at least `add_page`, `set_font`, `ln`, `write`, `output`) 42 | * compression is not yet supported (zlib support should be rewritten) 43 | * TTF Unicode fonts are not yet supported, use windows-1252 standard fonts (latin1) 44 | * image support is working at least for PNG (JPG and GIF are untested, and also depend on PIL) 45 | 46 | # Example # 47 | 48 | The following example runs unmodified on Python 2.x and Python 3.x 49 | 50 | ```python 51 | from fpdf import FPDF 52 | 53 | pdf = FPDF() 54 | # compression is not yet supported in py3k version 55 | pdf.compress = False 56 | pdf.add_page() 57 | # Unicode is not yet supported in the py3k version; use windows-1252 standard font 58 | pdf.set_font('Arial', '', 14) 59 | pdf.ln(10) 60 | pdf.write(5, 'hello world %s áéíóúüñ' % sys.version) 61 | pdf.image("pyfpdf/tutorial/logo.png", 50, 50) 62 | pdf.output('py3k.pdf', 'F') 63 | ``` 64 | 65 | View the result here: [py3k.pdf](https://github.com/reingart/pyfpdf/raw/master/tests/py3k.pdf) 66 | 67 | It should contain: 68 | 69 | ``` 70 | hello world 3.2.2 (default, Sep 4 2011, 09:51:08) [MSC v.1500 32 bit (Intel)] áéíóúüñ 71 | ``` 72 | 73 | (áéíóúüñ is a latin1 test) 74 | 75 | And the FPDF logo. 76 | -------------------------------------------------------------------------------- /examples/form.py: -------------------------------------------------------------------------------- 1 | # -*- coding: iso-8859-1 -*- 2 | from __future__ import with_statement 3 | 4 | import sys,os 5 | from fpdf import FPDF 6 | 7 | class Form: 8 | def __init__(self, infile): 9 | keys = ('name','type','x1','y1','x2','y2','font','size', 10 | 'bold','italic','underline','foreground','background', 11 | 'align','text','priority') 12 | # parse form format file and create fields dict 13 | self.fields = {} 14 | with open(infile) as file: 15 | for linea in file.readlines(): 16 | kargs = {} 17 | for i,v in enumerate(linea.split(";")): 18 | if not v.startswith("'"): 19 | v = v.replace(",",".") 20 | else: 21 | v = v#.decode('latin1') 22 | if v=='': 23 | v = None 24 | else: 25 | v = eval(v.strip()) 26 | kargs[keys[i]] = v 27 | self.fields[kargs['name'].lower()] = kargs 28 | self.handlers = {'T': self.text, 'L': self.line, 'I': self.image, 29 | 'B': self.rect, 'BC': self.barcode} 30 | 31 | def set(self, name, value): 32 | if name.lower() in self.fields: 33 | self.fields[name.lower()]['text'] = value 34 | 35 | def render(self, outfile): 36 | pdf = FPDF() 37 | pdf.add_page(); 38 | pdf.set_font('Arial','B',16); 39 | 40 | for field in self.fields.values(): 41 | self.handlers[field['type'].upper()](pdf, **field) 42 | 43 | pdf.output(outfile,"F") 44 | 45 | def text(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', font="arial", size=10, 46 | bold=False, italic=False, underline=False, align="", *args, **kwargs): 47 | if text: 48 | font = font.strip().lower() 49 | if font == 'arial black': 50 | font = 'arial' 51 | style = "" 52 | if bold: style += "B" 53 | if italic: style += "I" 54 | if underline: style += "U" 55 | align = {'I':'L','D':'R','C':'C','':'',None:None}[align] 56 | pdf.set_font(font,style,size) 57 | ##m_k = 72 / 2.54 58 | ##h = (size/m_k) 59 | pdf.set_xy(x1,y1) 60 | pdf.cell(w=x2-x1,h=y2-y1,txt=text,border=0,ln=0,align=align) 61 | #pdf.Text(x=x1,y=y1,txt=text) 62 | 63 | def line(self, pdf, x1=0, y1=0, x2=0, y2=0, size=0, *args, **kwargs): 64 | pdf.set_line_width(size) 65 | pdf.line(x1, y1, x2, y2) 66 | 67 | def rect(self, pdf, x1=0, y1=0, x2=0, y2=0, size=0, *args, **kwargs): 68 | pdf.set_line_width(size) 69 | pdf.rect(x1, y1, x2-x1, y2-y1) 70 | 71 | def image(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', *args,**kwargs): 72 | pdf.image(text,x1,y1,w=x2-x1,h=y2-y1,type='',link='') 73 | 74 | def barcode(self, pdf, x1=0, y1=0, x2=0, y2=0, text='', font="arial", size=1, 75 | *args, **kwargs): 76 | font = font.lower().strip() 77 | if font == 'interleaved 2of5 nt': 78 | pdf.interleaved2of5(text,x1,y1,w=size) 79 | 80 | if __name__ == "__main__": 81 | f = Form("invoice.csv") 82 | f.set("EMPRESA","Saraza") 83 | f.set("logo","logo.png") 84 | f.render("./invoice.pdf") 85 | if sys.platform.startswith("linux"): 86 | os.system("xdg-open ./invoice.pdf") 87 | else: 88 | os.system("./invoice.pdf") 89 | -------------------------------------------------------------------------------- /docs/ReferenceManual.md: -------------------------------------------------------------------------------- 1 | # PyFPDF Reference Manual # 2 | 3 | [TOC] 4 | 5 | ## Original FPDF API ## 6 | 7 | **Important**: the original FPDF (PHP) naming convention is CamelCase. This library uses [PEP8's](http://www.python.org/dev/peps/pep-0008/) lower\_case\_with\_underscores recommendation. 8 | 9 | * [accept_page_break](reference/accept_page_break.md) - determine whether to issue automatic page break 10 | * [add_font](reference/add_font.md) - add a new font 11 | * [add_link](reference/add_link.md) - create an internal link 12 | * [add_page](reference/add_page.md) - add a new page 13 | * [alias_nb_pages](reference/alias_nb_pages.md) - define an alias for number of pages 14 | * [cell](reference/cell.md) - print a cell 15 | * [close](reference/close.md) - terminate the document 16 | * [error](reference/error.md) - fatal error 17 | * [footer](reference/footer.md) - page footer 18 | * [FPDF](reference/FPDF.md) - constructor 19 | * [get_string_width](reference/get_string_width.md) - compute string length 20 | * [get_x](reference/get_x.md) - get current x position 21 | * [get_y](reference/get_y.md) - get current y position 22 | * [header](reference/header.md) - page header 23 | * [image](reference/image.md) - output an image 24 | * [line](reference/line.md) - draw a line 25 | * [link](reference/link.md) - put a link 26 | * [ln](reference/ln.md) - line break 27 | * [multi_cell](reference/multi_cell.md) - print text with line breaks 28 | * [output](reference/output.md) - save or send the document 29 | * [page_no](reference/page_no.md) - page number 30 | * [rect](reference/rect.md) - draw a rectangle 31 | * [set_author](reference/set_author.md) - set the document author 32 | * [set_auto_page_break](reference/set_auto_page_break.md) - set the automatic page breaking mode 33 | * [set_compression](reference/set_compression.md) - turn compression on or off 34 | * [set_creator](reference/set_creator.md) - set document creator 35 | * [set_display_mode](reference/set_display_mode.md) - set display mode 36 | * [set_draw_color](reference/set_draw_color.md) - set drawing color 37 | * [set_fill_color](reference/set_fill_color.md) - set filling color 38 | * [set_font](reference/set_font.md) - set font 39 | * [set_font_size](reference/set_font_size.md) - set font size 40 | * [set_keywords](reference/set_keywords.md) - associate keywords with document 41 | * [set_left_margin](reference/set_left_margin.md) - set left margin 42 | * [set_line_width](reference/set_line_width.md) - set line width 43 | * [set_link](reference/set_link.md) - set internal link destination 44 | * [set_margins](reference/set_margins.md) - set margins 45 | * [set_right_margin](reference/set_right_margin.md) - set right margin 46 | * [set_subject](reference/set_subject.md) - set document subject 47 | * [set_text_color](reference/set_text_color.md) - set text color 48 | * [set_title](reference/set_title.md) - set document title 49 | * [set_top_margin](reference/set_top_margin.md) - set top margin 50 | * [set_x](reference/set_x.md) - set current x position 51 | * [set_xy](reference/set_xy.md) - set current x and y positions 52 | * [set_y](reference/set_y.md) - set current y position 53 | * [text](reference/text.md) - print a string 54 | * [write](reference/write.md) - print flowing text 55 | 56 | ## Additional API ## 57 | 58 | These features are not available in the original FPDF and were implemented after forking. 59 | 60 | * [dashed_line](reference/dashed_line.md) - draw a dashed line 61 | * [ellipse](reference/ellipse.md) - draw an ellipse 62 | * [rotate](reference/rotate.md) - rotation around a given center 63 | * [set_doc_option](reference/set_doc_option.md) - set document options 64 | * [set_stretching](reference/set_stretching.md) - set horizontal font stretching 65 | * [write_html](reference/write_html.md) - print text with HTML markup 66 | 67 | -------------------------------------------------------------------------------- /docs/Testing.md: -------------------------------------------------------------------------------- 1 | # Testing # 2 | 3 | [TOC] 4 | 5 | This page describes the test suite of the PyFPDF library. 6 | 7 | This page applicable to version 1.7.1 and newer. 8 | 9 | ## Old tests ## 10 | 11 | There are old tests in the `tests` folder from the stone-age. These will be removed when the test suite completely supersedes all the old tests. 12 | 13 | ## Purposes ## 14 | 15 | * Cover all fixed issues 16 | * Reach **byte-to-byte accuracy** with all Python versions (2.x and 3.x) 17 | * Alert when a change made in the library breaks something 18 | 19 | ## Selected solution ## 20 | 21 | Currently we support two different ways to run the test suite: 22 | 23 | * `runtest.py` - custom script 24 | * [unittest](https://docs.python.org/3/library/unittest.html) - testing framework from the Python standard library 25 | 26 | ## runtest.py ## 27 | 28 | * Automatically tests all available Python interpreters. 29 | * Better support for older Python versions (prior to 2.7) 30 | * Shows a concise table of results 31 | * Shows hints 32 | * Temporary files are stored inside the `tests/out-x.x.x` folder. 33 | 34 | ### Quick start ### 35 | 36 | This is not not an exclusive list of methods. 37 | 38 | Installed copy: 39 | 40 | * Go to the _tests_ folder 41 | * Run `python runtest.py` 42 | 43 | Local copy: 44 | 45 | * Go to the _tests_ folder 46 | * Set the PYFPDFTESTLOCAL variable 47 | * Run `prepare_local.sh` or `prepare_local.bat` 48 | * Run `python runtest.py` 49 | 50 | Distributed copy: 51 | 52 | * In the root distributed folder: 53 | * `PYTHON_PATH=. python tests/runtest.py` 54 | 55 | You can list specific tests and interpreters with the `--test` and `--interp` arguments. For detailed information see `--help`. 56 | 57 | Please note, batch operations test required minimum in library, but when you call any test directly with `python test/cover/text_xx.py`. 58 | 59 | Allowed syntax for calling `tests/cover/*` tests: 60 | 61 | * `--auto` - do not add timestamp and author metadata, do not open the created PDF (if the test produces one) 62 | * `--check` - check generated PDFs against an expected hash 63 | * result filename. 64 | 65 | PDF output with `--auto` may differ. 66 | 67 | ### Structure ### 68 | 69 | * `cover` - all new tests 70 | * `fpdf_local` - local copy of fpdf, generated by prepare\_local 71 | * `out-x.x.x` - working directory for python x.x.x 72 | * `runtest.py` - batch tester 73 | * `resources.txt` - resources list 74 | * data files 75 | * old tests etc. 76 | 77 | Every test can be executed as a standalone app from `tests/cover` or the `tests/out-x.x.x` folder. 78 | 79 | ## unittest ## 80 | 81 | * More familiar and well documented framework (to specify different interpreters, enable warnings, etc) 82 | * Better exception reporting when a test fails 83 | * Shows unclosed files and deprecation warnings 84 | * Files are created in the current folder 85 | 86 | ### Quck start ### 87 | 88 | ``` 89 | PYTHON_PATH=. python -m unittest discover -s tests/cover/ 90 | ``` 91 | 92 | ## Variables ## 93 | 94 | Variables: 95 | 96 | * `format` - PDF, TXT 97 | * `fn` - result filename (if the test doesn't produce any external file, this can be omitted) 98 | * `hash` - hash when the file is created in automatic test mode 99 | * `2to3` - use the 2to3 tool (default - no) 100 | * `python2` - this test can be used with python2 (default - yes) 101 | * `python3` - this test can be used with python3 (default - yes) 102 | * `pil` - PIL or Pillow module is required (default - no) 103 | * `platform` - platform for this test (win32, linux2, etc; by default - all) 104 | 105 | ## Fonts ## 106 | 107 | Some (most) tests use a font pack: 108 | 109 | Place .ttf files in the _tests/font_ folder. You can use the `--downloadfonts` option of `runtest.py` to download and extract them. 110 | 111 | ## Test template ## 112 | 113 | File `tests/cover/test_template.py` contains all additional information. 114 | 115 | 116 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: PyFPDF 2 | site_url: https://github.com/reingart/pyfpdf 3 | repo_url: https://github.com/reingart/pyfpdf.git 4 | site_description: Simple PDF generation for Python (FPDF PHP port) 5 | docs_dir: docs 6 | site_dir: html 7 | markdown_extensions: [toc,fenced_code] 8 | use_directory_urls: false 9 | theme: readthedocs 10 | pages: 11 | - [index.md, "Project Home"] 12 | - [ProjectHome.md, "Project Home"] 13 | - [ReferenceManual.md, "Reference manual"] 14 | - [Tutorial.md, "Tutorial"] 15 | - [Tutorial-es.md, "Tutorial (Spanish translation)"] 16 | - [FAQ.md, "FAQ (Frequently asked questions)"] 17 | - [Python3.md, "Python 3"] 18 | - [Templates.md, "Templates"] 19 | - [Unicode.md, "Unicode"] 20 | - [Web2Py.md, "Web2Py framework"] 21 | - [Testing.md, "Testing"] 22 | - [Development.md, "Development"] 23 | - ["reference/accept_page_break.md", "Reference manual", "accept_page_break"] 24 | - ["reference/add_font.md", "Reference manual", "add_font"] 25 | - ["reference/add_link.md", "Reference manual", "add_link"] 26 | - ["reference/add_page.md", "Reference manual", "add_page"] 27 | - ["reference/alias_nb_pages.md", "Reference manual", "alias_nb_pages"] 28 | - ["reference/cell.md", "Reference manual", "cell"] 29 | - ["reference/close.md", "Reference manual", "close"] 30 | - ["reference/dashed_line.md", "Reference manual", "dashed_line"] 31 | - ["reference/ellipse.md", "Reference manual", "ellipse"] 32 | - ["reference/error.md", "Reference manual", "error"] 33 | - ["reference/FPDF.md", "Reference manual", "FPDF"] 34 | - ["reference/footer.md", "Reference manual", "footer"] 35 | - ["reference/get_string_width.md", "Reference manual", "get_string_width"] 36 | - ["reference/get_x.md", "Reference manual", "get_x"] 37 | - ["reference/get_y.md", "Reference manual", "get_y"] 38 | - ["reference/header.md", "Reference manual", "header"] 39 | - ["reference/image.md", "Reference manual", "image"] 40 | - ["reference/load_resource.md", "Reference manual", "load_resource"] 41 | - ["reference/line.md", "Reference manual", "line"] 42 | - ["reference/link.md", "Reference manual", "link"] 43 | - ["reference/ln.md", "Reference manual", "ln"] 44 | - ["reference/multi_cell.md", "Reference manual", "multi_cell"] 45 | - ["reference/open.md", "Reference manual", "open"] 46 | - ["reference/output.md", "Reference manual", "output"] 47 | - ["reference/page_no.md", "Reference manual", "page_no"] 48 | - ["reference/rect.md", "Reference manual", "rect"] 49 | - ["reference/set_author.md", "Reference manual", "set_author"] 50 | - ["reference/set_auto_page_break.md", "Reference manual", "set_auto_page_break"] 51 | - ["reference/set_compression.md", "Reference manual", "set_compression"] 52 | - ["reference/set_creator.md", "Reference manual", "set_creator"] 53 | - ["reference/set_doc_option.md", "Reference manual", "set_doc_option"] 54 | - ["reference/set_display_mode.md", "Reference manual", "set_display_mode"] 55 | - ["reference/set_draw_color.md", "Reference manual", "set_draw_color"] 56 | - ["reference/set_fill_color.md", "Reference manual", "set_fill_color"] 57 | - ["reference/set_font.md", "Reference manual", "set_font"] 58 | - ["reference/set_font_size.md", "Reference manual", "set_font_size"] 59 | - ["reference/set_keywords.md", "Reference manual", "set_keywords"] 60 | - ["reference/set_left_margin.md", "Reference manual", "set_left_margin"] 61 | - ["reference/set_line_width.md", "Reference manual", "set_line_width"] 62 | - ["reference/set_link.md", "Reference manual", "set_link"] 63 | - ["reference/set_margins.md", "Reference manual", "set_margins"] 64 | - ["reference/set_right_margin.md", "Reference manual", "set_right_margin"] 65 | - ["reference/set_stretching.md", "Reference manual", "set_stretching"] 66 | - ["reference/set_subject.md", "Reference manual", "set_subject"] 67 | - ["reference/set_text_color.md", "Reference manual", "set_text_color"] 68 | - ["reference/set_title.md", "Reference manual", "set_title"] 69 | - ["reference/set_top_margin.md", "Reference manual", "set_top_margin"] 70 | - ["reference/set_x.md", "Reference manual", "set_x"] 71 | - ["reference/set_xy.md", "Reference manual", "set_xy"] 72 | - ["reference/set_y.md", "Reference manual", "set_y"] 73 | - ["reference/text.md", "Reference manual", "text"] 74 | - ["reference/write.md", "Reference manual", "write"] 75 | - ["reference/write_html.md", "Reference manual", "write_html"] 76 | 77 | -------------------------------------------------------------------------------- /docs/ProjectHome.md: -------------------------------------------------------------------------------- 1 | # FPDF for Python # 2 | 3 | Fork me on GitHub 4 | 5 | _PyFPDF_ is a library for PDF document generation under Python, ported from PHP (see [FPDF](http://www.fpdf.org/): "Free"-PDF, a well-known PDFlib-extension replacement with many examples, scripts and derivatives). 6 | 7 | **Latest Released Version: 1.7 (August 15th, 2012)** - **Current Development Version: 1.7.1** 8 | 9 | ## Main features ## 10 | * Easy to use (and easy to extend) 11 | * Many simple examples and scripts available in many languages 12 | * No external dependencies or extensions (optionally PIL for GIF support) 13 | * No installation, no compilation or other libraries (DLLs) required 14 | * Small and compact code, useful for testing new features and teaching 15 | 16 | This repository is a fork of the library's [original port by Max Pat](http://www.fpdf.org/dl.php?id=94), with the following enhancements: 17 | 18 | * Python 2.5 to 3.4+ support (see [Python3](Python3.md) support) 19 | * [Unicode](Unicode.md) (UTF-8) TrueType font subset embedding (Central European, Cyrillic, Greek, Baltic, Thai, Chinese, Japanese, Korean, Hindi and almost any other language in the world) **New!** based on [sFPDF](http://www.fpdf.org/en/script/script91.php) LGPL3 PHP version from [Ian Back](mailto:ian@bpm1.com?subject=sFPDF) 20 | * Improved installers (setup.py, py2exe, PyPI) support 21 | * Barcode I2of5 and code39, QR code coming soon ... 22 | * PNG, GIF and JPG support (including transparency and alpha channel) **New!** 23 | * Exceptions support, other minor fixes, improvements and PEP8 code cleanups 24 | * Port of the [Tutorial](Tutorial.md) and [ReferenceManual](ReferenceManual.md) (Spanish translation available) 25 | 26 | FPDF original features: 27 | 28 | * Choice of measurement unit, page format and margins 29 | * Page header and footer management 30 | * Automatic page break 31 | * Automatic line break and text justification 32 | * Image, colors and links support 33 | * Page compression 34 | * Extensive [Tutorial](http://www.fpdf.org/en/tutorial/index.php) and complete online [documentation](http://www.fpdf.org/en/doc/index.php) 35 | 36 | ## Installation ## 37 | 38 | * Using [PyPI](http://pypi.python.org/pypi?:action=display&name=fpdf&version=1.7) 39 | * Using [EasyInstall](http://peak.telecommunity.com/DevCenter/EasyInstall) `c:\python27\Scripts\easy_install.exe fpdf` 40 | * From source: 41 | * [Download](https://github.com/reingart/pyfpdf/releases) and unpack source package (zip) or pull from the [repository](https://github.com/reingart/pyfpdf) 42 | * Run `python setup.py install` 43 | * Using [MSI](http://pyfpdf.googlecode.com/files/fpdf-1.7.win32.msi) or [Windows Installers](http://pyfpdf.googlecode.com/files/fpdf-1.7.hg.zip) 44 | 45 | For your convenience, some installers include the optional ["Free Unicode TrueType Font Pack"](http://pyfpdf.googlecode.com/files/fpdf_unicode_font_pack.zip) (96 TTF files, 16MB compressed). Please note that copyright restrictions may apply when embedding fonts. 46 | 47 | ## Support ## 48 | 49 | For community support, please feel free to file an [issue](https://github.com/reingart/pyfpdf/issues). 50 | 51 | For priority technical support, you can contact [Mariano Reingart](mailto:reingart@gmail.com) (current maintainer and project owner). Online payments accepted through PayPal. 52 | 53 | ### Pre-paid priority tech support plans ### 54 | 55 | * per email: 1 day coverage, up to 15 min $10,00 USD 56 | * per incident: 1 week coverage, up to 2 hs $50,00 USD 57 | * per feature: 1 month coverage, up to 6 hs $150,00 USD 58 | * per project: 3 month coverage, up to 15 hs $350,00 USD 59 | * extended: 9 month coverage, up to 30hs $750,00 USD 60 | 61 | Vendedor internacional 62 | -------------------------------------------------------------------------------- /attic/font/cp874.map: -------------------------------------------------------------------------------- 1 | !00 U+0000 .notdef 2 | !01 U+0001 .notdef 3 | !02 U+0002 .notdef 4 | !03 U+0003 .notdef 5 | !04 U+0004 .notdef 6 | !05 U+0005 .notdef 7 | !06 U+0006 .notdef 8 | !07 U+0007 .notdef 9 | !08 U+0008 .notdef 10 | !09 U+0009 .notdef 11 | !0A U+000A .notdef 12 | !0B U+000B .notdef 13 | !0C U+000C .notdef 14 | !0D U+000D .notdef 15 | !0E U+000E .notdef 16 | !0F U+000F .notdef 17 | !10 U+0010 .notdef 18 | !11 U+0011 .notdef 19 | !12 U+0012 .notdef 20 | !13 U+0013 .notdef 21 | !14 U+0014 .notdef 22 | !15 U+0015 .notdef 23 | !16 U+0016 .notdef 24 | !17 U+0017 .notdef 25 | !18 U+0018 .notdef 26 | !19 U+0019 .notdef 27 | !1A U+001A .notdef 28 | !1B U+001B .notdef 29 | !1C U+001C .notdef 30 | !1D U+001D .notdef 31 | !1E U+001E .notdef 32 | !1F U+001F .notdef 33 | !20 U+0020 space 34 | !21 U+0021 exclam 35 | !22 U+0022 quotedbl 36 | !23 U+0023 numbersign 37 | !24 U+0024 dollar 38 | !25 U+0025 percent 39 | !26 U+0026 ampersand 40 | !27 U+0027 quotesingle 41 | !28 U+0028 parenleft 42 | !29 U+0029 parenright 43 | !2A U+002A asterisk 44 | !2B U+002B plus 45 | !2C U+002C comma 46 | !2D U+002D hyphen 47 | !2E U+002E period 48 | !2F U+002F slash 49 | !30 U+0030 zero 50 | !31 U+0031 one 51 | !32 U+0032 two 52 | !33 U+0033 three 53 | !34 U+0034 four 54 | !35 U+0035 five 55 | !36 U+0036 six 56 | !37 U+0037 seven 57 | !38 U+0038 eight 58 | !39 U+0039 nine 59 | !3A U+003A colon 60 | !3B U+003B semicolon 61 | !3C U+003C less 62 | !3D U+003D equal 63 | !3E U+003E greater 64 | !3F U+003F question 65 | !40 U+0040 at 66 | !41 U+0041 A 67 | !42 U+0042 B 68 | !43 U+0043 C 69 | !44 U+0044 D 70 | !45 U+0045 E 71 | !46 U+0046 F 72 | !47 U+0047 G 73 | !48 U+0048 H 74 | !49 U+0049 I 75 | !4A U+004A J 76 | !4B U+004B K 77 | !4C U+004C L 78 | !4D U+004D M 79 | !4E U+004E N 80 | !4F U+004F O 81 | !50 U+0050 P 82 | !51 U+0051 Q 83 | !52 U+0052 R 84 | !53 U+0053 S 85 | !54 U+0054 T 86 | !55 U+0055 U 87 | !56 U+0056 V 88 | !57 U+0057 W 89 | !58 U+0058 X 90 | !59 U+0059 Y 91 | !5A U+005A Z 92 | !5B U+005B bracketleft 93 | !5C U+005C backslash 94 | !5D U+005D bracketright 95 | !5E U+005E asciicircum 96 | !5F U+005F underscore 97 | !60 U+0060 grave 98 | !61 U+0061 a 99 | !62 U+0062 b 100 | !63 U+0063 c 101 | !64 U+0064 d 102 | !65 U+0065 e 103 | !66 U+0066 f 104 | !67 U+0067 g 105 | !68 U+0068 h 106 | !69 U+0069 i 107 | !6A U+006A j 108 | !6B U+006B k 109 | !6C U+006C l 110 | !6D U+006D m 111 | !6E U+006E n 112 | !6F U+006F o 113 | !70 U+0070 p 114 | !71 U+0071 q 115 | !72 U+0072 r 116 | !73 U+0073 s 117 | !74 U+0074 t 118 | !75 U+0075 u 119 | !76 U+0076 v 120 | !77 U+0077 w 121 | !78 U+0078 x 122 | !79 U+0079 y 123 | !7A U+007A z 124 | !7B U+007B braceleft 125 | !7C U+007C bar 126 | !7D U+007D braceright 127 | !7E U+007E asciitilde 128 | !7F U+007F .notdef 129 | !80 U+20AC Euro 130 | !85 U+2026 ellipsis 131 | !91 U+2018 quoteleft 132 | !92 U+2019 quoteright 133 | !93 U+201C quotedblleft 134 | !94 U+201D quotedblright 135 | !95 U+2022 bullet 136 | !96 U+2013 endash 137 | !97 U+2014 emdash 138 | !A0 U+00A0 space 139 | !A1 U+0E01 kokaithai 140 | !A2 U+0E02 khokhaithai 141 | !A3 U+0E03 khokhuatthai 142 | !A4 U+0E04 khokhwaithai 143 | !A5 U+0E05 khokhonthai 144 | !A6 U+0E06 khorakhangthai 145 | !A7 U+0E07 ngonguthai 146 | !A8 U+0E08 chochanthai 147 | !A9 U+0E09 chochingthai 148 | !AA U+0E0A chochangthai 149 | !AB U+0E0B sosothai 150 | !AC U+0E0C chochoethai 151 | !AD U+0E0D yoyingthai 152 | !AE U+0E0E dochadathai 153 | !AF U+0E0F topatakthai 154 | !B0 U+0E10 thothanthai 155 | !B1 U+0E11 thonangmonthothai 156 | !B2 U+0E12 thophuthaothai 157 | !B3 U+0E13 nonenthai 158 | !B4 U+0E14 dodekthai 159 | !B5 U+0E15 totaothai 160 | !B6 U+0E16 thothungthai 161 | !B7 U+0E17 thothahanthai 162 | !B8 U+0E18 thothongthai 163 | !B9 U+0E19 nonuthai 164 | !BA U+0E1A bobaimaithai 165 | !BB U+0E1B poplathai 166 | !BC U+0E1C phophungthai 167 | !BD U+0E1D fofathai 168 | !BE U+0E1E phophanthai 169 | !BF U+0E1F fofanthai 170 | !C0 U+0E20 phosamphaothai 171 | !C1 U+0E21 momathai 172 | !C2 U+0E22 yoyakthai 173 | !C3 U+0E23 roruathai 174 | !C4 U+0E24 ruthai 175 | !C5 U+0E25 lolingthai 176 | !C6 U+0E26 luthai 177 | !C7 U+0E27 wowaenthai 178 | !C8 U+0E28 sosalathai 179 | !C9 U+0E29 sorusithai 180 | !CA U+0E2A sosuathai 181 | !CB U+0E2B hohipthai 182 | !CC U+0E2C lochulathai 183 | !CD U+0E2D oangthai 184 | !CE U+0E2E honokhukthai 185 | !CF U+0E2F paiyannoithai 186 | !D0 U+0E30 saraathai 187 | !D1 U+0E31 maihanakatthai 188 | !D2 U+0E32 saraaathai 189 | !D3 U+0E33 saraamthai 190 | !D4 U+0E34 saraithai 191 | !D5 U+0E35 saraiithai 192 | !D6 U+0E36 sarauethai 193 | !D7 U+0E37 saraueethai 194 | !D8 U+0E38 sarauthai 195 | !D9 U+0E39 sarauuthai 196 | !DA U+0E3A phinthuthai 197 | !DF U+0E3F bahtthai 198 | !E0 U+0E40 saraethai 199 | !E1 U+0E41 saraaethai 200 | !E2 U+0E42 saraothai 201 | !E3 U+0E43 saraaimaimuanthai 202 | !E4 U+0E44 saraaimaimalaithai 203 | !E5 U+0E45 lakkhangyaothai 204 | !E6 U+0E46 maiyamokthai 205 | !E7 U+0E47 maitaikhuthai 206 | !E8 U+0E48 maiekthai 207 | !E9 U+0E49 maithothai 208 | !EA U+0E4A maitrithai 209 | !EB U+0E4B maichattawathai 210 | !EC U+0E4C thanthakhatthai 211 | !ED U+0E4D nikhahitthai 212 | !EE U+0E4E yamakkanthai 213 | !EF U+0E4F fongmanthai 214 | !F0 U+0E50 zerothai 215 | !F1 U+0E51 onethai 216 | !F2 U+0E52 twothai 217 | !F3 U+0E53 threethai 218 | !F4 U+0E54 fourthai 219 | !F5 U+0E55 fivethai 220 | !F6 U+0E56 sixthai 221 | !F7 U+0E57 seventhai 222 | !F8 U+0E58 eightthai 223 | !F9 U+0E59 ninethai 224 | !FA U+0E5A angkhankhuthai 225 | !FB U+0E5B khomutthai 226 | -------------------------------------------------------------------------------- /attic/font/cp1253.map: -------------------------------------------------------------------------------- 1 | !00 U+0000 .notdef 2 | !01 U+0001 .notdef 3 | !02 U+0002 .notdef 4 | !03 U+0003 .notdef 5 | !04 U+0004 .notdef 6 | !05 U+0005 .notdef 7 | !06 U+0006 .notdef 8 | !07 U+0007 .notdef 9 | !08 U+0008 .notdef 10 | !09 U+0009 .notdef 11 | !0A U+000A .notdef 12 | !0B U+000B .notdef 13 | !0C U+000C .notdef 14 | !0D U+000D .notdef 15 | !0E U+000E .notdef 16 | !0F U+000F .notdef 17 | !10 U+0010 .notdef 18 | !11 U+0011 .notdef 19 | !12 U+0012 .notdef 20 | !13 U+0013 .notdef 21 | !14 U+0014 .notdef 22 | !15 U+0015 .notdef 23 | !16 U+0016 .notdef 24 | !17 U+0017 .notdef 25 | !18 U+0018 .notdef 26 | !19 U+0019 .notdef 27 | !1A U+001A .notdef 28 | !1B U+001B .notdef 29 | !1C U+001C .notdef 30 | !1D U+001D .notdef 31 | !1E U+001E .notdef 32 | !1F U+001F .notdef 33 | !20 U+0020 space 34 | !21 U+0021 exclam 35 | !22 U+0022 quotedbl 36 | !23 U+0023 numbersign 37 | !24 U+0024 dollar 38 | !25 U+0025 percent 39 | !26 U+0026 ampersand 40 | !27 U+0027 quotesingle 41 | !28 U+0028 parenleft 42 | !29 U+0029 parenright 43 | !2A U+002A asterisk 44 | !2B U+002B plus 45 | !2C U+002C comma 46 | !2D U+002D hyphen 47 | !2E U+002E period 48 | !2F U+002F slash 49 | !30 U+0030 zero 50 | !31 U+0031 one 51 | !32 U+0032 two 52 | !33 U+0033 three 53 | !34 U+0034 four 54 | !35 U+0035 five 55 | !36 U+0036 six 56 | !37 U+0037 seven 57 | !38 U+0038 eight 58 | !39 U+0039 nine 59 | !3A U+003A colon 60 | !3B U+003B semicolon 61 | !3C U+003C less 62 | !3D U+003D equal 63 | !3E U+003E greater 64 | !3F U+003F question 65 | !40 U+0040 at 66 | !41 U+0041 A 67 | !42 U+0042 B 68 | !43 U+0043 C 69 | !44 U+0044 D 70 | !45 U+0045 E 71 | !46 U+0046 F 72 | !47 U+0047 G 73 | !48 U+0048 H 74 | !49 U+0049 I 75 | !4A U+004A J 76 | !4B U+004B K 77 | !4C U+004C L 78 | !4D U+004D M 79 | !4E U+004E N 80 | !4F U+004F O 81 | !50 U+0050 P 82 | !51 U+0051 Q 83 | !52 U+0052 R 84 | !53 U+0053 S 85 | !54 U+0054 T 86 | !55 U+0055 U 87 | !56 U+0056 V 88 | !57 U+0057 W 89 | !58 U+0058 X 90 | !59 U+0059 Y 91 | !5A U+005A Z 92 | !5B U+005B bracketleft 93 | !5C U+005C backslash 94 | !5D U+005D bracketright 95 | !5E U+005E asciicircum 96 | !5F U+005F underscore 97 | !60 U+0060 grave 98 | !61 U+0061 a 99 | !62 U+0062 b 100 | !63 U+0063 c 101 | !64 U+0064 d 102 | !65 U+0065 e 103 | !66 U+0066 f 104 | !67 U+0067 g 105 | !68 U+0068 h 106 | !69 U+0069 i 107 | !6A U+006A j 108 | !6B U+006B k 109 | !6C U+006C l 110 | !6D U+006D m 111 | !6E U+006E n 112 | !6F U+006F o 113 | !70 U+0070 p 114 | !71 U+0071 q 115 | !72 U+0072 r 116 | !73 U+0073 s 117 | !74 U+0074 t 118 | !75 U+0075 u 119 | !76 U+0076 v 120 | !77 U+0077 w 121 | !78 U+0078 x 122 | !79 U+0079 y 123 | !7A U+007A z 124 | !7B U+007B braceleft 125 | !7C U+007C bar 126 | !7D U+007D braceright 127 | !7E U+007E asciitilde 128 | !7F U+007F .notdef 129 | !80 U+20AC Euro 130 | !82 U+201A quotesinglbase 131 | !83 U+0192 florin 132 | !84 U+201E quotedblbase 133 | !85 U+2026 ellipsis 134 | !86 U+2020 dagger 135 | !87 U+2021 daggerdbl 136 | !89 U+2030 perthousand 137 | !8B U+2039 guilsinglleft 138 | !91 U+2018 quoteleft 139 | !92 U+2019 quoteright 140 | !93 U+201C quotedblleft 141 | !94 U+201D quotedblright 142 | !95 U+2022 bullet 143 | !96 U+2013 endash 144 | !97 U+2014 emdash 145 | !99 U+2122 trademark 146 | !9B U+203A guilsinglright 147 | !A0 U+00A0 space 148 | !A1 U+0385 dieresistonos 149 | !A2 U+0386 Alphatonos 150 | !A3 U+00A3 sterling 151 | !A4 U+00A4 currency 152 | !A5 U+00A5 yen 153 | !A6 U+00A6 brokenbar 154 | !A7 U+00A7 section 155 | !A8 U+00A8 dieresis 156 | !A9 U+00A9 copyright 157 | !AB U+00AB guillemotleft 158 | !AC U+00AC logicalnot 159 | !AD U+00AD hyphen 160 | !AE U+00AE registered 161 | !AF U+2015 afii00208 162 | !B0 U+00B0 degree 163 | !B1 U+00B1 plusminus 164 | !B2 U+00B2 twosuperior 165 | !B3 U+00B3 threesuperior 166 | !B4 U+0384 tonos 167 | !B5 U+00B5 mu 168 | !B6 U+00B6 paragraph 169 | !B7 U+00B7 periodcentered 170 | !B8 U+0388 Epsilontonos 171 | !B9 U+0389 Etatonos 172 | !BA U+038A Iotatonos 173 | !BB U+00BB guillemotright 174 | !BC U+038C Omicrontonos 175 | !BD U+00BD onehalf 176 | !BE U+038E Upsilontonos 177 | !BF U+038F Omegatonos 178 | !C0 U+0390 iotadieresistonos 179 | !C1 U+0391 Alpha 180 | !C2 U+0392 Beta 181 | !C3 U+0393 Gamma 182 | !C4 U+0394 Delta 183 | !C5 U+0395 Epsilon 184 | !C6 U+0396 Zeta 185 | !C7 U+0397 Eta 186 | !C8 U+0398 Theta 187 | !C9 U+0399 Iota 188 | !CA U+039A Kappa 189 | !CB U+039B Lambda 190 | !CC U+039C Mu 191 | !CD U+039D Nu 192 | !CE U+039E Xi 193 | !CF U+039F Omicron 194 | !D0 U+03A0 Pi 195 | !D1 U+03A1 Rho 196 | !D3 U+03A3 Sigma 197 | !D4 U+03A4 Tau 198 | !D5 U+03A5 Upsilon 199 | !D6 U+03A6 Phi 200 | !D7 U+03A7 Chi 201 | !D8 U+03A8 Psi 202 | !D9 U+03A9 Omega 203 | !DA U+03AA Iotadieresis 204 | !DB U+03AB Upsilondieresis 205 | !DC U+03AC alphatonos 206 | !DD U+03AD epsilontonos 207 | !DE U+03AE etatonos 208 | !DF U+03AF iotatonos 209 | !E0 U+03B0 upsilondieresistonos 210 | !E1 U+03B1 alpha 211 | !E2 U+03B2 beta 212 | !E3 U+03B3 gamma 213 | !E4 U+03B4 delta 214 | !E5 U+03B5 epsilon 215 | !E6 U+03B6 zeta 216 | !E7 U+03B7 eta 217 | !E8 U+03B8 theta 218 | !E9 U+03B9 iota 219 | !EA U+03BA kappa 220 | !EB U+03BB lambda 221 | !EC U+03BC mu 222 | !ED U+03BD nu 223 | !EE U+03BE xi 224 | !EF U+03BF omicron 225 | !F0 U+03C0 pi 226 | !F1 U+03C1 rho 227 | !F2 U+03C2 sigma1 228 | !F3 U+03C3 sigma 229 | !F4 U+03C4 tau 230 | !F5 U+03C5 upsilon 231 | !F6 U+03C6 phi 232 | !F7 U+03C7 chi 233 | !F8 U+03C8 psi 234 | !F9 U+03C9 omega 235 | !FA U+03CA iotadieresis 236 | !FB U+03CB upsilondieresis 237 | !FC U+03CC omicrontonos 238 | !FD U+03CD upsilontonos 239 | !FE U+03CE omegatonos 240 | -------------------------------------------------------------------------------- /attic/font/cp1255.map: -------------------------------------------------------------------------------- 1 | !00 U+0000 .notdef 2 | !01 U+0001 .notdef 3 | !02 U+0002 .notdef 4 | !03 U+0003 .notdef 5 | !04 U+0004 .notdef 6 | !05 U+0005 .notdef 7 | !06 U+0006 .notdef 8 | !07 U+0007 .notdef 9 | !08 U+0008 .notdef 10 | !09 U+0009 .notdef 11 | !0A U+000A .notdef 12 | !0B U+000B .notdef 13 | !0C U+000C .notdef 14 | !0D U+000D .notdef 15 | !0E U+000E .notdef 16 | !0F U+000F .notdef 17 | !10 U+0010 .notdef 18 | !11 U+0011 .notdef 19 | !12 U+0012 .notdef 20 | !13 U+0013 .notdef 21 | !14 U+0014 .notdef 22 | !15 U+0015 .notdef 23 | !16 U+0016 .notdef 24 | !17 U+0017 .notdef 25 | !18 U+0018 .notdef 26 | !19 U+0019 .notdef 27 | !1A U+001A .notdef 28 | !1B U+001B .notdef 29 | !1C U+001C .notdef 30 | !1D U+001D .notdef 31 | !1E U+001E .notdef 32 | !1F U+001F .notdef 33 | !20 U+0020 space 34 | !21 U+0021 exclam 35 | !22 U+0022 quotedbl 36 | !23 U+0023 numbersign 37 | !24 U+0024 dollar 38 | !25 U+0025 percent 39 | !26 U+0026 ampersand 40 | !27 U+0027 quotesingle 41 | !28 U+0028 parenleft 42 | !29 U+0029 parenright 43 | !2A U+002A asterisk 44 | !2B U+002B plus 45 | !2C U+002C comma 46 | !2D U+002D hyphen 47 | !2E U+002E period 48 | !2F U+002F slash 49 | !30 U+0030 zero 50 | !31 U+0031 one 51 | !32 U+0032 two 52 | !33 U+0033 three 53 | !34 U+0034 four 54 | !35 U+0035 five 55 | !36 U+0036 six 56 | !37 U+0037 seven 57 | !38 U+0038 eight 58 | !39 U+0039 nine 59 | !3A U+003A colon 60 | !3B U+003B semicolon 61 | !3C U+003C less 62 | !3D U+003D equal 63 | !3E U+003E greater 64 | !3F U+003F question 65 | !40 U+0040 at 66 | !41 U+0041 A 67 | !42 U+0042 B 68 | !43 U+0043 C 69 | !44 U+0044 D 70 | !45 U+0045 E 71 | !46 U+0046 F 72 | !47 U+0047 G 73 | !48 U+0048 H 74 | !49 U+0049 I 75 | !4A U+004A J 76 | !4B U+004B K 77 | !4C U+004C L 78 | !4D U+004D M 79 | !4E U+004E N 80 | !4F U+004F O 81 | !50 U+0050 P 82 | !51 U+0051 Q 83 | !52 U+0052 R 84 | !53 U+0053 S 85 | !54 U+0054 T 86 | !55 U+0055 U 87 | !56 U+0056 V 88 | !57 U+0057 W 89 | !58 U+0058 X 90 | !59 U+0059 Y 91 | !5A U+005A Z 92 | !5B U+005B bracketleft 93 | !5C U+005C backslash 94 | !5D U+005D bracketright 95 | !5E U+005E asciicircum 96 | !5F U+005F underscore 97 | !60 U+0060 grave 98 | !61 U+0061 a 99 | !62 U+0062 b 100 | !63 U+0063 c 101 | !64 U+0064 d 102 | !65 U+0065 e 103 | !66 U+0066 f 104 | !67 U+0067 g 105 | !68 U+0068 h 106 | !69 U+0069 i 107 | !6A U+006A j 108 | !6B U+006B k 109 | !6C U+006C l 110 | !6D U+006D m 111 | !6E U+006E n 112 | !6F U+006F o 113 | !70 U+0070 p 114 | !71 U+0071 q 115 | !72 U+0072 r 116 | !73 U+0073 s 117 | !74 U+0074 t 118 | !75 U+0075 u 119 | !76 U+0076 v 120 | !77 U+0077 w 121 | !78 U+0078 x 122 | !79 U+0079 y 123 | !7A U+007A z 124 | !7B U+007B braceleft 125 | !7C U+007C bar 126 | !7D U+007D braceright 127 | !7E U+007E asciitilde 128 | !7F U+007F .notdef 129 | !80 U+20AC Euro 130 | !82 U+201A quotesinglbase 131 | !83 U+0192 florin 132 | !84 U+201E quotedblbase 133 | !85 U+2026 ellipsis 134 | !86 U+2020 dagger 135 | !87 U+2021 daggerdbl 136 | !88 U+02C6 circumflex 137 | !89 U+2030 perthousand 138 | !8B U+2039 guilsinglleft 139 | !91 U+2018 quoteleft 140 | !92 U+2019 quoteright 141 | !93 U+201C quotedblleft 142 | !94 U+201D quotedblright 143 | !95 U+2022 bullet 144 | !96 U+2013 endash 145 | !97 U+2014 emdash 146 | !98 U+02DC tilde 147 | !99 U+2122 trademark 148 | !9B U+203A guilsinglright 149 | !A0 U+00A0 space 150 | !A1 U+00A1 exclamdown 151 | !A2 U+00A2 cent 152 | !A3 U+00A3 sterling 153 | !A4 U+20AA afii57636 154 | !A5 U+00A5 yen 155 | !A6 U+00A6 brokenbar 156 | !A7 U+00A7 section 157 | !A8 U+00A8 dieresis 158 | !A9 U+00A9 copyright 159 | !AA U+00D7 multiply 160 | !AB U+00AB guillemotleft 161 | !AC U+00AC logicalnot 162 | !AD U+00AD sfthyphen 163 | !AE U+00AE registered 164 | !AF U+00AF macron 165 | !B0 U+00B0 degree 166 | !B1 U+00B1 plusminus 167 | !B2 U+00B2 twosuperior 168 | !B3 U+00B3 threesuperior 169 | !B4 U+00B4 acute 170 | !B5 U+00B5 mu 171 | !B6 U+00B6 paragraph 172 | !B7 U+00B7 middot 173 | !B8 U+00B8 cedilla 174 | !B9 U+00B9 onesuperior 175 | !BA U+00F7 divide 176 | !BB U+00BB guillemotright 177 | !BC U+00BC onequarter 178 | !BD U+00BD onehalf 179 | !BE U+00BE threequarters 180 | !BF U+00BF questiondown 181 | !C0 U+05B0 afii57799 182 | !C1 U+05B1 afii57801 183 | !C2 U+05B2 afii57800 184 | !C3 U+05B3 afii57802 185 | !C4 U+05B4 afii57793 186 | !C5 U+05B5 afii57794 187 | !C6 U+05B6 afii57795 188 | !C7 U+05B7 afii57798 189 | !C8 U+05B8 afii57797 190 | !C9 U+05B9 afii57806 191 | !CB U+05BB afii57796 192 | !CC U+05BC afii57807 193 | !CD U+05BD afii57839 194 | !CE U+05BE afii57645 195 | !CF U+05BF afii57841 196 | !D0 U+05C0 afii57842 197 | !D1 U+05C1 afii57804 198 | !D2 U+05C2 afii57803 199 | !D3 U+05C3 afii57658 200 | !D4 U+05F0 afii57716 201 | !D5 U+05F1 afii57717 202 | !D6 U+05F2 afii57718 203 | !D7 U+05F3 gereshhebrew 204 | !D8 U+05F4 gershayimhebrew 205 | !E0 U+05D0 afii57664 206 | !E1 U+05D1 afii57665 207 | !E2 U+05D2 afii57666 208 | !E3 U+05D3 afii57667 209 | !E4 U+05D4 afii57668 210 | !E5 U+05D5 afii57669 211 | !E6 U+05D6 afii57670 212 | !E7 U+05D7 afii57671 213 | !E8 U+05D8 afii57672 214 | !E9 U+05D9 afii57673 215 | !EA U+05DA afii57674 216 | !EB U+05DB afii57675 217 | !EC U+05DC afii57676 218 | !ED U+05DD afii57677 219 | !EE U+05DE afii57678 220 | !EF U+05DF afii57679 221 | !F0 U+05E0 afii57680 222 | !F1 U+05E1 afii57681 223 | !F2 U+05E2 afii57682 224 | !F3 U+05E3 afii57683 225 | !F4 U+05E4 afii57684 226 | !F5 U+05E5 afii57685 227 | !F6 U+05E6 afii57686 228 | !F7 U+05E7 afii57687 229 | !F8 U+05E8 afii57688 230 | !F9 U+05E9 afii57689 231 | !FA U+05EA afii57690 232 | !FD U+200E afii299 233 | !FE U+200F afii300 234 | --------------------------------------------------------------------------------