A PDF document generator with high level support for text, drawing and images

GoFPDF document generator

GitHub release CI MIT licensed Report GoDoc

Package go-pdf/fpdf implements a PDF document generator with high level support for text, drawing and images.

Features

  • UTF-8 support
  • Choice of measurement unit, page format and margins
  • Page header and footer management
  • Automatic page breaks, line breaks, and text justification
  • Inclusion of JPEG, PNG, GIF, TIFF and basic path-only SVG images
  • Colors, gradients and alpha channel transparency
  • Outline bookmarks
  • Internal and external links
  • TrueType, Type1 and encoding support
  • Page compression
  • Lines, Bézier curves, arcs, and ellipses
  • Rotation, scaling, skewing, translation, and mirroring
  • Clipping
  • Document protection
  • Layers
  • Templates
  • Barcodes
  • Charting facility
  • Import PDFs as templates

gofpdf has no dependencies other than the Go standard library. All tests pass on Linux, Mac and Windows platforms.

gofpdf supports UTF-8 TrueType fonts and “right-to-left” languages. Note that Chinese, Japanese, and Korean characters may not be included in many general purpose fonts. For these languages, a specialized font (for example, NotoSansSC for simplified Chinese) can be used.

Also, support is provided to automatically translate UTF-8 runes to code page encodings for languages that have fewer than 256 glyphs.

Installation

To install the package on your system, run

go get github.com/go-pdf/fpdf

Later, to receive updates, run

go get -u -v github.com/go-pdf/fpdf/...

Quick Start

The following Go code generates a simple PDF file.

pdf := fpdf.New("P", "mm", "A4", "")
pdf.AddPage()
pdf.SetFont("Arial", "B", 16)
pdf.Cell(40, 10, "Hello, world")
err := pdf.OutputFileAndClose("hello.pdf")

See the functions in the fpdf_test.go file (shown as examples in this documentation) for more advanced PDF examples.

Errors

If an error occurs in an Fpdf method, an internal error field is set. After this occurs, Fpdf method calls typically return without performing any operations and the error state is retained. This error management scheme facilitates PDF generation since individual method calls do not need to be examined for failure; it is generally sufficient to wait until after Output() is called. For the same reason, if an error occurs in the calling application during PDF generation, it may be desirable for the application to transfer the error to the Fpdf instance by calling the SetError() method or the SetErrorf() method. At any time during the life cycle of the Fpdf instance, the error state can be determined with a call to Ok() or Err(). The error itself can be retrieved with a call to Error().

Conversion Notes

This package is a relatively straightforward translation from the original FPDF library written in PHP (despite the caveat in the introduction to Effective Go). The API names have been retained even though the Go idiom would suggest otherwise (for example, pdf.GetX() is used rather than simply pdf.X()). The similarity of the two libraries makes the original FPDF website a good source of information. It includes a forum and FAQ.

However, some internal changes have been made. Page content is built up using buffers (of type bytes.Buffer) rather than repeated string concatenation. Errors are handled as explained above rather than panicking. Output is generated through an interface of type io.Writer or io.WriteCloser. A number of the original PHP methods behave differently based on the type of the arguments that are passed to them; in these cases additional methods have been exported to provide similar functionality. Font definition files are produced in JSON rather than PHP.

Example PDFs

A side effect of running go test ./... is the production of a number of example PDFs. These can be found in the gofpdf/pdf directory after the tests complete.

Please note that these examples run in the context of a test. In order run an example as a standalone application, you’ll need to examine fpdf_test.go for some helper routines, for example exampleFilename() and summary().

Example PDFs can be compared with reference copies in order to verify that they have been generated as expected. This comparison will be performed if a PDF with the same name as the example PDF is placed in the fpdf/pdf/reference directory and if the third argument to ComparePDFFiles() in internal/example/example.go is true. (By default it is false.) The routine that summarizes an example will look for this file and, if found, will call ComparePDFFiles() to check the example PDF for equality with its reference PDF. If differences exist between the two files they will be printed to standard output and the test will fail. If the reference file is missing, the comparison is considered to succeed. In order to successfully compare two PDFs, the placement of internal resources must be consistent and the internal creation timestamps must be the same. To do this, the methods SetCatalogSort() and SetCreationDate() need to be called for both files. This is done automatically for all examples.

Nonstandard Fonts

Nothing special is required to use the standard PDF fonts (courier, helvetica, times, zapfdingbats) in your documents other than calling SetFont().

You should use AddUTF8Font() or AddUTF8FontFromBytes() to add a TrueType UTF-8 encoded font. Use RTL() and LTR() methods switch between “right-to-left” and “left-to-right” mode.

In order to use a different non-UTF-8 TrueType or Type1 font, you will need to generate a font definition file and, if the font will be embedded into PDFs, a compressed version of the font file. This is done by calling the MakeFont function or using the included makefont command line utility. To create the utility, cd into the makefont subdirectory and run “go build”. This will produce a standalone executable named makefont. Select the appropriate encoding file from the font subdirectory and run the command as in the following example.

./makefont --embed --enc=../font/cp1252.map --dst=../font ../font/calligra.ttf

In your PDF generation code, call AddFont() to load the font and, as with the standard fonts, SetFont() to begin using it. Most examples, including the package example, demonstrate this method. Good sources of free, open-source fonts include Google Fonts and DejaVu Fonts.

Related Packages

The draw2d package is a two dimensional vector graphics library that can generate output in different forms. It uses go-pdf/fpdf for its document production mode.

Contributing Changes

go-pdf/fpdf is a global community effort and you are invited to make it even better. If you have implemented a new feature or corrected a problem, please consider contributing your change to the project. A contribution that does not directly pertain to the core functionality of go-pdf/fpdf should be placed in its own directory directly beneath the contrib directory.

Here are guidelines for making submissions. Your change should

  • be compatible with the MIT License
  • be properly documented
  • be formatted with go fmt
  • include an example in fpdf_test.go if appropriate
  • conform to the standards of golint and go vet, that is, golint . and go vet . should not generate any warnings
  • not diminish test coverage

Pull requests are the preferred means of accepting your changes.

License

go-pdf/fpdf is released under the MIT License. It is copyrighted by Dave Barnes and the contributors acknowledged below.

Acknowledgments

Thank you to Kurt Jung who originally wrote gofpdf in 2013 - 2019. This package’s code and documentation are closely derived from the FPDF library created by Olivier Plathey, and a number of font and image resources are copied directly from it. Bruno Michel has provided valuable assistance with the code. Drawing support is adapted from the FPDF geometric figures script by David Hernández Sanz. Transparency support is adapted from the FPDF transparency script by Martin Hall-May. Support for gradients and clipping is adapted from FPDF scripts by Andreas Würmser. Support for outline bookmarks is adapted from Olivier Plathey by Manuel Cornes. Layer support is adapted from Olivier Plathey. Support for transformations is adapted from the FPDF transformation script by Moritz Wagner and Andreas Würmser. PDF protection is adapted from the work of Klemen Vodopivec for the FPDF product. Lawrence Kesteloot provided code to allow an image’s extent to be determined prior to placement. Support for vertical alignment within a cell was provided by Stefan Schroeder. Ivan Daniluk generalized the font and image loading code to use the Reader interface while maintaining backward compatibility. Anthony Starks provided code for the Polygon function. Robert Lillack provided the Beziergon function and corrected some naming issues with the internal curve function. Claudio Felber provided implementations for dashed line drawing and generalized font loading. Stani Michiels provided support for multi-segment path drawing with smooth line joins, line join styles, enhanced fill modes, and has helped greatly with package presentation and tests. Templating is adapted by Marcus Downing from the FPDF_Tpl library created by Jan Slabon and Setasign. Jelmer Snoeck contributed packages that generate a variety of barcodes and help with registering images on the web. Jelmer Snoek and Guillermo Pascual augmented the basic HTML functionality with aligned text. Kent Quirk implemented backwards-compatible support for reading DPI from images that support it, and for setting DPI manually and then having it properly taken into account when calculating image size. Paulo Coutinho provided support for static embedded fonts. Dan Meyers added support for embedded JavaScript. David Fish added a generic alias-replacement function to enable, among other things, table of contents functionality. Andy Bakun identified and corrected a problem in which the internal catalogs were not sorted stably. Paul Montag added encoding and decoding functionality for templates, including images that are embedded in templates; this allows templates to be stored independently of gofpdf. Paul also added support for page boxes used in printing PDF documents. Wojciech Matusiak added supported for word spacing. Artem Korotkiy added support of UTF-8 fonts. Dave Barnes added support for imported objects and templates. Brigham Thompson added support for rounded rectangles. Joe Westcott added underline functionality and optimized image storage. Benoit KUGLER contributed support for rectangles with corners of unequal radius, modification times, and for file attachments and annotations.

Roadmap

  • Remove all legacy code page font support; use UTF-8 exclusively
  • Improve test coverage as reported by the coverage tool.
Comments
  • perf: improve perfs for pdfdeck

    perf: improve perfs for pdfdeck

    $ go get github.com/go-pdf/fpdf
    go get: github.com/go-pdf/fpdf@none updating to
    	github.com/go-pdf/[email protected]: parsing go.mod:
    	module declares its path as: github.com/phpdave11/gofpdf
    	        but was required as: github.com/go-pdf/fpdf
    
  • Generating PDF in Windows 10 vs Linux

    Generating PDF in Windows 10 vs Linux

    This is a strange situation, but I am creating a cross-platform program which includes generating PDFs and I've noticed that PDFs generated in Windows contain a small horizontal line in the middle of the generated PDF, while in Linux there isn't. Furthermore, if I open the Windows-generated PDF in Linux the line is gone.

    This only happens if I use CellFormat(), but not if I use Cell(). Help?

    EDIT: I just noticed that if I open the PDFs generated in Linux on the Windows machine, there is a line. The line is not present if the PDF is opened in Linux.

    Thank you for your time.

  • Latin é output as é

    Latin é output as é

    Hi, when I write text to a pdf page with accents like "é" the writer outputs as "é"

    I searched why this was happening, and I found that was a encoding problem. https://www.i18nqa.com/debug/utf8-debug.html

    I treid changin the font to "times" "courier" "helvetica" and the problem was persistent.

    Can you help me with this problem please.

    An image and the test pdf 2022-06-20_13-18 hello.pdf

  • New help on automatic page break

    New help on automatic page break

    From the README, it seems automatic page break is supported. In my local testing, when I keep writing texts, there's no new page generated and the additional text which cannot fit in a single page just disappears. Could you help me understand how auto page break can be enabled? Thanks!

  • Import existing pdf to use as template (ideally multiple pages)

    Import existing pdf to use as template (ideally multiple pages)

    Could you give an example of how we can import an existing pdf to add extra data to it.

    e.g. I would like to import a document and add signatures to it based on signature input images and x,y,w,h location

  • Need assistance in understanding TransformRotate()

    Need assistance in understanding TransformRotate()

    Hi,

    I am currently trying to rotate a block of text vertically in my PDF document and I have a hard time to understand how TransformRoate() operates - especially how to position the rotated element on my page. It seems that the X and Y parameters work in a different way that I would expect it.

    Here is some example code I wrote:

    func main() {
    	pdf := fpdf.New("P", "mm", "A4", "")
    	pdf.AddUTF8Font("opensans", "", "OpenSans-Regular.ttf")
    	pdf.AddUTF8Font("opensans", "B", "OpenSans-Bold.ttf")
    	pdf.AddUTF8Font("opensans", "I", "OpenSans-Italic.ttf")
    	pdf.AddUTF8Font("opensans", "BI", "OpenSans-BoldItalic.ttf")
    	pdf.AddPage()
    	pdf.SetFont("opensans", "", 10)
    
    	for i := 0.0; i <= 90; i = i + 10 {
    		pdf.AddLayer(fmt.Sprintf("%f", i), true)
    		pdf.SetXY(210.0/2, 297.0/2)
    		pdf.TransformBegin()
    		pdf.TransformRotate(i, 0, 0)
    		pdf.CellFormat(0, 5, fmt.Sprintf("Angel: %f", i), "", 0, "", false, 0, "")
    		pdf.TransformEnd()
    	}
    	if err := pdf.OutputFileAndClose("hello.pdf"); err != nil {
    		fmt.Printf("error generating PDF: %s\n", err)
    		os.Exit(1)
    	}
    }
    

    I would expect that I have a piece of text that is starting centered on the page and is rotated from there in 10° increments. But in reallity it seem that the text is skewed in some weird way, even though the X and Y parameters are always 0. The result looks like this:

    image

    Does anybody has some advice or pointer to what I am doing wrong? As final goal I'd like to position vertical text boxes and a QR code in the upper left corner of the document, but given that I am basically blindly guessing right now where the rotated element would end up, I am not getting reliable re-producable results.

    Any assistance is highly appreciated.

  • embed font files with //go:embed

    embed font files with //go:embed

    For issue go-pdf/fpdf#13 I just added the same files that was embedded in embedded.go. I mean i didn't add others *.map and *.json of font directory to keep exactly the same functionalities for now.

  • fpdf: introduce buffer pool for (de)flating buffers

    fpdf: introduce buffer pool for (de)flating buffers

    name              old time/op    new time/op    delta
    ParsePNG_rgb-8      22.8ms ± 1%    16.0ms ± 3%  -29.81%  (p=0.000 n=25+30)
    ParsePNG_gray-8      660µs ± 3%     624µs ± 4%   -5.54%  (p=0.000 n=28+30)
    ParsePNG_small-8    2.49µs ± 2%    2.12µs ± 3%  -14.83%  (p=0.000 n=30+30)
    ParseJPG-8          36.3µs ± 4%    36.8µs ± 5%     ~     (p=0.070 n=30+30)
    ParseGIF-8           410µs ± 3%     409µs ± 4%     ~     (p=0.562 n=30+29)
    
    name              old alloc/op   new alloc/op   delta
    ParsePNG_rgb-8      26.4MB ± 0%     4.2MB ±10%  -84.04%  (p=0.000 n=29+30)
    ParsePNG_gray-8     2.56MB ± 0%    2.49MB ± 0%   -2.73%  (p=0.000 n=30+30)
    ParsePNG_small-8    8.96kB ± 0%    9.84kB ± 0%   +9.73%  (p=0.000 n=30+30)
    ParseJPG-8           274kB ± 0%     274kB ± 0%   -0.00%  (p=0.002 n=30+30)
    ParseGIF-8           897kB ± 0%     898kB ± 0%   +0.10%  (p=0.000 n=30+30)
    
    name              old allocs/op  new allocs/op  delta
    ParsePNG_rgb-8         400 ± 0%       292 ± 0%  -27.00%  (p=0.000 n=30+28)
    ParsePNG_gray-8        164 ± 0%       114 ± 0%  -30.49%  (p=0.000 n=30+30)
    ParsePNG_small-8      35.0 ± 0%      10.0 ± 0%  -71.43%  (p=0.000 n=30+30)
    ParseJPG-8            12.0 ± 0%      12.0 ± 0%     ~     (all equal)
    ParseGIF-8             214 ± 0%       191 ± 0%  -10.75%  (p=0.000 n=30+30)
    
  • all: optimize rgbColorValue

    all: optimize rgbColorValue

    This CL introduces a per-document buffer to build color strings.

    name        old time/op    new time/op    delta
    RGB_grg-8      808ns ± 0%     576ns ± 0%  -28.66%  (p=0.000 n=17+18)
    RGB_gray-8     779ns ± 0%     584ns ± 0%  -25.01%  (p=0.000 n=18+18)
    RGB_full-8     746ns ± 1%     568ns ± 1%  -23.89%  (p=0.000 n=19+19)
    
    name        old alloc/op   new alloc/op   delta
    RGB_grg-8      64.0B ± 0%     24.0B ± 0%  -62.50%  (p=0.000 n=20+20)
    RGB_gray-8     48.0B ± 0%     24.0B ± 0%  -50.00%  (p=0.000 n=20+20)
    RGB_full-8     48.0B ± 0%     24.0B ± 0%  -50.00%  (p=0.000 n=20+20)
    
    name        old allocs/op  new allocs/op  delta
    RGB_grg-8       5.00 ± 0%      1.00 ± 0%  -80.00%  (p=0.000 n=20+20)
    RGB_gray-8      4.00 ± 0%      1.00 ± 0%  -75.00%  (p=0.000 n=20+20)
    RGB_full-8      4.00 ± 0%      1.00 ± 0%  -75.00%  (p=0.000 n=20+20)
    
  • all: optimize LineTo, CurveTo and methods formatting numbers

    all: optimize LineTo, CurveTo and methods formatting numbers

    This CL adds a per-doc formatting buffer that is used when formatting numbers.

    name       old time/op    new time/op    delta
    LineTo-8      500ns ± 1%     343ns ± 1%   -31.47%  (p=0.000 n=19+18)
    CurveTo-8    1.00µs ± 2%    0.74µs ± 0%   -25.86%  (p=0.000 n=20+18)
    
    name       old alloc/op   new alloc/op   delta
    LineTo-8      77.0B ± 0%     47.5B ± 1%   -38.38%  (p=0.000 n=17+20)
    CurveTo-8      228B ± 7%      118B ± 1%   -48.33%  (p=0.000 n=20+20)
    
    name       old allocs/op  new allocs/op  delta
    LineTo-8       3.00 ± 0%      0.00       -100.00%  (p=0.000 n=20+20)
    CurveTo-8      5.00 ± 0%      0.00       -100.00%  (p=0.000 n=20+20)
    
  • makefont function that return bytes instead of writing to files.

    makefont function that return bytes instead of writing to files.

    Currently if you design your program in such a way that you allow the user to specify a font, then you have to use the makefont function to convert fonts first and this writes to the disk and this could cause problems. It would be cool if there was a variant of the makefont function that return the bytes it would write to the file, especially considering that there is a AddUft8bytes function.

  • Add newline support to CellFormat

    Add newline support to CellFormat

    When I add a \n in CellFormat text parameter it takes it away and does nothing with it. It would be cool to have newline support in fpdf for the CellFormat function

  • How to add a page count at the bottom of Page

    How to add a page count at the bottom of Page

    Hi, I was trying to add a page count at the bottom of the page, as the other implementation of fpdf works, by using pdf.SetY(-15) and therefore adding a cell.

    But a new page is added and the {nb} is not interpolated.

    package main
    
    import (
    	"fmt"
    
    	"github.com/go-pdf/fpdf"
    )
    
    func main() {
    	pdf := fpdf.New("P", "mm", "A4", "")
    	tr := pdf.UnicodeTranslatorFromDescriptor("")
    	pdf.AddPage()
    	pdf.SetFont("Arial", "B", 16)
    	pdf.Cell(40, 10, tr("Olá, mundo"))
    	pdf.SetY(-15)
    	pdf.SetFont("Arial", "I", 8)
    	pageNum := fmt.Sprintf("%d/{nb}", pdf.PageNo())
    	pdf.CellFormat(0, 10, pageNum, "", 0, "C", false, 0, "")
    	err := pdf.OutputFileAndClose("hello.pdf")
    	if err != nil {
    		panic(err.Error())
    	}
    }
    
    

    To interpolate {nb} had to force by using pdf.AliasNbPages("{nb}"), but even though another page was added.

    image

  • fpdf: consider implementing a page-concurrent writing mode

    fpdf: consider implementing a page-concurrent writing mode

    for large documents, it may make sense to have a per-page goroutine worker producing the final bytes of a page, and assemble them in the final document serially.

    see https://github.com/phpdave11/gofpdf/issues/17.

    this would involve quite a large refactoring of fpdf.Fpdf (into pageWriters ?) though.

Related tags
goldmark-pdf is a renderer for goldmark that allows rendering to PDF.
goldmark-pdf is a renderer for goldmark that allows rendering to PDF.

A PDF renderer for the goldmark markdown parser.

Dec 27, 2022
Convert document to pdf with golang

Convert document to pdf Build docker: docker build --pull --rm -f "Dockerfile" -t convertdocument:latest "." docker run -p 3000:3000 registry.gitlab.

Nov 29, 2021
go-fastdfs 是一个简单的分布式文件系统(私有云存储),具有无中心、高性能,高可靠,免维护等优点,支持断点续传,分块上传,小文件合并,自动同步,自动修复。Go-fastdfs is a simple distributed file system (private cloud storage), with no center, high performance, high reliability, maintenance free and other advantages, support breakpoint continuation, block upload, small file merge, automatic synchronization, automatic repair.(similar fastdfs).
go-fastdfs 是一个简单的分布式文件系统(私有云存储),具有无中心、高性能,高可靠,免维护等优点,支持断点续传,分块上传,小文件合并,自动同步,自动修复。Go-fastdfs is a simple distributed file system (private cloud storage), with no center, high performance, high reliability, maintenance free and other advantages, support breakpoint continuation, block upload, small file merge, automatic synchronization, automatic repair.(similar fastdfs).

中文 English 愿景:为用户提供最简单、可靠、高效的分布式文件系统。 go-fastdfs是一个基于http协议的分布式文件系统,它基于大道至简的设计理念,一切从简设计,使得它的运维及扩展变得更加简单,它具有高性能、高可靠、无中心、免维护等优点。 大家担心的是这么简单的文件系统,靠不靠谱,可不

Jan 8, 2023
Read data from rss, convert in pdf and send to kindle. Amazon automatically convert them in azw3.

Kindle-RSS-PDF-AZW3 The Kindle RSS PDF AZW3 is a personal project. The Kindle RSS PDF AZW3 is a personal project. I received a Kindle for Christmas, a

Jan 10, 2022
Golang wrapper for Exiftool : extract as much metadata as possible (EXIF, ...) from files (pictures, pdf, office documents, ...)

go-exiftool go-exiftool is a golang library that wraps ExifTool. ExifTool's purpose is to extract as much metadata as possible (EXIF, IPTC, XMP, GPS,

Dec 28, 2022
A PDF processor written in Go.
A PDF processor written in Go.

pdfcpu: a Go PDF processor pdfcpu is a PDF processing library written in Go supporting encryption. It provides both an API and a CLI. Supported are al

Jan 8, 2023
A simple library for generating PDF written in Go lang

gopdf gopdf is a simple library for generating PDF document written in Go lang. Features Unicode subfont embedding. (Chinese, Japanese, Korean, etc.)

Jan 3, 2023
PDF tools for reMarkable tablets

rm-pdf-tools - PDF tools for reMarkable Disclaimer: rm-pdf-tools is currently in a very early version, bugs are to be expected. Furthermore, the inten

Oct 14, 2022
A command line tool for mainly exporting logbook records from Google Spreadsheet to PDF file in EASA format
A command line tool for mainly exporting logbook records from Google Spreadsheet to PDF file in EASA format

Logbook CLI This is a command line tool for mainly exporting logbook records from Google Spreadsheet to PDF file in EASA format. It also supports rend

Feb 6, 2022
A Docker-powered stateless API for PDF files.
A Docker-powered stateless API for PDF files.

Gotenberg provides a developer-friendly API to interact with powerful tools like Chromium and LibreOffice to convert many documents (HTML, Markdown, Word, Excel, etc.) to PDF, transform them, merge them, and more!

Dec 30, 2022
PDF file parser

#pdf A pdf document parsing and modifying library The libary provides functions to parse and show elements in PDF documents. It checks the validity

Nov 7, 2021
create PDF from ASCII File for Cable labels

CableLable create PDF from ASCII File for Cable labels file format is one label per line, a line containing up to 3 words, each word is a line on the

Nov 8, 2021
Ghostinthepdf - This is a small tool that helps to embed a PostScript file into a PDF

This is a small tool that helps to embed a PostScript file into a PDF in a way that GhostScript will run the PostScript code during the

Dec 20, 2022
Go-wk - PDF Generation API with wkhtmltopdf

Simple PDF Generation API with wkhtmltopdf Quick start Clone the repo locally an

Jan 25, 2022
Newser is a simple utility to generate a pdf with you favorite news articles
Newser is a simple utility to generate a pdf with you favorite news articles

Newser A simple utility to crawl some news sites or other resources and download content into a pdf Building Make sure you have config.yaml setup and

Nov 9, 2022
PDF Annotator of Nightmares 🎃
PDF Annotator of Nightmares 🎃

PDFrankenstein is a GUI tool that intends to fill the gap on Linux where a good capable PDF annotator like Adobe Acrobat does not exist. What can you

Dec 8, 2022
Simple go script that converts csv file into a json document

csv-go-parser Simple go script that converts csv file into a json document. CSV Input: id,first_name,last_name,email,avatar,ip_address 1,Pauline,Hirth

Jun 4, 2022
Split text files into gzip files with x lines

hakgzsplit split lines of text into multiple gzip files

Jun 21, 2022
csv reader/writer and csv generator.

IO csv reader sample version 0.0.1-SNAPSHOT Goals: main: read huge file, hex substring, write to new file. repo has 2 version. v1 can read a file and

Nov 4, 2021