gopdf

package module
v1.0.18 Latest Latest
Warning

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

Go to latest
Published: Oct 25, 2022 License: MIT Imports: 4 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{
        Text:      "hello world",
        FontSize:  36,
        X:         gopdf.MM(105),
        Y:         gopdf.MM(100),
        TextAlign: gopdf.TextAlignCenter,
        Font:      f,
    })
    
    // 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.RectElement{
        X1:        gopdf.MM(20),
        Y1:        gopdf.MM(150),
        Width:     gopdf.MM(50),
        Height:    gopdf.MM(30),
        LineWidth: gopdf.MM(3),
        LineColor: gopdf.ColorRGB{0, 255, 0},
        FillColor: gopdf.ColorRGB{255, 0, 255},
    })
    
    // 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,
        X:            gopdf.MM(20),
        Y:            gopdf.MM(100),
        Color:        gopdf.ColorRGB{200, 200, 200},
        OutlineColor: gopdf.ColorRGB{10, 20, 10},
        RenderMode:   types.RenderingModeFillAndStroke,
        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) {
    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()
}

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 Builder

type Builder struct {
	Info            types.InformationDictionary
	ID              [2]string
	CompressStreams bool
	Version         float64
	// 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) Build

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

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

func (*Builder) NewCapturedPage

func (q *Builder) NewCapturedPage(sourcePage types.Page, sourceFile *pdffile.File) (*CapturedPage, 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) 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) 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

type CapturedPage

type CapturedPage struct {
	CapturedPage *pdf.CapturedPage
	Left         Length
	Top          Length
}

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

func (*CapturedPage) Build

func (q *CapturedPage) Build(page *pdf.Page)

Build adds the element to the content stream

func (*CapturedPage) PageSize added in v1.0.16

func (q *CapturedPage) PageSize() PageSize

PageSize returns the page size of the captured page

type Color

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

Color is the interface any type of color needs to fulfill

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 set 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 set 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 set the color in the graphics state of the given page

type Element

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

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

type ImageBoxElement

type ImageBoxElement struct {
	Img             *pdf.Image
	Width           Length
	Height          Length
	Left            Length
	Top             Length
	VerticalAlign   VerticalAlign
	HorizontalAlign TextAlign
}

ImageBoxElement is used to add an image box to a page

func (*ImageBoxElement) Build

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

Build adds the element to the content stream

type ImageElement

type ImageElement struct {
	Img    *pdf.Image
	Width  Length
	Height Length
	Left   Length
	Top    Length
}

ImageElement is used to add an image to a page

func (*ImageElement) Build

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

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
}

LineElement is used to add a line to a page

func (*LineElement) Build

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

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 RectElement

type RectElement struct {
	X1, Y1, Width, Height Length
	LineWidth             Length
	LineColor             Color
	FillColor             Color
}

RectElement is used to add a rectangle to a page

func (*RectElement) Build

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

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 TextAlign

type TextAlign int
const (
	TextAlignLeft   TextAlign = 0
	TextAlignCenter TextAlign = 1
	TextAlignRight  TextAlign = 2
)

type TextBoxElement

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

func (*TextBoxElement) Build

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

Build adds the element to the content stream

func (*TextBoxElement) TextHeight

func (q *TextBoxElement) TextHeight() Length

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

type TextElement

type TextElement struct {
	Text         string
	X, Y         Length
	Font         pdf.FontHandler
	FontSize     float64
	Color        Color
	RenderMode   types.RenderingMode
	OutlineColor Color
	OutlineWidth Length
	TextAlign    TextAlign
	LineHeight   float64
	Italic       bool
	Bold         bool
	Underline    bool
}

TextElement draws a text, may have line breaks

func (*TextElement) Build

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

Build adds the element to the content stream

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