gopdf

package module
v1.0.91 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 13, 2023 License: MIT Imports: 12 Imported by: 0

README

race result AG is always looking for smart, passionate and hard-working Golang and Javascript developers with both strong attention to the detail and an entrepreneurial approach to tasks.

We are a Germany-based company building technology for timing sports events such London Marathon, Challenge Roth, Tour Down Under and thousands of other races in more than 80 countries. Check out www.raceresult.com and karriere.raceresult.com for more information.

gopdf - Free PDF creator in pure Golang

Go code (golang) to create PDF documents with several layers of abstraction that allow both, easy placement of elements on pages and accessing lower layers to implement any type of PDF object / operator.

Does support Composite Fonts for full Unicode support.

Getting Started

The highest level of abstraction is provided by the gopdf package. Simply create a new Builder object, add pages and add elements to the pages:

package yours

import (
    "github.com/raceresult/gopdf"
    "github.com/raceresult/gopdf/types"
)

func TestExample1(t *testing.T) {
    // create new PDF Builder
    pb := gopdf.New()
    
    // use a built-in standard fontm
    f, err := pb.NewStandardFont(types.StandardFont_Helvetica, types.EncodingWinAnsi)
    if err != nil {
        t.Error(err)
        return
    }
    
    // add first page
    p := pb.NewPage(gopdf.GetStandardPageSize(gopdf.PageSizeA4, false))
    
    // add "hello world" element
	p.AddElement(&gopdf.TextElement{
		TextChunk: gopdf.TextChunk{
			Text:     "hello world",
			Font:     f,
			FontSize: 36,
		},
		Left:      gopdf.MM(105),
		Top:       gopdf.MM(100),
		TextAlign: gopdf.HorizontalAlignCenter,
	})
    
    // output
    bts, err := pb.Build()
    ...
}

More advanced: let's add an image, a rectangle and a text using a composite font. Using a composite font, any unicode character can be mapped to any glyph in one or more fonts. Non-composite fonts, on the contrary, only support 256 different characters, so in a world of UTF-8/Unicode, composite fonts are the only thing you want to use. Character encoding and subsetting (embed fonts reduced to only those characters you are using) is quite sophisticated but completely handled by the pdf package. When using Composite Fonts you only need to handover normal (UTF-8 encoded) Go strings.

package yours

import (
    "github.com/raceresult/gopdf/builder"
    "github.com/raceresult/gopdf/types"
)

func TestExample2(t *testing.T) {
    // create new PDF Builder
    pb := gopdf.New()
    
    // add first page
    p := pb.NewPage(gopdf.GetStandardPageSize(gopdf.PageSizeA4, false))
    
    // add image
    bts, err := ioutil.ReadFile("myImage.jpg")
    if err != nil {
        t.Error(err)
        return
    }
    img, err := pb.NewImage(bts)
    if err != nil {
        t.Error(err)
        return
    }
    p.AddElement(&gopdf.ImageElement{
        Width:  gopdf.MM(70),
        Height: gopdf.MM(70 * float64(img.Image.Height) / float64(img.Image.Width)),
        Left:   gopdf.MM(20),
        Top:    gopdf.MM(20),
        Img:    img,
    })
    
    // add rectangle
	p.AddElement(&gopdf.TextElement{
		TextChunk: gopdf.TextChunk{
			Text:         "hello world - 漢語",
			Font:         f,
			FontSize:     36,
			Color:        gopdf.NewColorRGB(200, 200, 200),
			OutlineColor: gopdf.NewColorRGB(10, 20, 10),
			OutlineWidth: gopdf.MM(0.5),
		},
		Left: gopdf.MM(20),
		Top:  gopdf.MM(100),
	})
    
    // add composite font
    bts, err = ioutil.ReadFile("arialuni.ttf")
    if err != nil {
        t.Error(err)
        return
    }
    f, err := pb.NewCompositeFont(bts)
    if err != nil {
        t.Error(err)
        return
    }
    
    // add text using composite font
    p.AddElement(&gopdf.TextElement{
        Text:         "hello world - 漢語",
        Font:         f,
        FontSize:     36,
        Left:         gopdf.MM(20),
        Top:          gopdf.MM(100),
        Color:        gopdf.ColorRGB{200, 200, 200},
        OutlineColor: gopdf.ColorRGB{10, 20, 10},
        OutlineWidth: gopdf.MM(0.5),
    })
    
    
    // output
    bts, err := pb.Build()
    ...
}

This way, the builder supports the following element types with various attributes:

  • images (supports jpg, png, gif, bmp)
  • lines
  • rectangles (filled or unfilled)
  • texts
  • textboxes (text with max width, opt. max height, word wrap, ..)

Advanced: Add your own functionality

The following section describes how to go one level deeper and add custom functionality that is not yet provided by the builder package.

First of all, a quick overview of the PDF file format: PDF files are a set of "objects" that are referenced by other objects. For example, the root is the "Document Catalog" which references to the "Page Tree" which references to the individual page objects. Each page references to resources like images or fonts, and also to a "Content Stream" that contains the commands to draw text, images, or graphical elements.

The content stream is a list of "Operators" with "Operands", you could also call them function calls. Some functions change a state, for example set the drawing position or change the drawing color, others actually draw the text/image/line/...

Please take a look at the PDF Reference manual. You may have to use it look up the functions you need to use for your needs.

Let's assume you need a custom function to draw a cubic Bézier curve. The operators for this are:

  • "m": move to position
  • "c": add bezier curve to current path line
  • "S": stroke the path line.

Most operators have been implemented in the package "pdf" (even if there are no elements in the builder package using them). In this example, the functions needed are:

func (q *Page) Path_m(x, y float64)

func (q *Page) Path_c(x1, y1, x2, y2, x3, y3 float64)

func (q *Page) Path_S()

You can easily create your own element type for the Builder, it only needs to fulfill the Element interface:

type Element interface {
    Build(page *pdf.Page)
}

For example:

type BezierCurve struct {
    X, Y Length
    X1, Y1, X2, Y2, X3, Y3 Length
}

func (q *BezierCurve) Build(page *pdf.Page) error {
    page.Path_m(q.X.Pt(), q.Y.Pt())
    page.Path_c(q.X1.Pt(), q.Y1.Pt(), q.X2.Pt(), q.Y2.Pt(), q.X3.Pt(), q.Y3.Pt())
    page.Path_S()
	return nil
}

An instance of BezierCurve can now be added to a page using the AddElement method.

If you need to use operators that are not implemented in the pdf package, you can use the general function AddCommand:

func (q *Page) AddCommand(operator string, args ...types.Object)

If, however, the operator is implemented, please use the associated function to avoid unexpected behavior. In order to minimize the size of the PDF file, the pdf package keeps tracking of the current text and graphics state and ignores function call, that would not change the state, for example:

func (q *Page) TextState_Tc(charSpace float64) {
    if q.textState.Tc == charSpace {
        return
    }
    q.textState.Tc = charSpace
    
    q.AddCommand("Tc", types.Int(charSpace))
}

If you would call AddCommand("Tc", ...) instead of TextState_Tc, the internal textState would not be updated and you may see unexpected behavior later in your program.


Installation

To install GoPDF, use go get:

go get github.com/raceresult/gopdf

Staying up to date

To update GoPDF to the latest version, use go get -u github.com/raceresult/gopdf.


Supported go versions

We currently support the most recent major Go versions from 1.16 onward.


Contributing

Please feel free to submit issues, fork the repository and send pull requests!

When submitting an issue, we ask that you please include a complete test function that demonstrates the issue.


License

This project is licensed under the terms of the MIT license.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ColorRGBBlack = ColorRGB{R: 0, G: 0, B: 0}

Functions

This section is empty.

Types

type BarcodeElement added in v1.0.20

type BarcodeElement struct {
	Left, Top, Width, Height Length
	Text                     string
	Color                    Color
	Rotate                   float64
	Flipped                  bool
	Type                     BarcodeType
	Transparency             float64
}

BarcodeElement is used to add a barcode to a page

func (*BarcodeElement) Build added in v1.0.20

func (q *BarcodeElement) Build(page *pdf.Page) error

Build adds the element to the content stream

type BarcodeType added in v1.0.31

type BarcodeType int
const (
	BarcodeType39    BarcodeType = 1
	BarcodeTypeEAN13 BarcodeType = 2
	BarcodeType128   BarcodeType = 3
)

type Builder

type Builder struct {
	Info types.InformationDictionary
	ID   [2]string

	// Threshold length for compressing content streams
	CompressStreamsThreshold int

	// PDF Version number
	Version float64

	// number of worker routines used to generate content streams of pages
	WorkerRoutines int
	// contains filtered or unexported fields
}

Builder is the main object to build a PDF file

func New

func New() *Builder

New creates a new Builder object

func (*Builder) AddElement added in v1.0.54

func (q *Builder) AddElement(item ...Element)

AddElement adds one or more elements to the current page

func (*Builder) Build

func (q *Builder) Build() ([]byte, error)

Build builds the PDF document and returns the file as byte slice

func (*Builder) CurrPage added in v1.0.54

func (q *Builder) CurrPage() *Page

CurrPage returns the current page

func (*Builder) NewCapturedPage

func (q *Builder) NewCapturedPage(sourcePage types.Page, sourceFile *pdffile.File) (*Form, error)

NewCapturedPage adds a new captured page to the PDF file

func (*Builder) NewCompositeFont

func (q *Builder) NewCompositeFont(ttf []byte) (*pdf.CompositeFont, error)

NewCompositeFont adds a font as composite font to the pdf, i.e. with Unicode support

func (*Builder) NewCompositeFontFromOTF added in v1.0.31

func (q *Builder) NewCompositeFontFromOTF(otf []byte) (*pdf.CompositeFontOTF, error)

NewCompositeFontFromOTF adds an otf font as composite font to the pdf, i.e. with Unicode support

func (*Builder) NewFormFromPage added in v1.0.26

func (q *Builder) NewFormFromPage(page *Page) (*Form, error)

NewFormFromPage creates a new form object from the give page

func (*Builder) NewImage

func (q *Builder) NewImage(bts []byte) (*pdf.Image, error)

NewImage adds a new image to the PDF file

func (*Builder) NewPage

func (q *Builder) NewPage(size PageSize) *Page

NewPage adds a new page to the pdf

func (*Builder) NewPageBefore added in v1.0.20

func (q *Builder) NewPageBefore(size PageSize, beforePageNo int) *Page

NewPageBefore inserts a new page before the given pageNo to the pdf

func (*Builder) NewStandardFont

func (q *Builder) NewStandardFont(name types.StandardFontName, encoding types.Encoding) (*pdf.StandardFont, error)

NewStandardFont adds a new standard font (expected to be available in all PDF consuming systems) to the pdf

func (*Builder) NewTrueTypeFont

func (q *Builder) NewTrueTypeFont(ttf []byte, encoding types.Encoding, embed bool) (*pdf.TrueTypeFont, error)

NewTrueTypeFont adds a new TrueType font to the pdf

func (*Builder) PageCount

func (q *Builder) PageCount() int

PageCount returns the number of pages already added

func (*Builder) SelectPage added in v1.0.54

func (q *Builder) SelectPage(pageNo int) error

SelectPage set the current page to the page with the given number (starting from 1)

type CircleElement added in v1.0.20

type CircleElement struct {
	X, Y, Radius Length
	LineWidth    Length
	LineColor    Color
	FillColor    Color
	DashPattern  DashPattern
	Transparency float64
}

CircleElement is used to add a circle to a page

func (*CircleElement) Build added in v1.0.20

func (q *CircleElement) Build(page *pdf.Page) error

Build adds the element to the content stream

type Color

type Color interface {
	Build(page *pdf.Page, stroke bool)
}

Color is the interface any type of color needs to fulfill

func ParseColor added in v1.0.31

func ParseColor(s string) (Color, error)

ParseColor parses a string to a color. Can be r,g,b or c,m,y,k or #RRGGBB

type ColorCMYK

type ColorCMYK struct {
	C int
	M int
	Y int
	K int
}

ColorCMYK represents a CMYK color value

func NewColorCMYK

func NewColorCMYK(c, m, y, k int) ColorCMYK

NewColorCMYK creates a new ColorCMYK object

func (ColorCMYK) Build

func (q ColorCMYK) Build(page *pdf.Page, stroke bool)

Build sets the color in the graphics state of the given page

type ColorGray

type ColorGray struct {
	Gray int
}

ColorGray represents a gray color value

func NewColorGray

func NewColorGray(gray int) ColorGray

NewColorGray creates a new ColorGray object

func (ColorGray) Build

func (q ColorGray) Build(page *pdf.Page, stroke bool)

Build sets the color in the graphics state of the given page

type ColorRGB

type ColorRGB struct {
	R int
	G int
	B int
}

ColorRGB represents a RGB color value

func NewColorRGB

func NewColorRGB(r, g, b int) ColorRGB

NewColorRGB creates a new ColorRGB object

func (ColorRGB) Build

func (q ColorRGB) Build(page *pdf.Page, stroke bool)

Build sets the color in the graphics state of the given page

type DashPattern added in v1.0.22

type DashPattern struct {
	Phase Length
	Array []Length
}

DashPattern represents a dash pattern

func NewDashPattern added in v1.0.22

func NewDashPattern(phase Length, array ...Length) DashPattern

NewDashPattern creates a new DashPattern object

func (DashPattern) Build added in v1.0.22

func (q DashPattern) Build(page *pdf.Page) error

Build sets the dash pattern in the graphics state of the given page

type Element

type Element interface {
	Build(page *pdf.Page) error
}

Element is the interface any object needs to fulfill to be added to the content stream of a page

type EllipseElement added in v1.0.22

type EllipseElement struct {
	Left, Top, Width, Height Length
	LineWidth                Length
	LineColor                Color
	FillColor                Color
	DashPattern              DashPattern
	Transparency             float64
}

EllipseElement is used to add an ellipse to a page

func (*EllipseElement) Build added in v1.0.22

func (q *EllipseElement) Build(page *pdf.Page) error

Build adds the element to the content stream

type Form added in v1.0.26

type Form struct {
	Left, Top, Width, Height Length
	BBox                     types.Rectangle
	Form                     types.Reference
}

Form is used to add a captured page from another document to a page

func (*Form) Build added in v1.0.26

func (q *Form) Build(page *pdf.Page) error

Build adds the element to the content stream

func (*Form) PageSize added in v1.0.26

func (q *Form) PageSize() PageSize

PageSize returns the page size of the captured page

type HorizontalAlign added in v1.0.35

type HorizontalAlign int
const (
	HorizontalAlignLeft   HorizontalAlign = 0
	HorizontalAlignCenter HorizontalAlign = 1
	HorizontalAlignRight  HorizontalAlign = 2
)

type ImageBoxElement

type ImageBoxElement struct {
	Left, Top, Width, Height Length
	Img                      *pdf.Image
	VerticalAlign            VerticalAlign
	HorizontalAlign          HorizontalAlign
	Rotate                   float64
	Transparency             float64
}

ImageBoxElement is used to add an image box to a page

func (*ImageBoxElement) Build

func (q *ImageBoxElement) Build(page *pdf.Page) error

Build adds the element to the content stream

type ImageElement

type ImageElement struct {
	Img                      *pdf.Image
	Left, Top, Width, Height Length
	Rotate                   float64
	Transparency             float64
}

ImageElement is used to add an image to a page

func (*ImageElement) Build

func (q *ImageElement) Build(page *pdf.Page) error

Build adds the element to the content stream

type Length

type Length struct {
	Value float64
	Unit  LinearMeasure
}

Length represents a length using a certain measure

func Inch

func Inch(inch float64) Length

Inch creates a Length measured in inch

func MM

func MM(mm float64) Length

MM creates a Length measured in mm

func Pt

func Pt(pt float64) Length

Pt creates a Length measured in pt

func (Length) Mm

func (q Length) Mm() float64

Mm converts the value to millimeters

func (Length) Pt

func (q Length) Pt() float64

Pt converts the value to pt

type LineElement

type LineElement struct {
	X1, Y1, X2, Y2 Length
	LineWidth      Length
	Color          Color
	DashPattern    DashPattern
	Transparency   float64
}

LineElement is used to add a line to a page

func (*LineElement) Build

func (q *LineElement) Build(page *pdf.Page) error

Build adds the element to the content stream

type LinearMeasure

type LinearMeasure int

LinearMeasure represents a linear measure like mm or inch.

const (
	UnitPt LinearMeasure = iota
	UnitMM
	UnitInch
)

type Page

type Page struct {
	Width  Length
	Height Length
	Rotate int
	// contains filtered or unexported fields
}

Page represents on page in the PDF document to which elements can be added arbitrarily

func NewPage

func NewPage(size PageSize) *Page

NewPage creates a new Page object with the given page size

func (*Page) AddElement

func (q *Page) AddElement(item ...Element)

AddElement adds one or more elements to the page

type PageSize

type PageSize [2]Length

PageSize is width x height

func GetStandardPageSize

func GetStandardPageSize(size StandardPageSize, landscape bool) PageSize

GetStandardPageSize returns a standard page size like DIN-A4 in either portrait or landscape

type QRCodeElement added in v1.0.23

type QRCodeElement struct {
	Left, Top, Size Length
	Text            string
	Color           Color
	RecoveryLevel   qrcode.RecoveryLevel
	Rotate          float64
	Transparency    float64
}

QRCodeElement is used to add a QRCode to a page

func (*QRCodeElement) Build added in v1.0.23

func (q *QRCodeElement) Build(page *pdf.Page) error

Build adds the element to the content stream

type RectElement

type RectElement struct {
	Left, Top, Width, Height Length
	LineWidth                Length
	LineColor                Color
	FillColor                Color
	DashPattern              DashPattern
	Rotate                   float64
	Transparency             float64
}

RectElement is used to add a rectangle to a page

func (*RectElement) Build

func (q *RectElement) Build(page *pdf.Page) error

Build adds the element to the content stream

type StandardPageSize

type StandardPageSize int

StandardPageSize is used for GetStandardPageSize to get a standard page size like DIN-A4

const (
	PageSizeA0 StandardPageSize = iota
	PageSizeA1
	PageSizeA2
	PageSizeA3
	PageSizeA4
	PageSizeA5
	PageSizeA6
	PageSizeA7
	PageSizeLetter
	PageSizeLegal
)

type TextBoxElement

type TextBoxElement struct {
	TextElement
	Width, Height   Length
	VerticalAlign   VerticalAlign
	HeightBufferRel float64
}

TextBoxElement is similar to TextElement, but can have a maximum width and height

func (*TextBoxElement) Build

func (q *TextBoxElement) Build(page *pdf.Page) error

Build adds the element to the content stream

func (*TextBoxElement) ShrinkToFit added in v1.0.65

func (q *TextBoxElement) ShrinkToFit()

ShrinkToFit reduces the font size so that the entire text fits into the box

func (*TextBoxElement) TextHeight

func (q *TextBoxElement) TextHeight() Length

TextHeight returns the height of the text, accounting for line breaks and max width

type TextChunk added in v1.0.62

type TextChunk struct {
	Text          string
	Font          pdf.FontHandler
	FontSize      float64
	Color         Color
	OutlineColor  Color
	OutlineWidth  Length
	DashPattern   DashPattern
	Bold          bool
	Italic        bool
	Underline     bool
	StrikeThrough bool
	CharSpacing   Length
	TextScaling   float64
}

func (*TextChunk) FontHeight added in v1.0.62

func (q *TextChunk) FontHeight() Length

FontHeight returns the height of the font (bounding box y min to max)

type TextChunkBoxElement added in v1.0.62

type TextChunkBoxElement struct {
	Chunks []TextChunk

	Transparency    float64
	LineHeight      float64
	Left, Top       Length
	Width, Height   Length
	Rotate          float64
	TextAlign       HorizontalAlign
	VerticalAlign   VerticalAlign
	HeightBufferRel float64
}

TextChunkBoxElement is similar to TextBoxElement, but can have chunks with different format

func (*TextChunkBoxElement) Build added in v1.0.62

func (q *TextChunkBoxElement) Build(page *pdf.Page) error

Build adds the element to the content stream

func (*TextChunkBoxElement) ShrinkToFit added in v1.0.65

func (q *TextChunkBoxElement) ShrinkToFit()

ShrinkToFit reduces the font size so that the entire text fits into the box

func (*TextChunkBoxElement) TextHeight added in v1.0.62

func (q *TextChunkBoxElement) TextHeight() Length

TextHeight returns the height of the text, accounting for line breaks and max width

type TextElement

type TextElement struct {
	TextChunk
	Left, Top    Length
	TextAlign    HorizontalAlign
	LineHeight   float64
	Rotate       float64
	Transparency float64
}

TextElement draws a text, may have line breaks

func (*TextElement) Build

func (q *TextElement) Build(page *pdf.Page) error

Build adds the element to the content stream

func (*TextElement) FontHeight added in v1.0.31

func (q *TextElement) FontHeight() Length

FontHeight returns the height of the font (bounding box y min to max)

func (*TextElement) TextHeight

func (q *TextElement) TextHeight() Length

TextHeight returns the height of the text, accounting for line breaks

type VerticalAlign

type VerticalAlign int
const (
	VerticalAlignTop    VerticalAlign = 0
	VerticalAlignMiddle VerticalAlign = 1
	VerticalAlignBottom VerticalAlign = 2
)

Directories

Path Synopsis
pdf
standardfont/afm
Package afm implements a decoder for AFM (Adobe Font Metrics) files.
Package afm implements a decoder for AFM (Adobe Font Metrics) files.
standardfont/fixed
Package fixed provides types to work with fixed-point numbers.
Package fixed provides types to work with fixed-point numbers.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL