PDF
golang
qiitap
gofpdf

この記事は Go2 Advent Calendar 2017 及び しむどん Advent Calendar 2017 の19日目の記事です。

gofpdf とは

https://github.com/jung-kurt/gofpdf/

gofpdfはPDFを生成するgoのライブラリです。テキスト、図面、イメージを実装しています。READMEに実装している機能が記載されています。

Features
- 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

(README.md抜粋)

  • 測定単位、ページフォーマット、マージンの選択
  • ページヘッダーとフッターの管理
  • 自動ページ区切り、改行、およびテキストの位置揃え
  • JPEG、PNG、GIF、TIFF、および基本的なパスのみのSVG画像を含める
  • 色、グラデーション、アルファチャンネルの透明度
  • ブックマークの概要
  • 内部および外部リンク
  • TrueType、Type1、およびエンコーディングのサポート
  • ページ圧縮
  • 線、ベジエ曲線、円弧、楕円
  • 回転、スケーリング、スキュー、変換、ミラーリング
  • クリッピング
  • 文書保護
  • レイヤー
  • テンプレート
  • バーコード

かなり高機能です。

簡単な使い方

まずはREADMEに記載されている例から試して見ます。"Hello, world" という文字だけが記述されたPDFを生成します。

hello.go
package main

import (
    "fmt"
    "github.com/jung-kurt/gofpdf"
)

func main() {
    pdf := gofpdf.New("P", "mm", "A4", "")
    pdf.AddPage()
    pdf.SetFont("Arial", "B", 16)
    pdf.Cell(40, 10, "Hello, world")
    err := pdf.OutputFileAndClose("hello.pdf")
    if err != nil {
        fmt.Printf("error\n")
    }
}

一行ずつ見ていきます。

    pdf := gofpdf.New("P", "mm", "A4", "")

Fpdfを生成してそのポインタを返します。第1引数はorientationStrです。これはデフォルトのページ方向を指定します。PはPortrait(縦)、LはLandscapeです(横)。空の文字列はPになります。第2引数はunitStrです。これは要素のサイズパラメータで使用される長さの単位を指定します。ここではミリメートルを指定しています。空の文字列はmmになります。他にpt, cm, in(インチ)が指定できます。第3引数はsizeStrです。"A3", "A4", "A5" などを指定します。第4引数はfontDirStrです。フォントが格納されているディレクトリのパスを指定します。空文字は"."になります。

    pdf.AddPage()

AddPage()はページを追加します。追加したページが編集対象のページになります。

あ、デバッグコードがコメントアウトされて残っているw
https://github.com/jung-kurt/gofpdf/blob/1bef4f81c40b64d68788e590003f4f8fbdc4d296/fpdf.go#L714

    pdf.SetFont("Arial", "B", 16)

SetFont()はフォントの設定です。第1引数はfamilyStr、フォントファミリーの指定です。第2引数はstyleStr、"B" (bold), "I" (italic), "U" (underscore)が指定できます。"BI"のように組み合わせて指定もできます。第3引数はsize、文字サイズを指定します。

    pdf.Cell(40, 10, "Hello, world")

Cell()でセルを追加します。セルは文字などの表示領域です。第1引数で幅、第2引数で高さを指定します。第3引数は挿入する文字列を指定します。

    err := pdf.OutputFileAndClose("hello.pdf")

OutputFileAndClose()はPDFをファイルに出力してファイルをクローズします。
第1引数に出力するファイルパスを指定します。

go run hello.go

これを実行するとhello.pdfが出力されます。

Fpdfの構造

// Fpdf is the principal structure for creating a single PDF document
type Fpdf struct {
    page             int                       // current page number
    n                int                       // current object number
    offsets          []int                     // array of object offsets
    templates        map[int64]Template        // templates used in this document
    templateObjects  map[int64]int             // template object IDs within this document
    buffer           fmtBuffer                 // buffer holding in-memory PDF
    pages            []*bytes.Buffer           // slice[page] of page content; 1-based
    state            int                       // current document state
    compress         bool                      // compression flag
    k                float64                   // scale factor (number of points in user unit)
    defOrientation   string                    // default orientation
    curOrientation   string                    // current orientation
    stdPageSizes     map[string]SizeType       // standard page sizes
    defPageSize      SizeType                  // default page size
    curPageSize      SizeType                  // current page size
    pageSizes        map[int]SizeType          // used for pages with non default sizes or orientations
    unitStr          string                    // unit of measure for all rendered objects except fonts
    wPt, hPt         float64                   // dimensions of current page in points
    w, h             float64                   // dimensions of current page in user unit
    lMargin          float64                   // left margin
    tMargin          float64                   // top margin
    rMargin          float64                   // right margin
    bMargin          float64                   // page break margin
    cMargin          float64                   // cell margin
    x, y             float64                   // current position in user unit
    lasth            float64                   // height of last printed cell
    lineWidth        float64                   // line width in user unit
    fontpath         string                    // path containing fonts
    fontLoader       FontLoader                // used to load font files from arbitrary locations
    coreFonts        map[string]bool           // array of core font names
    fonts            map[string]fontDefType    // array of used fonts
    fontFiles        map[string]fontFileType   // array of font files
    diffs            []string                  // array of encoding differences
    fontFamily       string                    // current font family
    fontStyle        string                    // current font style
    underline        bool                      // underlining flag
    currentFont      fontDefType               // current font info
    fontSizePt       float64                   // current font size in points
    fontSize         float64                   // current font size in user unit
    ws               float64                   // word spacing
    images           map[string]*ImageInfoType // array of used images
    pageLinks        [][]linkType              // pageLinks[page][link], both 1-based
    links            []intLinkType             // array of internal links
    outlines         []outlineType             // array of outlines
    outlineRoot      int                       // root of outlines
    autoPageBreak    bool                      // automatic page breaking
    acceptPageBreak  func() bool               // returns true to accept page break
    pageBreakTrigger float64                   // threshold used to trigger page breaks
    inHeader         bool                      // flag set when processing header
    headerFnc        func()                    // function provided by app and called to write header
    inFooter         bool                      // flag set when processing footer
    footerFnc        func()                    // function provided by app and called to write footer
    footerFncLpi     func(bool)                // function provided by app and called to write footer with last page flag
    zoomMode         string                    // zoom display mode
    layoutMode       string                    // layout display mode
    xmp              []byte                    // XMP metadata
    title            string                    // title
    subject          string                    // subject
    author           string                    // author
    keywords         string                    // keywords
    creator          string                    // creator
    creationDate     time.Time                 // override for dcoument CreationDate value
    aliasNbPagesStr  string                    // alias for total number of pages
    pdfVersion       string                    // PDF version number
    fontDirStr       string                    // location of font definition files
    capStyle         int                       // line cap style: butt 0, round 1, square 2
    joinStyle        int                       // line segment join style: miter 0, round 1, bevel 2
    dashArray        []float64                 // dash array
    dashPhase        float64                   // dash phase
    blendList        []blendModeType           // slice[idx] of alpha transparency modes, 1-based
    blendMap         map[string]int            // map into blendList
    blendMode        string                    // current blend mode
    alpha            float64                   // current transpacency
    gradientList     []gradientType            // slice[idx] of gradient records
    clipNest         int                       // Number of active clipping contexts
    transformNest    int                       // Number of active transformation contexts
    err              error                     // Set if error occurs during life cycle of instance
    protect          protectType               // document protection structure
    layer            layerRecType              // manages optional layers in document
    catalogSort      bool                      // sort resource catalogs in document
    nJs              int                       // JavaScript object number
    javascript       *string                   // JavaScript code to include in the PDF
    colorFlag        bool                      // indicates whether fill and text colors are different
    color            struct {
        // Composite values of colors
        draw, fill, text colorType
    }
    spotColorMap map[string]spotColorType // Map of named ink-based colors
}

これらを変更していくことでPDFを構成していきます。

Fpdf.SetHeaderFunc() - ヘッダーを設定する

pdf.SetHeaderFunc(func() {
    pdf.SetY(5)
    pdf.SetFont("Arial", "B", 15)
    pdf.Cell(60, 0, "")
    pdf.CellFormat(
        80, 10, titleStr, "1", 0, "C", false, 0,
        "https://qiita.com/advent-calendar/2017/go2")
    pdf.Ln(20)
})

ヘッダーの設定はヘッダーを生成する関数を登録することで実現します。

Fpdf.SetFooterFunc() - フッターを設定する

pdf.SetFooterFunc(func() {
    pdf.SetY(-15)
    pdf.SetFont("Arial", "I", 8)
    pdf.CellFormat(0, 10, fmt.Sprintf("Page %d/{nb}", pdf.PageNo()),
        "", 0, "C", false, 0, "")
})
pdf.AliasNbPages("")

フッターもヘッダー同様、フッターを生成する関数を登録することで実現します。

Fpdf.SetTitle() - タイトルを設定する

pdf.SetTitle(titleStr, false)

第1引数は文字列、第二引数はUTF8とかどうかをboolで指定します。

Fpdf.SetAuthor() - Authorを設定する

pdf.SetAuthor("TakesxiSximada", false)

第1引数は文字列、第二引数はUTF8とかどうかをboolで指定します。

Fpdf.SetFont() - フォントの設定

pdf.SetFont("Arial", "B", 16)

フォントファミリー、スタイル、サイズを指定します。

Fpdf.AddPage() - ページを追加する

pdf.AddPage()

Fpdf.Image() - 画像を追加する

pdf.Image("./sximada.jpg", 160, 28, 30, 0, false, "", 0,
    "https://twitter.com/TakesxiSximada")

最後に渡しているURLはリンクのジャンプ先になります。

Fpdf.CellFormat() - Cellの情報を詳細に設定する

pdf.CellFormat(width, 10, text, "", 0, "C", false, 0, "")

Fpdf.Cell()でセルを追加しましたが、それ以外の属性を指定したい場合はCellFormat()を使います。Fpdf.Cell()はCellFormat()を内部で読んでいます。

Fpdf.Ln() - 改行

pdf.Ln(10)

Fpdf.SetProtection() - 制約を付与する

pdf.SetProtection(gofpdf.CnProtectAnnotForms, "foo", "bar")

第一引数はフラグで次の値を指定できます。

意味
CnProtectPrint 印刷可能
CnProtectModify 編集可能
CnProtectCopy コピー可能
CnProtectAnnotForms アノテーションやフォームをPDFエディタで追加
// Advisory bitflag constants that control document activities
const (
    CnProtectPrint      = 4
    CnProtectModify     = 8
    CnProtectCopy       = 16
    CnProtectAnnotForms = 32
)

第2引数はユーザーパスワードです。この値を設定するとファイルを開く場合にパスワードを求めます。第3引数はオーナーパスワードです。ユーザーパスワードとの違いは、このパスワードで開いた場合はこのPDFに対する全ての操作権限が与えられます。

Fpdf.SetMargins() - マージンを設定する

pdf.SetMargins(100, 100, 100)

Fpdf.Rect() - 四角を描画する

pdf.Rect(3, 3, 3, 3, "F")

X、Y、幅、高さ、スタイルを指定します。例の場合では小さく黒い四角が左上に出力されます。