A simple library for generating PDF written in Go lang

Related tags

File Handling gopdf
Overview

gopdf

gopdf is a simple library for generating PDF document written in Go lang.

Features

  • Unicode subfont embedding. (Chinese, Japanese, Korean, etc.)
  • Draw line, oval, rect, curve
  • Draw image ( jpg, png )
  • Password protection
  • Font kerning

Installation

go get -u github.com/signintech/gopdf

Print text

  
package main
import (
	"log"
	"github.com/signintech/gopdf"
)

func main() {

	pdf := gopdf.GoPdf{}
	pdf.Start(gopdf.Config{ PageSize: *gopdf.PageSizeA4 })  
	pdf.AddPage()
	err := pdf.AddTTFFont("wts11", "../ttf/wts11.ttf")
	if err != nil {
		log.Print(err.Error())
		return
	}

	err = pdf.SetFont("wts11", "", 14)
	if err != nil {
		log.Print(err.Error())
		return
	}
	pdf.Cell(nil, "您好")
	pdf.WritePdf("hello.pdf")

}

Image

package main
import (
	"log"
	"github.com/signintech/gopdf"
)

func main() {
	pdf := gopdf.GoPdf{}
	pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4 })  
	pdf.AddPage()
	var err error
	err = pdf.AddTTFFont("loma", "../ttf/Loma.ttf")
	if err != nil {
		log.Print(err.Error())
		return
	}
	
	pdf.Image("../imgs/gopher.jpg", 200, 50, nil) //print image
	err = pdf.SetFont("loma", "", 14)
	if err != nil {
		log.Print(err.Error())
		return
	}
	pdf.SetX(250) //move current location
	pdf.SetY(200)
	pdf.Cell(nil, "gopher and gopher") //print text

	pdf.WritePdf("image.pdf")
}
  

Links

package main

import (
	"log"
	"github.com/signintech/gopdf"
)

func main()  {
	pdf := gopdf.GoPdf{}
	pdf.Start(gopdf.Config{ PageSize: *gopdf.PageSizeA4 }) //595.28, 841.89 = A4
	pdf.AddPage()
	err := pdf.AddTTFFont("times", "./test/res/times.ttf")
	if err != nil {
		log.Print(err.Error())
		return
	}

	err = pdf.SetFont("times", "", 14)
	if err != nil {
		log.Print(err.Error())
		return
	}

	pdf.SetX(30)
	pdf.SetY(40)
	pdf.Text("Link to example.com")
	pdf.AddExternalLink("http://example.com/", 27.5, 28, 125, 15)

	pdf.SetX(30)
	pdf.SetY(70)
	pdf.Text("Link to second page")
	pdf.AddInternalLink("anchor", 27.5, 58, 120, 15)

	pdf.AddPage()
	pdf.SetX(30)
	pdf.SetY(100)
	pdf.SetAnchor("anchor")
	pdf.Text("Anchor position")

	pdf.WritePdf("hello.tmp.pdf")

}

Draw line

pdf.SetLineWidth(2)
pdf.SetLineType("dashed")
pdf.Line(10, 30, 585, 30)

Draw oval

pdf.SetLineWidth(1)
pdf.Oval(100, 200, 500, 500)

Draw polygon

pdf.SetStrokeColor(255, 0, 0)
pdf.SetLineWidth(2)
pdf.SetFillColor(0, 255, 0)
pdf.Polygon([]gopdf.Point{{X: 10, Y: 30}, {X: 585, Y: 200}, {X: 585, Y: 250}}, "DF")

Rotation text or image

pdf.SetX(100)
pdf.SetY(100)
pdf.Rotate(270.0, 100.0, 100.0)
pdf.Text("Hello...")
pdf.RotateReset() //reset

Set transparency

Read about transparency in pdf (page 320, section 11)

// alpha - value of transparency, can be between `0` and `1`
// blendMode - default value is `/Normal` - read about [blendMode and kinds of its](https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/PDF32000_2008.pdf) `(page 325, section 11.3.5)`

transparency := Transparency{
	Alpha: 0.5,
	BlendModeType: "",
}
pdf.SetTransparency(transparency Transparency)

Password protection

package main

import (
	"log"

	"github.com/signintech/gopdf"
)


func main() {

	pdf := gopdf.GoPdf{}
	pdf.Start(gopdf.Config{
		PageSize: *gopdf.PageSizeA4, //595.28, 841.89 = A4
		Protection: gopdf.PDFProtectionConfig{
			UseProtection: true,
			Permissions: gopdf.PermissionsPrint | gopdf.PermissionsCopy | gopdf.PermissionsModify,
			OwnerPass:   []byte("123456"),
			UserPass:    []byte("123456789")},
	})

	pdf.AddPage()
	pdf.AddTTFFont("loma", "../ttf/loma.ttf")
	pdf.Cell(nil,"Hi")
	pdf.WritePdf("protect.pdf")
}

Import existing PDF

Import existing PDF power by package gofpdi created by @phpdave11 (thank you 😄 )

package main

import (
        "github.com/signintech/gopdf"
        "io"
        "net/http"
        "os"
)

func main() {
        var err error

        // Download a Font
        fontUrl := "https://github.com/google/fonts/raw/master/ofl/daysone/DaysOne-Regular.ttf"
        if err = DownloadFile("example-font.ttf", fontUrl); err != nil {
            panic(err)
        }

        // Download a PDF
        fileUrl := "https://tcpdf.org/files/examples/example_012.pdf"
        if err = DownloadFile("example-pdf.pdf", fileUrl); err != nil {
            panic(err)
        }

        pdf := gopdf.GoPdf{}
        pdf.Start(gopdf.Config{PageSize: gopdf.Rect{W: 595.28, H: 841.89}}) //595.28, 841.89 = A4

        pdf.AddPage()

        err = pdf.AddTTFFont("daysone", "example-font.ttf")
        if err != nil {
            panic(err)
        }

        err = pdf.SetFont("daysone", "", 20)
        if err != nil {
            panic(err)
        }

        // Color the page
        pdf.SetLineWidth(0.1)
        pdf.SetFillColor(124, 252, 0) //setup fill color
        pdf.RectFromUpperLeftWithStyle(50, 100, 400, 600, "FD")
        pdf.SetFillColor(0, 0, 0)

        pdf.SetX(50)
        pdf.SetY(50)
        pdf.Cell(nil, "Import existing PDF into GoPDF Document")

        // Import page 1
        tpl1 := pdf.ImportPage("example-pdf.pdf", 1, "/MediaBox")

        // Draw pdf onto page
        pdf.UseImportedTemplate(tpl1, 50, 100, 400, 0)

        pdf.WritePdf("example.pdf")

}

// DownloadFile will download a url to a local file. It's efficient because it will
// write as it downloads and not load the whole file into memory.
func DownloadFile(filepath string, url string) error {
        // Get the data
        resp, err := http.Get(url)
        if err != nil {
            return err
        }
        defer resp.Body.Close()

        // Create the file
        out, err := os.Create(filepath)
        if err != nil {
            return err
        }
        defer out.Close()

        // Write the body to file
        _, err = io.Copy(out, resp.Body)
        return err
}

Possible to set Trim-box

package main

import (
	"log"

	"github.com/signintech/gopdf"
)

func main() {
	
    pdf := gopdf.GoPdf{}
    mm6ToPx := 22.68
    
    // Base trim-box
    pdf.Start(gopdf.Config{
        PageSize: *gopdf.PageSizeA4, //595.28, 841.89 = A4
        TrimBox: gopdf.Box{Left: mm6ToPx, Top: mm6ToPx, Right: 595 - mm6ToPx, Bottom: 842 - mm6ToPx},
    })

    // Page trim-box
    opt := gopdf.PageOption{
        PageSize: gopdf.PageSizeA4, //595.28, 841.89 = A4
        TrimBox: &gopdf.Box{Left: mm6ToPx, Top: mm6ToPx, Right: 595 - mm6ToPx, Bottom: 842 - mm6ToPx},
    }
    pdf.AddPageWithOption(opt)

    if err := pdf.AddTTFFont("wts11", "../ttf/wts11.ttf"); err != nil {
        log.Print(err.Error())
        return
    }
    
    if err := pdf.SetFont("wts11", "", 14); err != nil {
        log.Print(err.Error())
        return
    }

    pdf.Cell(nil,"Hi")
    pdf.WritePdf("hello.pdf")
}

visit https://github.com/oneplus1000/gopdfsample for more samples.

Issues
  • White/Transparent text error in output PDF

    White/Transparent text error in output PDF

    Currently I am generating reports in a table format. It has been working fine for months, but suddenly I have a report for June where all the text is invisible. The text is all there, I can extract it using a tool such as pdftotext, but it is invisble when I open the PDF with any pdf viewer or pdf tool such as Scribus. For instance, the report of May generates a 16 pages PDF with no problems. Same code, for the June report, generates a 11 pages PDF with invisible text.

    I cannot share the PDF as it contains sensible information, but here is an screenshot: image

    Any idea how to solve this? Thank you

    opened by graux 20
  • Kerning support feature request

    Kerning support feature request

    Hi, gopdf developers, thanks for a nice native package. The only feature i miss is kerning support. Without kerning, generated pdf documents look non-professional. It's a weak point of almost all open source pdf libraries. Do you have plans to implement this at some point? Especially it would be great if one could add/override internal font kerning values for arbitrary character pairs because many fonts lack thorough kerning spacings.

    opened by mikamiel 10
  • An issue with precisely aligning characters over a baseline

    An issue with precisely aligning characters over a baseline

    Hi, oneplus1000, I've encountered a problem when aligning characters of different sizes/typefaces over a same baseline. Characters do not position accurately. Is there a way to precisely put arbitrary characters(of arbitrary sizes/typefaces) over a same baseline? Maybe I'm doing something wrong? Is TypoAscender() the right metric in this case?

    import (
        "github.com/signintech/gopdf"
        "github.com/signintech/gopdf/fontmaker/core"
    )
    
    func getSpecTypoAsc(fontPath string, fontSize float64) float64 {
        var parser core.TTFParser
        parser.Parse(fontPath)
        typoAsc := float64(parser.TypoAscender()) * 1000.00 / float64(parser.UnitsPerEm())
        return typoAsc * fontSize / 1000.0
    }
    
    func main() {
        arialPath := "./ttf/arial.ttf"
        dejavuPath := "./ttf/DejaVuSerif.ttf"
        pdf := gopdf.GoPdf{}
        pdf.Start(gopdf.Config{Unit: "pt", PageSize: gopdf.Rect{W: 595.28, H: 841.89}})
        pdf.AddPage()
        pdf.AddTTFFont("arial", arialPath)
        pdf.AddTTFFont("deja", dejavuPath)
        pdf.SetX(0) 
        pdf.SetY(0)
        pdf.SetFont("arial", "", 60)
        pdf.Cell(nil, "h")
        pdf.SetFont("arial", "", 30)
        pdf.SetY(getSpecTypoAsc(arialPath, 60) - getSpecTypoAsc(arialPath, 30))
        pdf.Cell(nil, "h")
        pdf.SetFont("deja", "", 20)
        pdf.SetY(getSpecTypoAsc(arialPath, 60) - getSpecTypoAsc(dejavuPath, 20))
        pdf.Cell(nil, "h")      
        pdf.WritePdf("baseline.pdf")
    }
    

    baseline-dif

    opened by mikamiel 6
  • optimize:added functions to implement add new page automatically.

    optimize:added functions to implement add new page automatically.

    Abstract

    1. Added function SetNewY() to implement add new page automatically (such as text content). 2.Added function SetNewYIfNoOffset() to implement add new page automatically (such as image content).
    2. Test case files are in /test/pagination/.
    3. In addition, the code added this time will not affect the original function. It just provides an extra option.

    Description

    1. When using pdf.SetY(),there may be cases where the content truncated because of beyond the page. image

    2. When using SetNewY(), it will paginate automatically. image

    3. Unfortunately, this method is only suitable for scenarios where gp.curr.Y changes after adding content, such as pdf.Text(). When calling the scene where gp.curr.Y does not change, such as pdf.Image(), you need to use pdf.SetNewYIfNoOffset().

    4. When using pdf.SetNewYIfNoOffset(), it will paginate automatically. image

    opened by ixuer 5
  • Draw image over rectangle

    Draw image over rectangle

    I am trying to insert an image on top of a rectangle without much success.

    pdf.SetFillColor(37, 45, 66)
    pdf.RectFromLowerLeftWithStyle(X, Y+H, W, H, "F")
    
    bytesOfImg := GetImageBytesFromOutThere()
    imgH, _ := gopdf.ImageHolderByBytes(bytesOfImg)
    imgRect := gopdf.Rect{
    	W: 200,
    	H: 300,
    }
    pdf.ImageByHolder(imgH, x, y, &imgRect)
    

    No matter what I try the picture is drawn under the rectangle.

    layer

    opened by curtiskoelling 5
  • Introduce SplitTextWithWordWrap based on text spaces.

    Introduce SplitTextWithWordWrap based on text spaces.

    Since SplitText unfortunately also splits words in case the maximum line width is exceeded the SplitTextWithWordWrap function is meant to be 'word-sensitive'. Words do not get split anymore except there is no space rune available in the current line.

    Additionally introduced: setupDefaultA4PDF() for test support to get rid of some boilerplate code.

    opened by jenpet 4
  • Letter J missing when writing text

    Letter J missing when writing text

    When using the font EB Garamond from google, the lowercase letter j does not render properly. Only the dot is printed. This is super strange. Not sure if I am doing something wrong, or if there is a special trick for some fonts. Just asking here first incase there are any obvious known issues I need to look out for before I waste a few hours trying to debug it 😀

    package main
    
    import (
    	"github.com/signintech/gopdf"
    	"log"
    )
    
    func main() {
    	pdf := gopdf.GoPdf{}
    	pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4})
    	pdf.AddPage()
    
            // Downloaded from https://fonts.google.com/specimen/EB+Garamond
    	err := pdf.AddTTFFont("EBGaramond", "EBGaramond-Regular.ttf")
    	if err != nil {
    		log.Print(err.Error())
    		return
    	}
    
    	err = pdf.SetFont("EBGaramond", "", 14)
    	if err != nil {
    		log.Print(err.Error())
    		return
    	}
    
    	pdf.SetX(30)
    	pdf.SetY(40)
    	pdf.Text("hijk")
    
    	pdf.WritePdf("test.pdf")
    }
    
    opened by zaddok 4
  • How to draw a black filled triangle?

    How to draw a black filled triangle?

    I need to draw a triangle filled with black color. I can draw a triangle using 3 calls of Line method. But I cannot find a way to fill the triangle with black color. How can I do it?

    opened by pioz 4
  • Printing png files

    Printing png files

    Good day!

    Having problems printing out png images:

    pdf := gopdf.GoPdf{}
    pdf.Start(gopdf.Config{ PageSize: gopdf.Rect{W: 505, H: 840}})
    pdf.AddPage()
    pdf.Image("img/logo.png", 0, 0, &gopdf.Rect{W: 500, H: 500});
    

    – doesn't print anything.

    bytesOfImg, err := ioutil.ReadFile("img/logo.png")
    if err != nil {
        log.Print("Can't read file")
        log.Print(err)
        return
    }
    
    imgH, err := gopdf.ImageHolderByBytes(bytesOfImg)
    if err != nil {
        log.Print("Couldn't create holder")
        log.Print(err)
        return
    }
    
    err = pdf.ImageByHolder(imgH, 0, 0, nil)
    if err != nil {
        log.Print("Couldn't print out image")
        log.Print(err)
        return
    }
    

    – and this code prints "Couldn't print out image", "EOF"

    Thank you!

    opened by krdkv 4
  • large PDF causes out of memory

    large PDF causes out of memory

    Hi,

    I'm using gopdf package to generate PDF documents, but if the PDF document is very large, such as more than 10000 A4 pages, the program eats many memory then crashes due to out of memory. Any suggestions? Thanks!

    Regards, Fan

    opened by missdeer 4
  • Question: Cell fill color

    Question: Cell fill color

    I am trying to figure out a way to set the fill color of a cell, much like the way you would draw a filled rectangle.

    pdf.RectFromUpperLeftWithStyle(x, y, 200.28, 150.89, "FD")

    Thus far, I have not seen a way to do this. I want to build a PDF with tabular data, and need to be able to fill the cell background with a certain color. As far as I can tell, I'm stuck with a white background for cells.

    opened by seeroush 4
  • Support Image(s) From Readers

    Support Image(s) From Readers

    Hi there,

    I've fiddled around with a lot of libs but this is so far the most promising one to me, so thanks for the effort you guys put into it. I'm currently facing an issue which either is caused by a misuse of the library within my code or by some missing functionality within the library itself.

    Scenario:

    I have base64 encoded images that I process within my application which are not available on disk as a binary file. The image format is a PNG and I need to add them into my generated PDFs. There are several approaches to this but the most obvious one does unfortunately not work for me.

    Approach 1: using ImageFrom()

    Decode the image and pass an image.Image variable into the lib's ImageFrom() function.

    // setup foo
    s := "<BASE64_ENCODED_IMG>"
    r := base64.NewDecoder(base64.StdEncoding, strings.NewReader(s))
    img, _, _ := image.Decode(r)
    pdf.ImageFrom(img, 0,0, nil)
    

    This results in a completely black box having the correct measurements but obviously not satisfying my actual need. Checking the ImageFrom() function puzzles me a bit since it enforces JPEG encoding independent of the actual image input.

        // ...
        go func() {
    		bw := bufio.NewWriter(w)
    		err := jpeg.Encode(bw, img, nil)
    		bw.Flush()
    		if err != nil {
    			w.CloseWithError(err)
    		} else {
    			w.Close()
    		}
    	}()
        // ...
    

    Approach 2: write to and again read from disk using Image()

    This possibility is unfortunately not a real option since I do not want to invest into housekeeping of images which are only temporarily written to the disk, re-read into the memory and then get deleted again. Nevertheless, it actually works since it utilizes different image processing logic.

    Possible Mitigation(s)

    • I completely missed a clean way to get base64 encoded PNG-typed images into a PDF page using existing functionality
    • Enhance the ImageFrom() function to take image types into account and not try to force them to be JPEGs. This might either cause an uncomfortable signature change to also pass in the type of the image which can be received by image.Decode() or some kind of an internal "re-calculation" of the type.
    • My personal favorite as of now: provide a ImageFromReader(imgReader io.Reader, x float64, y float64, rect *Rect) error function which basically does the same as ImageFrom() but without the reader-writer piping.

    Let me guys know what you think about it or give me a little push in the right direction in case I'm somehow lost.

    Regards & thanks

    opened by jenpet 2
  • (Question): How to image bytes to pdf?

    (Question): How to image bytes to pdf?

    Hello, I want to add image into PDF per page but using bytes method like img2pdf python did. I want to download from an image URL and get the raw bytes and that bytes convert into PDF, I don't want to download and create a file then convert it into PDF. How to use it?

    opened by rushkii 2
  • Import full pdf from s3

    Import full pdf from s3

    Is there a way to easy initiate a pdf object with a pdf object returned from another service (for me its S3)

    data is returned from s3 as blob data and is just a pdf file with an arbitrary amount of pages.

    could i load the file into the pfd objects buffer?

    opened by joshpauline 0
  • Error on pdf.AddTTFFont

    Error on pdf.AddTTFFont

    Thanks for the great work of this lib. However i have a small problem on printing text after importing a PDF.

    i follow the example provided in README file, but error occurred while adding "ttf" font file, the programs are (example-font.ttf does exist, for sure): err = pdf.AddTTFFont("daysone", "example-font.ttf") if err != nil { panic(err) } and the error message is: panic: Unrecognized file (font) format [recovered] panic: Unrecognized file (font) format

    Thanks in advance for any answer to this!

    opened by Xavierxhq 0
Owner
Signin Technology
Signin Technology
goldmark-pdf is a renderer for goldmark that allows rendering to PDF.

A PDF renderer for the goldmark markdown parser.

Stephen Afam-Osemene 85 May 10, 2022
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

pdfcpu 3.2k Jun 24, 2022
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

Nenad 75 May 29, 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,

null 114 Jun 22, 2022
A PDF document generator with high level support for text, drawing and images

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

null 140 Jun 22, 2022
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

Niels Saurer 11 Jun 18, 2022
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

Vladimir Simakhin 0 Feb 6, 2022
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!

Gotenberg 3.8k Jun 29, 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

null 0 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

null 0 Nov 8, 2021
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.

null 0 Nov 29, 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

Emil Lerner 123 Jun 18, 2022
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

Elia 0 Jan 10, 2022
Go-wk - PDF Generation API with wkhtmltopdf

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

Gustavo Andrioli 0 Jan 25, 2022
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

Mansour Behabadi 145 Jun 20, 2022
Dirmap is a tool for generating a directory map.

dirmap ?? dirmap is a tool for generating a directory map. It extracts a part of the document from markdown or source code of each directory and uses

Ken’ichiro Oyama 10 May 20, 2022
Go-lang based sonos standup system

Overview This is an CLI tool that can handle timed standup playback on a sonos device. It allows you to add links to audio files that will be randomly

null 1 Nov 23, 2021
goelftools is library written in Go for parsing ELF file.

goelftools goelftools is library written in Go for parsing ELF file. This library is inspired by pyelftools and rbelftools. Motivation The motivation

null 28 Jun 30, 2022
GoCsv is a library written in pure Go to use csv data more comfortable

GoCsv GoCsv is a library written in pure Go to use csv data more comfortable Supported Go version golang >= 1.13 Installation go get github.com/shr004

Herald 4 Nov 25, 2021