A minimalist Go PDF writer in 1982 lines. Draws text, images and shapes. Helps understand the PDF format. Used in production for reports.

one-file-pdf - A minimalist PDF generator in <2K lines and 1 file

Go Report Card Build Status Test Coverage Gitter chat godoc License: MIT

The main idea behind this project was:
"How small can I make a PDF generator for it to still be useful for 80% of common PDF generation needs?"

The result is a single .go file with less than 1999 lines of code, about 400 of which are color and glyph-size constants, and ~350 are comments.

  • It's easier to learn about the internals of the PDF format with a small, concise library.
  • The current version of the file is indicated in the header (the timestamp).

Features:

  • The essentials for generating PDF documents, sufficient for common business reports.
  • Use all built-in PDF fonts: Courier, Helvetica, Symbol, Times, ZapfDingbats, and their variants
  • Specify colo(u)rs by name (144 web colors), HTML codes (#RRGGBB) or RGB value
  • Set columns for text (like tab stops on the page)
  • Built-in grid option to help measurement and positioning
  • Metadata properties: author, creator, keywords, subject and title
  • Set the measurement units you want: mm, cm, inches, twips or points
  • Draw lines with different thickness
  • Filled or outline rectangles, circles and ellipses
  • JPEG, GIF and transparent PNG images (filled with specified background color)
  • Stream compression can be turned on or off (PDF files normally compress streams to reduce file size, but turning it off helps in debugging or learning about PDF commands)

Not Yet Supported:

  • Unicode (requires font embedding)
  • Font embedding
  • PDF encryption
  • Paths, curves and complex graphics

Installation:

    go get github.com/balacode/one-file-pdf

Naming Convention:

All types in are prefixed with PDF for public, and 'pdf' for private types. The only type you need to use is PDF, while PDFColorNames are left public for reference.

Hello World:

package main 

import (
	"fmt"
	"github.com/balacode/one-file-pdf"
)

func main() {
    fmt.Println(`Generating a "Hello World" PDF...`)

    // create a new PDF using 'A4' page size
    var pdf = pdf.NewPDF("A4")

    // set the measurement units to centimeters
    pdf.SetUnits("cm")

    // draw a grid to help us align stuff (just a guide, not necessary)
    pdf.DrawUnitGrid()

    // draw the word 'HELLO' in orange, using 100pt bold Helvetica font
    // - text is placed on top of, not below the Y-coordinate
    // - you can use method chaining
    pdf.SetFont("Helvetica-Bold", 100).
        SetXY(5, 5).
        SetColor("Orange").
        DrawText("HELLO")

    // draw the word 'WORLD' in blue-violet, using 100pt Helvetica font
    // note that here we use the colo(u)r hex code instead
    // of its name, using the CSS/HTML format: #RRGGBB
    pdf.SetXY(5, 9).
        SetColor("#8A2BE2").
        SetFont("Helvetica", 100).
        DrawText("WORLD!")

    // draw a flower icon using 300pt Zapf-Dingbats font
    pdf.SetX(7).SetY(17).
        SetColorRGB(255, 0, 0).
        SetFont("ZapfDingbats", 300).
        DrawText("a")

    // save the file:
    // if the file exists, it will be overwritten
    // if the file is in use, prints an error message
    pdf.SaveFile("hello.pdf")
} //                                                                        main

Samples:

Click on a sample to see the PDF in more detail.

"Hello World!" sample image

"Synergy Ipsum" sample image

Changelog:

These are the most recent changes in the functionality of the package, not including internal changes which are best seen in the commits history.

2018-04-14

  • Changed CurrentPage from read-only to read/write property: added SetCurrentPage()
  • Created PageCount() read-only property
  • Created dingbats() demo to generate zapf_dingbats_table.pdf. You can use this table to look up the hex code for each icon.
  • Changed text encoding from /WinAnsiEncoding to /StandardEncoding

See changelog.md for changes made earlier.

Roadmap:

  • Achieve 100% test coverage
  • Create a unit test for every method
  • Unicode support
  • Partial font embedding
Comments
  • No support for simple color (RGB) PNG images

    No support for simple color (RGB) PNG images

    I have been experimenting with using color PNG images with DrawImage() method, and so far found this to work with just a two line change. Is there much more than this needed in order to officially support color images instead of grayscale?

    screen shot 2018-03-11 at 10 34 59 pm screen shot 2018-03-11 at 10 35 20 pm

  • Return error(s) where possible please

    Return error(s) where possible please

    How to know that SaveFile failed except by reading log? Please return errors instead of logging them.

    Application code should log, libraries should not log but return errors.

    Other than that good library looking forward using it. Thanks.

  • tests: Add tests to ToColor function

    tests: Add tests to ToColor function

    Hi @balacode,

    Firstly thanks for this great package.

    I'd like to help you and I've started adding some tests on ToColor function. I implemented it in a different way from what you already have in the package, but in another hand table driven tests are a standard way to test in Go ecosystem.

    Perhaps we could move the hex code to another private method, but let's keep it simple for now.

    Feel free to reach me regarding any part of it. Thanks again!

  • How to support Unicode in the PDF format?

    How to support Unicode in the PDF format?

    Unicode support is essential in modern software, so we are going to implement some kind of Unicode support in this PDF writer. If you know or can link to any information about font embedding (to enable Unicode) or just referencing external fonts installed on the system in order to use Unicode, please let me know. Thanks for your attention.

  • PDF Metadata not properly encoded

    PDF Metadata not properly encoded

    The metadata fields like Title, Subject, Author, etc. are not shown in the rendered PDF because the /Type/Info object isn't properly delimited by the code.

    To fix this, add call to pdf.writeObj near line 1081, like so:

    screen shot 2018-03-05 at 10 43 19 am

  • SaveFile method creates unreadable file

    SaveFile method creates unreadable file

    In SaveFile, ioutil.WriteFile is used to save the file without any file attributes. Therefore, the file cannot be read until one performs a chmod to set reasonable attributes.

    var err = ioutil.WriteFile(filename, pdf.Bytes(), 0)

    should be

    var err = ioutil.WriteFile(filename, pdf.Bytes(), 0644)

  • ZapfDingbats icons not rendered on Debian Linux 9 (squeeze) - probably extraneous issue

    ZapfDingbats icons not rendered on Debian Linux 9 (squeeze) - probably extraneous issue

    The flower icon in the hello.pdf file is not rendered on Debian while using the default PDF viewer. But ZapfDingbats is a standard PDF font. Probably, this may be a Debian issue, but I would appreciate any info if you experienced something similar on your OS, or PDF reader app. #

  • png_images.pdf (demo) is larger than estimated

    png_images.pdf (demo) is larger than estimated

    The generated png_images.pdf is about 6MB in size, but based on my estimates it should be under 3MB:

    dice.png is 420 x 315 pixels = 132,300 pixels 132,300 pixels x 3 colors = 396,900 bytes for RGB data 396,900 x 5 background varieties = 1,984,500 bytes

    gophers.png is 600 x 476 pixels = 285,600 pixels 285,600 x 3 colors = 856,800 bytes for RGB data

    Additional data for PDF commands, let's say 200K

    The file size should be about 3MB, but the generated demo is 6MB

    ** What to consider: **

    • Is the library reusing all repeated images?
    • Can the image byte stream be compressed to save space?
  • Larger charset

    Larger charset

    Release 1.0.1 seems to be restricted to pure ASCII. Would it be possible to extend it to PDF encoding as described on https://gist.github.com/zmughal/5130211 ? Unless it diverts work away from full unicode support of course.

    I tried to use one-file-pdf for Swedish in https://github.com/jonasgit/pdfhw but it seems to fail. Unless I did something wrong?

  • PNG embedding is slow

    PNG embedding is slow

    Noticeable time (about 1 second) is spent when generating png_images.pdf

    • Is the library regenerating every PNG image, even if it is repeated?
    • If decoding and re-encoding the image data in a PDF stream is a slow operation, then goroutines could be used to speed up the process.
Optimized bit-level Reader and Writer for Go.

bitio Package bitio provides an optimized bit-level Reader and Writer for Go. You can use Reader.ReadBits() to read arbitrary number of bits from an i

Dec 1, 2022
A Go package that reports processor topology

Description ------------ cpu package reports (some) processor topology information Note that the term package refers to a physical processor

Nov 5, 2022
A reverse-proxy cache for external images used on LinuxFr.org

External images on LinuxFr.org Our users can use images from external domains on LinuxFr.org. This component is a reverse-proxy / cache for these imag

May 14, 2021
Packer Plugin Vagrant - The Vagrant multi-component plugin can be used with HashiCorp Packer to create custom images

Packer Plugin Vagrant - The Vagrant multi-component plugin can be used with HashiCorp Packer to create custom images

Jul 13, 2022
Highly extensible, customizable application launcher and window switcher written in less than 300 lines of Golang and fyne
Highly extensible, customizable application launcher and window switcher written in less than 300 lines of Golang and fyne

golauncher A go application launcher A simple, highly extensible, customizable application launcher and window switcher written in less than 300 lines

Aug 21, 2022
Minimalist and opinionated feed reader
Minimalist and opinionated feed reader

Miniflux 2 Miniflux is a minimalist and opinionated feed reader: Written in Go (Golang) Works only with Postgresql Doesn't use any ORM Doesn't use any

Jan 3, 2023
gopbin is a minimalist and opinionated pastebin implementation written in Go.

gopbin gopbin is a minimalist and opinionated pastebin implementation written in

Dec 28, 2021
mackerel metric plugin for count lines in log

mackerel metric plugin for count lines in log

Nov 13, 2021
Print lines matching a pattern in repositories using GitHub API
Print lines matching a pattern in repositories using GitHub API

gh-grep Print lines matching a pattern in repositories using GitHub API Usage $ gh grep func.*schema.Schema --include=**/*.go --owner k1LoW --repo tbl

Dec 1, 2022
James is your butler and helps you to create, build, debug, test and run your Go projects
James is your butler and helps you to create, build, debug, test and run your Go projects

go-james James is your butler and helps you to create, build, debug, test and run your Go projects. When you often create new apps using Go, it quickl

Oct 8, 2022
Helps exercise your memory by giving you random tokens and poems to memorize.

memory-enhancer Helps exercise your memory by giving you random tokens and poems to memorize. Using Every day when you first open your terminal you wi

Nov 9, 2021
modver - a Go package and command that helps you obey semantic versioning rules in your Go module.

Modver This is modver, a Go package and command that helps you obey semantic versioning rules in your Go module. It can read and compare two different

Dec 12, 2022
wkhtmltopdf Go bindings and high level interface for HTML to PDF conversion
wkhtmltopdf Go bindings and high level interface for HTML to PDF conversion

wkhtmltopdf Go bindings and high level interface for HTML to PDF conversion. Implements wkhtmltopdf Go bindings. It can be used to convert HTML docume

Dec 17, 2022
An operator that helps you perform benchmarks

Camunda-Benchmark-Operator ??️‍♀️ An operator that helps you perform benchmarks. Your first benchmark This requires that you know how to run the opera

Mar 2, 2022
HTTP service to generate PDF from Json requests

pdfgen HTTP service to generate PDF from Json requests Install and run The recommended method is to use the docker container by mounting your template

Dec 2, 2022
A vitamin C rich, book, pdf & documentation brewing library for e-readers/e-ink readers
A vitamin C rich, book, pdf & documentation brewing library for e-readers/e-ink readers

go-Cbook A vitamin C rich, book, pdf & documentation brewing library for e-readers/e-ink readers. Now take priviliges of (eye-safe) e-readers to read

Dec 28, 2021
Get and save EroCool.com images

Get and save EroCool.com images

Nov 9, 2021
Parse a shell script and output all export declarations in an easy to read format

Find Exports Parse a shell script and output all export declarations in an easy to read format. Usage Example $ findexports ~/.bashrc PATH=$PATH:/usr/

Jan 13, 2022
The new home of the CUE language! Validate and define text-based and dynamic configuration

The CUE Data Constraint Language Configure, Unify, Execute CUE is an open source data constraint language which aims to simplify tasks involving defin

Dec 31, 2022