diff options
Diffstat (limited to 'vendor/github.com/jung-kurt/gofpdf/fpdf_test.go')
| -rw-r--r-- | vendor/github.com/jung-kurt/gofpdf/fpdf_test.go | 1859 |
1 files changed, 1859 insertions, 0 deletions
diff --git a/vendor/github.com/jung-kurt/gofpdf/fpdf_test.go b/vendor/github.com/jung-kurt/gofpdf/fpdf_test.go new file mode 100644 index 0000000..456295c --- /dev/null +++ b/vendor/github.com/jung-kurt/gofpdf/fpdf_test.go @@ -0,0 +1,1859 @@ +/* + * Copyright (c) 2013-2015 Kurt Jung (Gmail: kurt.w.jung) + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package gofpdf_test + +import ( + "bufio" + "bytes" + "fmt" + "io" + "io/ioutil" + "math" + "net/http" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/jung-kurt/gofpdf" + "github.com/jung-kurt/gofpdf/internal/example" + "github.com/jung-kurt/gofpdf/internal/files" +) + +func init() { + cleanup() +} + +func cleanup() { + filepath.Walk(example.PdfDir(), + func(path string, info os.FileInfo, err error) (reterr error) { + if info.Mode().IsRegular() { + dir, _ := filepath.Split(path) + if "reference" != filepath.Base(dir) { + if len(path) > 3 { + if path[len(path)-4:] == ".pdf" { + os.Remove(path) + } + } + } + } + return + }) +} + +type fontResourceType struct { +} + +func (f fontResourceType) Open(name string) (rdr io.Reader, err error) { + var buf []byte + buf, err = ioutil.ReadFile(example.FontFile(name)) + if err == nil { + rdr = bytes.NewReader(buf) + fmt.Printf("Generalized font loader reading %s\n", name) + } + return +} + +// Convert 'ABCDEFG' to, for example, 'A,BCD,EFG' +func strDelimit(str string, sepstr string, sepcount int) string { + pos := len(str) - sepcount + for pos > 0 { + str = str[:pos] + sepstr + str[pos:] + pos = pos - sepcount + } + return str +} + +func lorem() string { + return "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod " + + "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis " + + "nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis " + + "aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat " + + "nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui " + + "officia deserunt mollit anim id est laborum." +} + +// This example demonstrates the generation of a simple PDF document. Note that +// since only core fonts are used (in this case Arial, a synonym for +// Helvetica), an empty string can be specified for the font directory in the +// call to New(). Note also that the example.Filename() and example.Summary() +// functions belong to a separate, internal package and are not part of the +// gofpdf library. If an error occurs at some point during the construction of +// the document, subsequent method calls exit immediately and the error is +// finally retrieved with the output call where it can be handled by the +// application. +func Example() { + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + pdf.SetFont("Arial", "B", 16) + pdf.Cell(40, 10, "Hello World!") + fileStr := example.Filename("basic") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/basic.pdf +} + +// This example demonsrates the generation of headers, footers and page breaks. +func ExampleFpdf_AddPage() { + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.SetHeaderFunc(func() { + pdf.Image(example.ImageFile("logo.png"), 10, 6, 30, 0, false, "", 0, "") + pdf.SetY(5) + pdf.SetFont("Arial", "B", 15) + pdf.Cell(80, 0, "") + pdf.CellFormat(30, 10, "Title", "1", 0, "C", false, 0, "") + pdf.Ln(20) + }) + 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("") + pdf.AddPage() + pdf.SetFont("Times", "", 12) + for j := 1; j <= 40; j++ { + pdf.CellFormat(0, 10, fmt.Sprintf("Printing line number %d", j), + "", 1, "", false, 0, "") + } + fileStr := example.Filename("Fpdf_AddPage") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_AddPage.pdf +} + +// This example demonstrates word-wrapping, line justification and +// page-breaking. +func ExampleFpdf_MultiCell() { + pdf := gofpdf.New("P", "mm", "A4", "") + titleStr := "20000 Leagues Under the Seas" + pdf.SetTitle(titleStr, false) + pdf.SetAuthor("Jules Verne", false) + pdf.SetHeaderFunc(func() { + // Arial bold 15 + pdf.SetFont("Arial", "B", 15) + // Calculate width of title and position + wd := pdf.GetStringWidth(titleStr) + 6 + pdf.SetX((210 - wd) / 2) + // Colors of frame, background and text + pdf.SetDrawColor(0, 80, 180) + pdf.SetFillColor(230, 230, 0) + pdf.SetTextColor(220, 50, 50) + // Thickness of frame (1 mm) + pdf.SetLineWidth(1) + // Title + pdf.CellFormat(wd, 9, titleStr, "1", 1, "C", true, 0, "") + // Line break + pdf.Ln(10) + }) + pdf.SetFooterFunc(func() { + // Position at 1.5 cm from bottom + pdf.SetY(-15) + // Arial italic 8 + pdf.SetFont("Arial", "I", 8) + // Text color in gray + pdf.SetTextColor(128, 128, 128) + // Page number + pdf.CellFormat(0, 10, fmt.Sprintf("Page %d", pdf.PageNo()), + "", 0, "C", false, 0, "") + }) + chapterTitle := func(chapNum int, titleStr string) { + // // Arial 12 + pdf.SetFont("Arial", "", 12) + // Background color + pdf.SetFillColor(200, 220, 255) + // Title + pdf.CellFormat(0, 6, fmt.Sprintf("Chapter %d : %s", chapNum, titleStr), + "", 1, "L", true, 0, "") + // Line break + pdf.Ln(4) + } + chapterBody := func(fileStr string) { + // Read text file + txtStr, err := ioutil.ReadFile(fileStr) + if err != nil { + pdf.SetError(err) + } + // Times 12 + pdf.SetFont("Times", "", 12) + // Output justified text + pdf.MultiCell(0, 5, string(txtStr), "", "", false) + // Line break + pdf.Ln(-1) + // Mention in italics + pdf.SetFont("", "I", 0) + pdf.Cell(0, 5, "(end of excerpt)") + } + printChapter := func(chapNum int, titleStr, fileStr string) { + pdf.AddPage() + chapterTitle(chapNum, titleStr) + chapterBody(fileStr) + } + printChapter(1, "A RUNAWAY REEF", example.TextFile("20k_c1.txt")) + printChapter(2, "THE PROS AND CONS", example.TextFile("20k_c2.txt")) + fileStr := example.Filename("Fpdf_MultiCell") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_MultiCell.pdf +} + +// This example demonstrates the generation of a PDF document that has multiple +// columns. This is accomplished with the SetLeftMargin() and Cell() methods. +func ExampleFpdf_SetLeftMargin() { + var y0 float64 + var crrntCol int + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.SetDisplayMode("fullpage", "TwoColumnLeft") + titleStr := "20000 Leagues Under the Seas" + pdf.SetTitle(titleStr, false) + pdf.SetAuthor("Jules Verne", false) + setCol := func(col int) { + // Set position at a given column + crrntCol = col + x := 10.0 + float64(col)*65.0 + pdf.SetLeftMargin(x) + pdf.SetX(x) + } + chapterTitle := func(chapNum int, titleStr string) { + // Arial 12 + pdf.SetFont("Arial", "", 12) + // Background color + pdf.SetFillColor(200, 220, 255) + // Title + pdf.CellFormat(0, 6, fmt.Sprintf("Chapter %d : %s", chapNum, titleStr), + "", 1, "L", true, 0, "") + // Line break + pdf.Ln(4) + y0 = pdf.GetY() + } + chapterBody := func(fileStr string) { + // Read text file + txtStr, err := ioutil.ReadFile(fileStr) + if err != nil { + pdf.SetError(err) + } + // Font + pdf.SetFont("Times", "", 12) + // Output text in a 6 cm width column + pdf.MultiCell(60, 5, string(txtStr), "", "", false) + pdf.Ln(-1) + // Mention + pdf.SetFont("", "I", 0) + pdf.Cell(0, 5, "(end of excerpt)") + // Go back to first column + setCol(0) + } + printChapter := func(num int, titleStr, fileStr string) { + // Add chapter + pdf.AddPage() + chapterTitle(num, titleStr) + chapterBody(fileStr) + } + pdf.SetAcceptPageBreakFunc(func() bool { + // Method accepting or not automatic page break + if crrntCol < 2 { + // Go to next column + setCol(crrntCol + 1) + // Set ordinate to top + pdf.SetY(y0) + // Keep on page + return false + } + // Go back to first column + setCol(0) + // Page break + return true + }) + pdf.SetHeaderFunc(func() { + // Arial bold 15 + pdf.SetFont("Arial", "B", 15) + // Calculate width of title and position + wd := pdf.GetStringWidth(titleStr) + 6 + pdf.SetX((210 - wd) / 2) + // Colors of frame, background and text + pdf.SetDrawColor(0, 80, 180) + pdf.SetFillColor(230, 230, 0) + pdf.SetTextColor(220, 50, 50) + // Thickness of frame (1 mm) + pdf.SetLineWidth(1) + // Title + pdf.CellFormat(wd, 9, titleStr, "1", 1, "C", true, 0, "") + // Line break + pdf.Ln(10) + // Save ordinate + y0 = pdf.GetY() + }) + pdf.SetFooterFunc(func() { + // Position at 1.5 cm from bottom + pdf.SetY(-15) + // Arial italic 8 + pdf.SetFont("Arial", "I", 8) + // Text color in gray + pdf.SetTextColor(128, 128, 128) + // Page number + pdf.CellFormat(0, 10, fmt.Sprintf("Page %d", pdf.PageNo()), + "", 0, "C", false, 0, "") + }) + printChapter(1, "A RUNAWAY REEF", example.TextFile("20k_c1.txt")) + printChapter(2, "THE PROS AND CONS", example.TextFile("20k_c2.txt")) + fileStr := example.Filename("Fpdf_SetLeftMargin_multicolumn") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_SetLeftMargin_multicolumn.pdf +} + +// This example demonstrates various table styles. +func ExampleFpdf_CellFormat_tables() { + pdf := gofpdf.New("P", "mm", "A4", "") + type countryType struct { + nameStr, capitalStr, areaStr, popStr string + } + countryList := make([]countryType, 0, 8) + header := []string{"Country", "Capital", "Area (sq km)", "Pop. (thousands)"} + loadData := func(fileStr string) { + fl, err := os.Open(fileStr) + if err == nil { + scanner := bufio.NewScanner(fl) + var c countryType + for scanner.Scan() { + // Austria;Vienna;83859;8075 + lineStr := scanner.Text() + list := strings.Split(lineStr, ";") + if len(list) == 4 { + c.nameStr = list[0] + c.capitalStr = list[1] + c.areaStr = list[2] + c.popStr = list[3] + countryList = append(countryList, c) + } else { + err = fmt.Errorf("error tokenizing %s", lineStr) + } + } + fl.Close() + if len(countryList) == 0 { + err = fmt.Errorf("error loading data from %s", fileStr) + } + } + if err != nil { + pdf.SetError(err) + } + } + // Simple table + basicTable := func() { + for _, str := range header { + pdf.CellFormat(40, 7, str, "1", 0, "", false, 0, "") + } + pdf.Ln(-1) + for _, c := range countryList { + pdf.CellFormat(40, 6, c.nameStr, "1", 0, "", false, 0, "") + pdf.CellFormat(40, 6, c.capitalStr, "1", 0, "", false, 0, "") + pdf.CellFormat(40, 6, c.areaStr, "1", 0, "", false, 0, "") + pdf.CellFormat(40, 6, c.popStr, "1", 0, "", false, 0, "") + pdf.Ln(-1) + } + } + // Better table + improvedTable := func() { + // Column widths + w := []float64{40.0, 35.0, 40.0, 45.0} + wSum := 0.0 + for _, v := range w { + wSum += v + } + // Header + for j, str := range header { + pdf.CellFormat(w[j], 7, str, "1", 0, "C", false, 0, "") + } + pdf.Ln(-1) + // Data + for _, c := range countryList { + pdf.CellFormat(w[0], 6, c.nameStr, "LR", 0, "", false, 0, "") + pdf.CellFormat(w[1], 6, c.capitalStr, "LR", 0, "", false, 0, "") + pdf.CellFormat(w[2], 6, strDelimit(c.areaStr, ",", 3), + "LR", 0, "R", false, 0, "") + pdf.CellFormat(w[3], 6, strDelimit(c.popStr, ",", 3), + "LR", 0, "R", false, 0, "") + pdf.Ln(-1) + } + pdf.CellFormat(wSum, 0, "", "T", 0, "", false, 0, "") + } + // Colored table + fancyTable := func() { + // Colors, line width and bold font + pdf.SetFillColor(255, 0, 0) + pdf.SetTextColor(255, 255, 255) + pdf.SetDrawColor(128, 0, 0) + pdf.SetLineWidth(.3) + pdf.SetFont("", "B", 0) + // Header + w := []float64{40, 35, 40, 45} + wSum := 0.0 + for _, v := range w { + wSum += v + } + for j, str := range header { + pdf.CellFormat(w[j], 7, str, "1", 0, "C", true, 0, "") + } + pdf.Ln(-1) + // Color and font restoration + pdf.SetFillColor(224, 235, 255) + pdf.SetTextColor(0, 0, 0) + pdf.SetFont("", "", 0) + // Data + fill := false + for _, c := range countryList { + pdf.CellFormat(w[0], 6, c.nameStr, "LR", 0, "", fill, 0, "") + pdf.CellFormat(w[1], 6, c.capitalStr, "LR", 0, "", fill, 0, "") + pdf.CellFormat(w[2], 6, strDelimit(c.areaStr, ",", 3), + "LR", 0, "R", fill, 0, "") + pdf.CellFormat(w[3], 6, strDelimit(c.popStr, ",", 3), + "LR", 0, "R", fill, 0, "") + pdf.Ln(-1) + fill = !fill + } + pdf.CellFormat(wSum, 0, "", "T", 0, "", false, 0, "") + } + loadData(example.TextFile("countries.txt")) + pdf.SetFont("Arial", "", 14) + pdf.AddPage() + basicTable() + pdf.AddPage() + improvedTable() + pdf.AddPage() + fancyTable() + fileStr := example.Filename("Fpdf_CellFormat_tables") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_CellFormat_tables.pdf +} + +// This example demonstrates internal and external links with and without basic +// HTML. +func ExampleFpdf_HTMLBasicNew() { + pdf := gofpdf.New("P", "mm", "A4", "") + // First page: manual local link + pdf.AddPage() + pdf.SetFont("Helvetica", "", 20) + _, lineHt := pdf.GetFontSize() + pdf.Write(lineHt, "To find out what's new in this tutorial, click ") + pdf.SetFont("", "U", 0) + link := pdf.AddLink() + pdf.WriteLinkID(lineHt, "here", link) + pdf.SetFont("", "", 0) + // Second page: image link and basic HTML with link + pdf.AddPage() + pdf.SetLink(link, 0, -1) + pdf.Image(example.ImageFile("logo.png"), 10, 12, 30, 0, false, "", 0, "http://www.fpdf.org") + pdf.SetLeftMargin(45) + pdf.SetFontSize(14) + _, lineHt = pdf.GetFontSize() + htmlStr := `You can now easily print text mixing different styles: <b>bold</b>, ` + + `<i>italic</i>, <u>underlined</u>, or <b><i><u>all at once</u></i></b>!<br><br>` + + `<center>You can also center text.</center>` + + `<right>Or align it to the right.</right>` + + `You can also insert links on text, such as ` + + `<a href="http://www.fpdf.org">www.fpdf.org</a>, or on an image: click on the logo.` + html := pdf.HTMLBasicNew() + html.Write(lineHt, htmlStr) + fileStr := example.Filename("Fpdf_HTMLBasicNew") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_HTMLBasicNew.pdf +} + +// This example demonstrates the use of a non-standard font. +func ExampleFpdf_AddFont() { + pdf := gofpdf.New("P", "mm", "A4", example.FontDir()) + pdf.AddFont("Calligrapher", "", "calligra.json") + pdf.AddPage() + pdf.SetFont("Calligrapher", "", 35) + pdf.Cell(0, 10, "Enjoy new fonts with FPDF!") + fileStr := example.Filename("Fpdf_AddFont") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_AddFont.pdf +} + +// This example demonstrates how to align text with the Write function. +func ExampleFpdf_WriteAligned() { + pdf := gofpdf.New("P", "mm", "A4", example.FontDir()) + pdf.AddPage() + pdf.SetFont("Helvetica", "", 12) + pdf.WriteAligned(0, 35, "This text is the default alignment, Left", "") + pdf.Ln(35) + pdf.WriteAligned(0, 35, "This text is aligned Left", "L") + pdf.Ln(35) + pdf.WriteAligned(0, 35, "This text is aligned Center", "C") + pdf.Ln(35) + pdf.WriteAligned(0, 35, "This text is aligned Right", "R") + fileStr := example.Filename("Fpdf_WriteAligned") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_WriteAligned.pdf +} + +// This example demonstrates how images are included in documents. +func ExampleFpdf_Image() { + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + pdf.SetFont("Arial", "", 11) + pdf.Image(example.ImageFile("logo.png"), 10, 10, 30, 0, false, "", 0, "") + pdf.Text(50, 20, "logo.png") + pdf.Image(example.ImageFile("logo.gif"), 10, 40, 30, 0, false, "", 0, "") + pdf.Text(50, 50, "logo.gif") + pdf.Image(example.ImageFile("logo-gray.png"), 10, 70, 30, 0, false, "", 0, "") + pdf.Text(50, 80, "logo-gray.png") + pdf.Image(example.ImageFile("logo-rgb.png"), 10, 100, 30, 0, false, "", 0, "") + pdf.Text(50, 110, "logo-rgb.png") + pdf.Image(example.ImageFile("logo.jpg"), 10, 130, 30, 0, false, "", 0, "") + pdf.Text(50, 140, "logo.jpg") + fileStr := example.Filename("Fpdf_Image") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_Image.pdf +} + +// This examples demonstrates Landscape mode with images. +func ExampleFpdf_SetAcceptPageBreakFunc() { + var y0 float64 + var crrntCol int + loremStr := lorem() + pdf := gofpdf.New("L", "mm", "A4", "") + const ( + pageWd = 297.0 // A4 210.0 x 297.0 + margin = 10.0 + gutter = 4 + colNum = 3 + colWd = (pageWd - 2*margin - (colNum-1)*gutter) / colNum + ) + setCol := func(col int) { + crrntCol = col + x := margin + float64(col)*(colWd+gutter) + pdf.SetLeftMargin(x) + pdf.SetX(x) + } + pdf.SetHeaderFunc(func() { + titleStr := "gofpdf" + pdf.SetFont("Helvetica", "B", 48) + wd := pdf.GetStringWidth(titleStr) + 6 + pdf.SetX((pageWd - wd) / 2) + pdf.SetTextColor(128, 128, 160) + pdf.Write(12, titleStr[:2]) + pdf.SetTextColor(128, 128, 128) + pdf.Write(12, titleStr[2:]) + pdf.Ln(20) + y0 = pdf.GetY() + }) + pdf.SetAcceptPageBreakFunc(func() bool { + if crrntCol < colNum-1 { + setCol(crrntCol + 1) + pdf.SetY(y0) + // Start new column, not new page + return false + } + setCol(0) + return true + }) + pdf.AddPage() + pdf.SetFont("Times", "", 12) + for j := 0; j < 20; j++ { + if j == 1 { + pdf.Image(example.ImageFile("fpdf.png"), -1, 0, colWd, 0, true, "", 0, "") + } else if j == 5 { + pdf.Image(example.ImageFile("golang-gopher.png"), + -1, 0, colWd, 0, true, "", 0, "") + } + pdf.MultiCell(colWd, 5, loremStr, "", "", false) + pdf.Ln(-1) + } + fileStr := example.Filename("Fpdf_SetAcceptPageBreakFunc_landscape") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_SetAcceptPageBreakFunc_landscape.pdf +} + +// This examples tests corner cases as reported by the gocov tool. +func ExampleFpdf_SetKeywords() { + var err error + fileStr := example.Filename("Fpdf_SetKeywords") + err = gofpdf.MakeFont(example.FontFile("CalligrapherRegular.pfb"), + example.FontFile("cp1252.map"), example.FontDir(), nil, true) + if err == nil { + pdf := gofpdf.New("", "", "", "") + pdf.SetFontLocation(example.FontDir()) + pdf.SetTitle("世界", true) + pdf.SetAuthor("世界", true) + pdf.SetSubject("世界", true) + pdf.SetCreator("世界", true) + pdf.SetKeywords("世界", true) + pdf.AddFont("Calligrapher", "", "CalligrapherRegular.json") + pdf.AddPage() + pdf.SetFont("Calligrapher", "", 16) + pdf.Writef(5, "\x95 %s \x95", pdf) + err = pdf.OutputFileAndClose(fileStr) + } + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_SetKeywords.pdf +} + +// This example demonstrates the construction of various geometric figures, +func ExampleFpdf_Circle() { + const ( + thin = 0.2 + thick = 3.0 + ) + pdf := gofpdf.New("", "", "", "") + pdf.SetFont("Helvetica", "", 12) + pdf.SetFillColor(200, 200, 220) + pdf.AddPage() + + y := 15.0 + pdf.Text(10, y, "Circles") + pdf.SetFillColor(200, 200, 220) + pdf.SetLineWidth(thin) + pdf.Circle(20, y+15, 10, "D") + pdf.Circle(45, y+15, 10, "F") + pdf.Circle(70, y+15, 10, "FD") + pdf.SetLineWidth(thick) + pdf.Circle(95, y+15, 10, "FD") + pdf.SetLineWidth(thin) + + y += 40.0 + pdf.Text(10, y, "Ellipses") + pdf.SetFillColor(220, 200, 200) + pdf.Ellipse(30, y+15, 20, 10, 0, "D") + pdf.Ellipse(75, y+15, 20, 10, 0, "F") + pdf.Ellipse(120, y+15, 20, 10, 0, "FD") + pdf.SetLineWidth(thick) + pdf.Ellipse(165, y+15, 20, 10, 0, "FD") + pdf.SetLineWidth(thin) + + y += 40.0 + pdf.Text(10, y, "Curves (quadratic)") + pdf.SetFillColor(220, 220, 200) + pdf.Curve(10, y+30, 15, y-20, 40, y+30, "D") + pdf.Curve(45, y+30, 50, y-20, 75, y+30, "F") + pdf.Curve(80, y+30, 85, y-20, 110, y+30, "FD") + pdf.SetLineWidth(thick) + pdf.Curve(115, y+30, 120, y-20, 145, y+30, "FD") + pdf.SetLineCapStyle("round") + pdf.Curve(150, y+30, 155, y-20, 180, y+30, "FD") + pdf.SetLineWidth(thin) + pdf.SetLineCapStyle("butt") + + y += 40.0 + pdf.Text(10, y, "Curves (cubic)") + pdf.SetFillColor(220, 200, 220) + pdf.CurveBezierCubic(10, y+30, 15, y-20, 10, y+30, 40, y+30, "D") + pdf.CurveBezierCubic(45, y+30, 50, y-20, 45, y+30, 75, y+30, "F") + pdf.CurveBezierCubic(80, y+30, 85, y-20, 80, y+30, 110, y+30, "FD") + pdf.SetLineWidth(thick) + pdf.CurveBezierCubic(115, y+30, 120, y-20, 115, y+30, 145, y+30, "FD") + pdf.SetLineCapStyle("round") + pdf.CurveBezierCubic(150, y+30, 155, y-20, 150, y+30, 180, y+30, "FD") + pdf.SetLineWidth(thin) + pdf.SetLineCapStyle("butt") + + y += 40.0 + pdf.Text(10, y, "Arcs") + pdf.SetFillColor(200, 220, 220) + pdf.SetLineWidth(thick) + pdf.Arc(45, y+35, 20, 10, 0, 0, 180, "FD") + pdf.SetLineWidth(thin) + pdf.Arc(45, y+35, 25, 15, 0, 90, 270, "D") + pdf.SetLineWidth(thick) + pdf.Arc(45, y+35, 30, 20, 0, 0, 360, "D") + pdf.SetLineCapStyle("round") + pdf.Arc(135, y+35, 20, 10, 135, 0, 180, "FD") + pdf.SetLineWidth(thin) + pdf.Arc(135, y+35, 25, 15, 135, 90, 270, "D") + pdf.SetLineWidth(thick) + pdf.Arc(135, y+35, 30, 20, 135, 0, 360, "D") + pdf.SetLineWidth(thin) + pdf.SetLineCapStyle("butt") + + fileStr := example.Filename("Fpdf_Circle_figures") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_Circle_figures.pdf +} + +// This example demonstrates alpha transparency. +func ExampleFpdf_SetAlpha() { + const ( + gapX = 10.0 + gapY = 9.0 + rectW = 40.0 + rectH = 58.0 + pageW = 210 + pageH = 297 + ) + modeList := []string{"Normal", "Multiply", "Screen", "Overlay", + "Darken", "Lighten", "ColorDodge", "ColorBurn", "HardLight", "SoftLight", + "Difference", "Exclusion", "Hue", "Saturation", "Color", "Luminosity"} + pdf := gofpdf.New("", "", "", "") + pdf.SetLineWidth(2) + pdf.SetAutoPageBreak(false, 0) + pdf.AddPage() + pdf.SetFont("Helvetica", "", 18) + pdf.SetXY(0, gapY) + pdf.SetTextColor(0, 0, 0) + pdf.CellFormat(pageW, gapY, "Alpha Blending Modes", "", 0, "C", false, 0, "") + j := 0 + y := 3 * gapY + for col := 0; col < 4; col++ { + x := gapX + for row := 0; row < 4; row++ { + pdf.Rect(x, y, rectW, rectH, "D") + pdf.SetFont("Helvetica", "B", 12) + pdf.SetFillColor(0, 0, 0) + pdf.SetTextColor(250, 250, 230) + pdf.SetXY(x, y+rectH-4) + pdf.CellFormat(rectW, 5, modeList[j], "", 0, "C", true, 0, "") + pdf.SetFont("Helvetica", "I", 150) + pdf.SetTextColor(80, 80, 120) + pdf.SetXY(x, y+2) + pdf.CellFormat(rectW, rectH, "A", "", 0, "C", false, 0, "") + pdf.SetAlpha(0.5, modeList[j]) + pdf.Image(example.ImageFile("golang-gopher.png"), + x-gapX, y, rectW+2*gapX, 0, false, "", 0, "") + pdf.SetAlpha(1.0, "Normal") + x += rectW + gapX + j++ + } + y += rectH + gapY + } + fileStr := example.Filename("Fpdf_SetAlpha_transparency") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_SetAlpha_transparency.pdf +} + +// This example deomstrates various gradients. +func ExampleFpdf_LinearGradient() { + pdf := gofpdf.New("", "", "", "") + pdf.SetFont("Helvetica", "", 12) + pdf.AddPage() + pdf.LinearGradient(0, 0, 210, 100, 250, 250, 255, 220, 220, 225, 0, 0, 0, .5) + pdf.LinearGradient(20, 25, 75, 75, 220, 220, 250, 80, 80, 220, 0, .2, 0, .8) + pdf.Rect(20, 25, 75, 75, "D") + pdf.LinearGradient(115, 25, 75, 75, 220, 220, 250, 80, 80, 220, 0, 0, 1, 1) + pdf.Rect(115, 25, 75, 75, "D") + pdf.RadialGradient(20, 120, 75, 75, 220, 220, 250, 80, 80, 220, + 0.25, 0.75, 0.25, 0.75, 1) + pdf.Rect(20, 120, 75, 75, "D") + pdf.RadialGradient(115, 120, 75, 75, 220, 220, 250, 80, 80, 220, + 0.25, 0.75, 0.75, 0.75, 0.75) + pdf.Rect(115, 120, 75, 75, "D") + fileStr := example.Filename("Fpdf_LinearGradient_gradient") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_LinearGradient_gradient.pdf +} + +// This example demonstrates clipping. +func ExampleFpdf_ClipText() { + pdf := gofpdf.New("", "", "", "") + y := 10.0 + pdf.AddPage() + + pdf.SetFont("Helvetica", "", 24) + pdf.SetXY(0, y) + pdf.ClipText(10, y+12, "Clipping examples", false) + pdf.RadialGradient(10, y, 100, 20, 128, 128, 160, 32, 32, 48, + 0.25, 0.5, 0.25, 0.5, 0.2) + pdf.ClipEnd() + + y += 12 + pdf.SetFont("Helvetica", "B", 120) + pdf.SetDrawColor(64, 80, 80) + pdf.SetLineWidth(.5) + pdf.ClipText(10, y+40, pdf.String(), true) + pdf.RadialGradient(10, y, 200, 50, 220, 220, 250, 80, 80, 220, + 0.25, 0.5, 0.25, 0.5, 1) + pdf.ClipEnd() + + y += 55 + pdf.ClipRect(10, y, 105, 20, true) + pdf.SetFillColor(255, 255, 255) + pdf.Rect(10, y, 105, 20, "F") + pdf.ClipCircle(40, y+10, 15, false) + pdf.RadialGradient(25, y, 30, 30, 220, 250, 220, 40, 60, 40, 0.3, + 0.85, 0.3, 0.85, 0.5) + pdf.ClipEnd() + pdf.ClipEllipse(80, y+10, 20, 15, false) + pdf.RadialGradient(60, y, 40, 30, 250, 220, 220, 60, 40, 40, 0.3, + 0.85, 0.3, 0.85, 0.5) + pdf.ClipEnd() + pdf.ClipEnd() + + y += 28 + pdf.ClipEllipse(26, y+10, 16, 10, true) + pdf.Image(example.ImageFile("logo.jpg"), 10, y, 32, 0, false, "JPG", 0, "") + pdf.ClipEnd() + + pdf.ClipCircle(60, y+10, 10, true) + pdf.RadialGradient(50, y, 20, 20, 220, 220, 250, 40, 40, 60, 0.3, + 0.7, 0.3, 0.7, 0.5) + pdf.ClipEnd() + + pdf.ClipPolygon([]gofpdf.PointType{{X: 80, Y: y + 20}, {X: 90, Y: y}, + {X: 100, Y: y + 20}}, true) + pdf.LinearGradient(80, y, 20, 20, 250, 220, 250, 60, 40, 60, 0.5, + 1, 0.5, 0.5) + pdf.ClipEnd() + + y += 30 + pdf.SetLineWidth(.1) + pdf.SetDrawColor(180, 180, 180) + pdf.ClipRoundedRect(10, y, 120, 20, 5, true) + pdf.RadialGradient(10, y, 120, 20, 255, 255, 255, 240, 240, 220, + 0.25, 0.75, 0.25, 0.75, 0.5) + pdf.SetXY(5, y-5) + pdf.SetFont("Times", "", 12) + pdf.MultiCell(130, 5, lorem(), "", "", false) + pdf.ClipEnd() + + fileStr := example.Filename("Fpdf_ClipText") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_ClipText.pdf +} + +// This example generates a PDF document with various page sizes. +func ExampleFpdf_PageSize() { + pdf := gofpdf.NewCustom(&gofpdf.InitType{ + UnitStr: "in", + Size: gofpdf.SizeType{Wd: 6, Ht: 6}, + FontDirStr: example.FontDir(), + }) + pdf.SetMargins(0.5, 1, 0.5) + pdf.SetFont("Times", "", 14) + pdf.AddPageFormat("L", gofpdf.SizeType{Wd: 3, Ht: 12}) + pdf.SetXY(0.5, 1.5) + pdf.CellFormat(11, 0.2, "12 in x 3 in", "", 0, "C", false, 0, "") + pdf.AddPage() // Default size established in NewCustom() + pdf.SetXY(0.5, 3) + pdf.CellFormat(5, 0.2, "6 in x 6 in", "", 0, "C", false, 0, "") + pdf.AddPageFormat("P", gofpdf.SizeType{Wd: 3, Ht: 12}) + pdf.SetXY(0.5, 6) + pdf.CellFormat(2, 0.2, "3 in x 12 in", "", 0, "C", false, 0, "") + for j := 0; j <= 3; j++ { + wd, ht, u := pdf.PageSize(j) + fmt.Printf("%d: %6.2f %s, %6.2f %s\n", j, wd, u, ht, u) + } + fileStr := example.Filename("Fpdf_PageSize") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // 0: 6.00 in, 6.00 in + // 1: 12.00 in, 3.00 in + // 2: 6.00 in, 6.00 in + // 3: 3.00 in, 12.00 in + // Successfully generated pdf/Fpdf_PageSize.pdf +} + +// This example demonstrates the Bookmark method. +func ExampleFpdf_Bookmark() { + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + pdf.SetFont("Arial", "", 15) + pdf.Bookmark("Page 1", 0, 0) + pdf.Bookmark("Paragraph 1", 1, -1) + pdf.Cell(0, 6, "Paragraph 1") + pdf.Ln(50) + pdf.Bookmark("Paragraph 2", 1, -1) + pdf.Cell(0, 6, "Paragraph 2") + pdf.AddPage() + pdf.Bookmark("Page 2", 0, 0) + pdf.Bookmark("Paragraph 3", 1, -1) + pdf.Cell(0, 6, "Paragraph 3") + fileStr := example.Filename("Fpdf_Bookmark") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_Bookmark.pdf +} + +// This example demonstrates various transformations. It is adapted from an +// example script by Moritz Wagner and Andreas Würmser. +func ExampleFpdf_TransformBegin() { + const ( + light = 200 + dark = 0 + ) + var refX, refY float64 + var refStr string + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + color := func(val int) { + pdf.SetDrawColor(val, val, val) + pdf.SetTextColor(val, val, val) + } + reference := func(str string, x, y float64, val int) { + color(val) + pdf.Rect(x, y, 40, 10, "D") + pdf.Text(x, y-1, str) + } + refDraw := func(str string, x, y float64) { + refStr = str + refX = x + refY = y + reference(str, x, y, light) + } + refDupe := func() { + reference(refStr, refX, refY, dark) + } + + titleStr := "Transformations" + titlePt := 36.0 + titleHt := pdf.PointConvert(titlePt) + pdf.SetFont("Helvetica", "", titlePt) + titleWd := pdf.GetStringWidth(titleStr) + titleX := (210 - titleWd) / 2 + pdf.Text(titleX, 10+titleHt, titleStr) + pdf.TransformBegin() + pdf.TransformMirrorVertical(10 + titleHt + 0.5) + pdf.ClipText(titleX, 10+titleHt, titleStr, false) + // Remember that the transform will mirror the gradient box too + pdf.LinearGradient(titleX, 10, titleWd, titleHt+4, 120, 120, 120, + 255, 255, 255, 0, 0, 0, 0.6) + pdf.ClipEnd() + pdf.TransformEnd() + + pdf.SetFont("Helvetica", "", 12) + + // Scale by 150% centered by lower left corner of the rectangle + refDraw("Scale", 50, 60) + pdf.TransformBegin() + pdf.TransformScaleXY(150, 50, 70) + refDupe() + pdf.TransformEnd() + + // Translate 7 to the right, 5 to the bottom + refDraw("Translate", 125, 60) + pdf.TransformBegin() + pdf.TransformTranslate(7, 5) + refDupe() + pdf.TransformEnd() + + // Rotate 20 degrees counter-clockwise centered by the lower left corner of + // the rectangle + refDraw("Rotate", 50, 110) + pdf.TransformBegin() + pdf.TransformRotate(20, 50, 120) + refDupe() + pdf.TransformEnd() + + // Skew 30 degrees along the x-axis centered by the lower left corner of the + // rectangle + refDraw("Skew", 125, 110) + pdf.TransformBegin() + pdf.TransformSkewX(30, 125, 110) + refDupe() + pdf.TransformEnd() + + // Mirror horizontally with axis of reflection at left side of the rectangle + refDraw("Mirror horizontal", 50, 160) + pdf.TransformBegin() + pdf.TransformMirrorHorizontal(50) + refDupe() + pdf.TransformEnd() + + // Mirror vertically with axis of reflection at bottom side of the rectangle + refDraw("Mirror vertical", 125, 160) + pdf.TransformBegin() + pdf.TransformMirrorVertical(170) + refDupe() + pdf.TransformEnd() + + // Reflect against a point at the lower left point of rectangle + refDraw("Mirror point", 50, 210) + pdf.TransformBegin() + pdf.TransformMirrorPoint(50, 220) + refDupe() + pdf.TransformEnd() + + // Mirror against a straight line described by a point and an angle + angle := -20.0 + px := 120.0 + py := 220.0 + refDraw("Mirror line", 125, 210) + pdf.TransformBegin() + pdf.TransformRotate(angle, px, py) + pdf.Line(px-1, py-1, px+1, py+1) + pdf.Line(px-1, py+1, px+1, py-1) + pdf.Line(px-5, py, px+60, py) + pdf.TransformEnd() + pdf.TransformBegin() + pdf.TransformMirrorLine(angle, px, py) + refDupe() + pdf.TransformEnd() + + fileStr := example.Filename("Fpdf_TransformBegin") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_TransformBegin.pdf +} + +// This example demonstrates Lawrence Kesteloot's image registration code. +func ExampleFpdf_RegisterImage() { + const ( + margin = 10 + wd = 210 + ht = 297 + ) + fileList := []string{ + "logo-gray.png", + "logo.jpg", + "logo.png", + "logo-rgb.png", + "logo-progressive.jpg", + } + var infoPtr *gofpdf.ImageInfoType + var imageFileStr string + var imgWd, imgHt, lf, tp float64 + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + pdf.SetMargins(10, 10, 10) + pdf.SetFont("Helvetica", "", 15) + for j, str := range fileList { + imageFileStr = example.ImageFile(str) + infoPtr = pdf.RegisterImage(imageFileStr, "") + imgWd, imgHt = infoPtr.Extent() + switch j { + case 0: + lf = margin + tp = margin + case 1: + lf = wd - margin - imgWd + tp = margin + case 2: + lf = (wd - imgWd) / 2.0 + tp = (ht - imgHt) / 2.0 + case 3: + lf = margin + tp = ht - imgHt - margin + case 4: + lf = wd - imgWd - margin + tp = ht - imgHt - margin + } + pdf.Image(imageFileStr, lf, tp, imgWd, imgHt, false, "", 0, "") + } + fileStr := example.Filename("Fpdf_RegisterImage") + // Test the image information retrieval method + infoShow := func(imageStr string) { + imageStr = example.ImageFile(imageStr) + info := pdf.GetImageInfo(imageStr) + if info != nil { + if info.Width() > 0.0 { + fmt.Printf("Image %s is registered\n", filepath.ToSlash(imageStr)) + } else { + fmt.Printf("Incorrect information for image %s\n", filepath.ToSlash(imageStr)) + } + } else { + fmt.Printf("Image %s is not registered\n", filepath.ToSlash(imageStr)) + } + } + infoShow(fileList[0]) + infoShow("foo.png") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Image image/logo-gray.png is registered + // Image image/foo.png is not registered + // Successfully generated pdf/Fpdf_RegisterImage.pdf +} + +// This example demonstrates Bruno Michel's line splitting function. +func ExampleFpdf_SplitLines() { + const ( + fontPtSize = 18.0 + wd = 100.0 + ) + pdf := gofpdf.New("P", "mm", "A4", "") // A4 210.0 x 297.0 + pdf.SetFont("Times", "", fontPtSize) + _, lineHt := pdf.GetFontSize() + pdf.AddPage() + pdf.SetMargins(10, 10, 10) + lines := pdf.SplitLines([]byte(lorem()), wd) + ht := float64(len(lines)) * lineHt + y := (297.0 - ht) / 2.0 + pdf.SetDrawColor(128, 128, 128) + pdf.SetFillColor(255, 255, 210) + x := (210.0 - (wd + 40.0)) / 2.0 + pdf.Rect(x, y-20.0, wd+40.0, ht+40.0, "FD") + pdf.SetY(y) + for _, line := range lines { + pdf.CellFormat(190.0, lineHt, string(line), "", 1, "C", false, 0, "") + } + fileStr := example.Filename("Fpdf_Splitlines") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_Splitlines.pdf +} + +// This example demonstrates how to render a simple path-only SVG image of the +// type generated by the jSignature web control. +func ExampleFpdf_SVGBasicWrite() { + const ( + fontPtSize = 16.0 + wd = 100.0 + sigFileStr = "signature.svg" + ) + var ( + sig gofpdf.SVGBasicType + err error + ) + pdf := gofpdf.New("P", "mm", "A4", "") // A4 210.0 x 297.0 + pdf.SetFont("Times", "", fontPtSize) + lineHt := pdf.PointConvert(fontPtSize) + pdf.AddPage() + pdf.SetMargins(10, 10, 10) + htmlStr := `This example renders a simple ` + + `<a href="http://www.w3.org/TR/SVG/">SVG</a> (scalable vector graphics) ` + + `image that contains only basic path commands without any styling, ` + + `color fill, reflection or endpoint closures. In particular, the ` + + `type of vector graphic returned from a ` + + `<a href="http://willowsystems.github.io/jSignature/#/demo/">jSignature</a> ` + + `web control is supported and is used in this example.` + html := pdf.HTMLBasicNew() + html.Write(lineHt, htmlStr) + sig, err = gofpdf.SVGBasicFileParse(example.ImageFile(sigFileStr)) + if err == nil { + scale := 100 / sig.Wd + scaleY := 30 / sig.Ht + if scale > scaleY { + scale = scaleY + } + pdf.SetLineCapStyle("round") + pdf.SetLineWidth(0.25) + pdf.SetDrawColor(0, 0, 128) + pdf.SetXY((210.0-scale*sig.Wd)/2.0, pdf.GetY()+10) + pdf.SVGBasicWrite(&sig, scale) + } else { + pdf.SetError(err) + } + fileStr := example.Filename("Fpdf_SVGBasicWrite") + err = pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_SVGBasicWrite.pdf +} + +// This example demonstrates Stefan Schroeder's code to control vertical +// alignment. +func ExampleFpdf_CellFormat_align() { + type recType struct { + align, txt string + } + recList := []recType{ + {"TL", "top left"}, + {"TC", "top center"}, + {"TR", "top right"}, + {"LM", "middle left"}, + {"CM", "middle center"}, + {"RM", "middle right"}, + {"BL", "bottom left"}, + {"BC", "bottom center"}, + {"BR", "bottom right"}, + } + recListBaseline := []recType{ + {"AL", "baseline left"}, + {"AC", "baseline center"}, + {"AR", "baseline right"}, + } + var formatRect = func(pdf *gofpdf.Fpdf, recList []recType) { + linkStr := "" + for pageJ := 0; pageJ < 2; pageJ++ { + pdf.AddPage() + pdf.SetMargins(10, 10, 10) + pdf.SetAutoPageBreak(false, 0) + borderStr := "1" + for _, rec := range recList { + pdf.SetXY(20, 20) + pdf.CellFormat(170, 257, rec.txt, borderStr, 0, rec.align, false, 0, linkStr) + borderStr = "" + } + linkStr = "https://github.com/jung-kurt/gofpdf" + } + } + pdf := gofpdf.New("P", "mm", "A4", "") // A4 210.0 x 297.0 + pdf.SetFont("Helvetica", "", 16) + formatRect(pdf, recList) + formatRect(pdf, recListBaseline) + var fr fontResourceType + pdf.SetFontLoader(fr) + pdf.AddFont("Calligrapher", "", "calligra.json") + pdf.SetFont("Calligrapher", "", 16) + formatRect(pdf, recListBaseline) + fileStr := example.Filename("Fpdf_CellFormat_align") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Generalized font loader reading calligra.json + // Generalized font loader reading calligra.z + // Successfully generated pdf/Fpdf_CellFormat_align.pdf +} + +// This example demonstrates the use of characters in the high range of the +// Windows-1252 code page (gofdpf default). See the example for CellFormat (4) +// for a way to do this automatically. +func ExampleFpdf_CellFormat_codepageescape() { + pdf := gofpdf.New("P", "mm", "A4", "") // A4 210.0 x 297.0 + fontSize := 16.0 + pdf.SetFont("Helvetica", "", fontSize) + ht := pdf.PointConvert(fontSize) + write := func(str string) { + pdf.CellFormat(190, ht, str, "", 1, "C", false, 0, "") + pdf.Ln(ht) + } + pdf.AddPage() + htmlStr := `Until gofpdf supports UTF-8 encoded source text, source text needs ` + + `to be specified with all special characters escaped to match the code page ` + + `layout of the currently selected font. By default, gofdpf uses code page 1252.` + + ` See <a href="http://en.wikipedia.org/wiki/Windows-1252">Wikipedia</a> for ` + + `a table of this layout.` + html := pdf.HTMLBasicNew() + html.Write(ht, htmlStr) + pdf.Ln(2 * ht) + write("Voix ambigu\xeb d'un c\x9cur qui au z\xe9phyr pr\xe9f\xe8re les jattes de kiwi.") + write("Falsches \xdcben von Xylophonmusik qu\xe4lt jeden gr\xf6\xdferen Zwerg.") + write("Heiz\xf6lr\xfccksto\xdfabd\xe4mpfung") + write("For\xe5rsj\xe6vnd\xf8gn / Efter\xe5rsj\xe6vnd\xf8gn") + fileStr := example.Filename("Fpdf_CellFormat_codepageescape") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_CellFormat_codepageescape.pdf +} + +// This example demonstrates the automatic conversion of UTF-8 strings to an +// 8-bit font encoding. +func ExampleFpdf_CellFormat_codepage() { + pdf := gofpdf.New("P", "mm", "A4", example.FontDir()) // A4 210.0 x 297.0 + // See documentation for details on how to generate fonts + pdf.AddFont("Helvetica-1251", "", "helvetica_1251.json") + pdf.AddFont("Helvetica-1253", "", "helvetica_1253.json") + fontSize := 16.0 + pdf.SetFont("Helvetica", "", fontSize) + ht := pdf.PointConvert(fontSize) + tr := pdf.UnicodeTranslatorFromDescriptor("") // "" defaults to "cp1252" + write := func(str string) { + // pdf.CellFormat(190, ht, tr(str), "", 1, "C", false, 0, "") + pdf.MultiCell(190, ht, tr(str), "", "C", false) + pdf.Ln(ht) + } + pdf.AddPage() + str := `Gofpdf provides a translator that will convert any UTF-8 code point ` + + `that is present in the specified code page.` + pdf.MultiCell(190, ht, str, "", "L", false) + pdf.Ln(2 * ht) + write("Voix ambiguë d'un cœur qui au zéphyr préfère les jattes de kiwi.") + write("Falsches Üben von Xylophonmusik quält jeden größeren Zwerg.") + write("Heizölrückstoßabdämpfung") + write("Forårsjævndøgn / Efterårsjævndøgn") + write("À noite, vovô Kowalsky vê o ímã cair no pé do pingüim queixoso e vovó" + + "põe açúcar no chá de tâmaras do jabuti feliz.") + pdf.SetFont("Helvetica-1251", "", fontSize) // Name matches one specified in AddFont() + tr = pdf.UnicodeTranslatorFromDescriptor("cp1251") + write("Съешь же ещё этих мягких французских булок, да выпей чаю.") + + pdf.SetFont("Helvetica-1253", "", fontSize) + tr = pdf.UnicodeTranslatorFromDescriptor("cp1253") + write("Θέλει αρετή και τόλμη η ελευθερία. (Ανδρέας Κάλβος)") + + fileStr := example.Filename("Fpdf_CellFormat_codepage") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_CellFormat_codepage.pdf +} + +// This example demonstrates password protection for documents. +func ExampleFpdf_SetProtection() { + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.SetProtection(gofpdf.CnProtectPrint, "123", "abc") + pdf.AddPage() + pdf.SetFont("Arial", "", 12) + pdf.Write(10, "Password-protected.") + fileStr := example.Filename("Fpdf_SetProtection") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_SetProtection.pdf +} + +// This example displays equilateral polygons in a demonstration of the Polygon +// function. +func ExampleFpdf_Polygon() { + const rowCount = 5 + const colCount = 4 + const ptSize = 36 + var x, y, radius, gap, advance float64 + var rgVal int + var pts []gofpdf.PointType + vertices := func(count int) (res []gofpdf.PointType) { + var pt gofpdf.PointType + res = make([]gofpdf.PointType, 0, count) + mlt := 2.0 * math.Pi / float64(count) + for j := 0; j < count; j++ { + pt.Y, pt.X = math.Sincos(float64(j) * mlt) + res = append(res, gofpdf.PointType{ + X: x + radius*pt.X, + Y: y + radius*pt.Y}) + } + return + } + pdf := gofpdf.New("P", "mm", "A4", "") // A4 210.0 x 297.0 + pdf.AddPage() + pdf.SetFont("Helvetica", "", ptSize) + pdf.SetDrawColor(0, 80, 180) + gap = 12.0 + pdf.SetY(gap) + pdf.CellFormat(190.0, gap, "Equilateral polygons", "", 1, "C", false, 0, "") + radius = (210.0 - float64(colCount+1)*gap) / (2.0 * float64(colCount)) + advance = gap + 2.0*radius + y = 2*gap + pdf.PointConvert(ptSize) + radius + rgVal = 230 + for row := 0; row < rowCount; row++ { + pdf.SetFillColor(rgVal, rgVal, 0) + rgVal -= 12 + x = gap + radius + for col := 0; col < colCount; col++ { + pts = vertices(row*colCount + col + 3) + pdf.Polygon(pts, "FD") + x += advance + } + y += advance + } + fileStr := example.Filename("Fpdf_Polygon") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_Polygon.pdf +} + +// This example demonstrates document layers. The initial visibility of a layer +// is specified with the second parameter to AddLayer(). The layer list +// displayed by the document reader allows layer visibility to be controlled +// interactively. +func ExampleFpdf_AddLayer() { + + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + pdf.SetFont("Arial", "", 15) + pdf.Write(8, "This line doesn't belong to any layer.\n") + + // Define layers + l1 := pdf.AddLayer("Layer 1", true) + l2 := pdf.AddLayer("Layer 2", true) + + // Open layer pane in PDF viewer + pdf.OpenLayerPane() + + // First layer + pdf.BeginLayer(l1) + pdf.Write(8, "This line belongs to layer 1.\n") + pdf.EndLayer() + + // Second layer + pdf.BeginLayer(l2) + pdf.Write(8, "This line belongs to layer 2.\n") + pdf.EndLayer() + + // First layer again + pdf.BeginLayer(l1) + pdf.Write(8, "This line belongs to layer 1 again.\n") + pdf.EndLayer() + + fileStr := example.Filename("Fpdf_AddLayer") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_AddLayer.pdf +} + +// This example demonstrates the use of an image that is retrieved from a web +// server. +func ExampleFpdf_RegisterImageReader() { + + const ( + margin = 10 + wd = 210 + ht = 297 + fontSize = 15 + urlStr = "https://github.com/jung-kurt/gofpdf/blob/master/image/gofpdf.png?raw=true" + msgStr = `Images from the web can be easily embedded when a PDF document is generated.` + ) + + var ( + rsp *http.Response + err error + tp string + ) + + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + pdf.SetFont("Helvetica", "", fontSize) + ln := pdf.PointConvert(fontSize) + pdf.MultiCell(wd-margin-margin, ln, msgStr, "", "L", false) + rsp, err = http.Get(urlStr) + if err == nil { + tp = pdf.ImageTypeFromMime(rsp.Header["Content-Type"][0]) + infoPtr := pdf.RegisterImageReader(urlStr, tp, rsp.Body) + if pdf.Ok() { + imgWd, imgHt := infoPtr.Extent() + pdf.Image(urlStr, (wd-imgWd)/2.0, pdf.GetY()+ln, + imgWd, imgHt, false, tp, 0, "") + } + } else { + pdf.SetError(err) + } + fileStr := example.Filename("Fpdf_RegisterImageReader_url") + err = pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_RegisterImageReader_url.pdf + +} + +// This example demonstrates the Beziergon function. +func ExampleFpdf_Beziergon() { + + const ( + margin = 10 + wd = 210 + unit = (wd - 2*margin) / 6 + ht = 297 + fontSize = 15 + msgStr = `Demonstration of Beziergon function` + coefficient = 0.6 + delta = coefficient * unit + ln = fontSize * 25.4 / 72 + offsetX = (wd - 4*unit) / 2.0 + offsetY = offsetX + 2*ln + ) + + srcList := []gofpdf.PointType{ + {X: 0, Y: 0}, + {X: 1, Y: 0}, + {X: 1, Y: 1}, + {X: 2, Y: 1}, + {X: 2, Y: 2}, + {X: 3, Y: 2}, + {X: 3, Y: 3}, + {X: 4, Y: 3}, + {X: 4, Y: 4}, + {X: 1, Y: 4}, + {X: 1, Y: 3}, + {X: 0, Y: 3}, + } + + ctrlList := []gofpdf.PointType{ + {X: 1, Y: -1}, + {X: 1, Y: 1}, + {X: 1, Y: 1}, + {X: 1, Y: 1}, + {X: 1, Y: 1}, + {X: 1, Y: 1}, + {X: 1, Y: 1}, + {X: 1, Y: 1}, + {X: -1, Y: 1}, + {X: -1, Y: -1}, + {X: -1, Y: -1}, + {X: -1, Y: -1}, + } + + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + pdf.SetFont("Helvetica", "", fontSize) + for j, src := range srcList { + srcList[j].X = offsetX + src.X*unit + srcList[j].Y = offsetY + src.Y*unit + } + for j, ctrl := range ctrlList { + ctrlList[j].X = ctrl.X * delta + ctrlList[j].Y = ctrl.Y * delta + } + jPrev := len(srcList) - 1 + srcPrev := srcList[jPrev] + curveList := []gofpdf.PointType{srcPrev} // point [, control 0, control 1, point]* + control := func(x, y float64) { + curveList = append(curveList, gofpdf.PointType{X: x, Y: y}) + } + for j, src := range srcList { + ctrl := ctrlList[jPrev] + control(srcPrev.X+ctrl.X, srcPrev.Y+ctrl.Y) // Control 0 + ctrl = ctrlList[j] + control(src.X-ctrl.X, src.Y-ctrl.Y) // Control 1 + curveList = append(curveList, src) // Destination + jPrev = j + srcPrev = src + } + pdf.MultiCell(wd-margin-margin, ln, msgStr, "", "C", false) + pdf.SetDashPattern([]float64{0.8, 0.8}, 0) + pdf.SetDrawColor(160, 160, 160) + pdf.Polygon(srcList, "D") + pdf.SetDashPattern([]float64{}, 0) + pdf.SetDrawColor(64, 64, 128) + pdf.SetLineWidth(pdf.GetLineWidth() * 3) + pdf.Beziergon(curveList, "D") + fileStr := example.Filename("Fpdf_Beziergon") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_Beziergon.pdf + +} + +// This example demonstrates loading a non-standard font using a generalized +// font loader. fontResourceType implements the FontLoader interface and is +// defined locally in the test source code. +func ExampleFpdf_SetFontLoader() { + var fr fontResourceType + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.SetFontLoader(fr) + pdf.AddFont("Calligrapher", "", "calligra.json") + pdf.AddPage() + pdf.SetFont("Calligrapher", "", 35) + pdf.Cell(0, 10, "Load fonts from any source") + fileStr := example.Filename("Fpdf_SetFontLoader") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Generalized font loader reading calligra.json + // Generalized font loader reading calligra.z + // Successfully generated pdf/Fpdf_SetFontLoader.pdf +} + +// This example demonstrates the Path Drawing functions, such as: MoveTo, +// LineTo, CurveTo, ..., ClosePath and DrawPath. +func ExampleFpdf_MoveTo() { + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + pdf.MoveTo(20, 20) + pdf.LineTo(170, 20) + pdf.ArcTo(170, 40, 20, 20, 0, 90, 0) + pdf.CurveTo(190, 100, 105, 100) + pdf.CurveBezierCubicTo(20, 100, 105, 200, 20, 200) + pdf.ClosePath() + pdf.SetFillColor(200, 200, 200) + pdf.SetLineWidth(3) + pdf.DrawPath("DF") + fileStr := example.Filename("Fpdf_MoveTo_path") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_MoveTo_path.pdf +} + +// This example demonstrates various line cap and line join styles. +func ExampleFpdf_SetLineJoinStyle() { + const offset = 75.0 + pdf := gofpdf.New("L", "mm", "A4", "") + pdf.AddPage() + var draw = func(cap, join string, x0, y0, x1, y1 float64) { + // transform begin & end needed to isolate caps and joins + pdf.SetLineCapStyle(cap) + pdf.SetLineJoinStyle(join) + + // Draw thick line + pdf.SetDrawColor(0x33, 0x33, 0x33) + pdf.SetLineWidth(30.0) + pdf.MoveTo(x0, y0) + pdf.LineTo((x0+x1)/2+offset, (y0+y1)/2) + pdf.LineTo(x1, y1) + pdf.DrawPath("D") + + // Draw thin helping line + pdf.SetDrawColor(0xFF, 0x33, 0x33) + pdf.SetLineWidth(2.56) + pdf.MoveTo(x0, y0) + pdf.LineTo((x0+x1)/2+offset, (y0+y1)/2) + pdf.LineTo(x1, y1) + pdf.DrawPath("D") + + } + x := 35.0 + caps := []string{"butt", "square", "round"} + joins := []string{"bevel", "miter", "round"} + for i := range caps { + draw(caps[i], joins[i], x, 50, x, 160) + x += offset + } + fileStr := example.Filename("Fpdf_SetLineJoinStyle_caps") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_SetLineJoinStyle_caps.pdf +} + +// This example demonstrates various fill modes. +func ExampleFpdf_DrawPath() { + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.SetDrawColor(0xff, 0x00, 0x00) + pdf.SetFillColor(0x99, 0x99, 0x99) + pdf.SetFont("Helvetica", "", 15) + pdf.AddPage() + pdf.SetAlpha(1, "Multiply") + var ( + polygon = func(cx, cy, r, n, dir float64) { + da := 2 * math.Pi / n + pdf.MoveTo(cx+r, cy) + pdf.Text(cx+r, cy, "0") + i := 1 + for a := da; a < 2*math.Pi; a += da { + x, y := cx+r*math.Cos(dir*a), cy+r*math.Sin(dir*a) + pdf.LineTo(x, y) + pdf.Text(x, y, strconv.Itoa(i)) + i++ + } + pdf.ClosePath() + } + polygons = func(cx, cy, r, n, dir float64) { + d := 1.0 + for rf := r; rf > 0; rf -= 10 { + polygon(cx, cy, rf, n, d) + d *= dir + } + } + star = func(cx, cy, r, n float64) { + da := 4 * math.Pi / n + pdf.MoveTo(cx+r, cy) + for a := da; a < 4*math.Pi+da; a += da { + x, y := cx+r*math.Cos(a), cy+r*math.Sin(a) + pdf.LineTo(x, y) + } + pdf.ClosePath() + } + ) + // triangle + polygons(55, 45, 40, 3, 1) + pdf.DrawPath("B") + pdf.Text(15, 95, "B (same direction, non zero winding)") + + // square + polygons(155, 45, 40, 4, 1) + pdf.DrawPath("B*") + pdf.Text(115, 95, "B* (same direction, even odd)") + + // pentagon + polygons(55, 145, 40, 5, -1) + pdf.DrawPath("B") + pdf.Text(15, 195, "B (different direction, non zero winding)") + + // hexagon + polygons(155, 145, 40, 6, -1) + pdf.DrawPath("B*") + pdf.Text(115, 195, "B* (different direction, even odd)") + + // star + star(55, 245, 40, 5) + pdf.DrawPath("B") + pdf.Text(15, 290, "B (non zero winding)") + + // star + star(155, 245, 40, 5) + pdf.DrawPath("B*") + pdf.Text(115, 290, "B* (even odd)") + + fileStr := example.Filename("Fpdf_DrawPath_fill") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_DrawPath_fill.pdf +} + +// This example demonstrates creating and using templates +func ExampleFpdf_CreateTemplate() { + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.SetCompression(false) + // pdf.SetFont("Times", "", 12) + template := pdf.CreateTemplate(func(tpl *gofpdf.Tpl) { + tpl.Image(example.ImageFile("logo.png"), 6, 6, 30, 0, false, "", 0, "") + tpl.SetFont("Arial", "B", 16) + tpl.Text(40, 20, "Template says hello") + tpl.SetDrawColor(0, 100, 200) + tpl.SetLineWidth(2.5) + tpl.Line(95, 12, 105, 22) + }) + _, tplSize := template.Size() + // fmt.Println("Size:", tplSize) + // fmt.Println("Scaled:", tplSize.ScaleBy(1.5)) + + template2 := pdf.CreateTemplate(func(tpl *gofpdf.Tpl) { + tpl.UseTemplate(template) + subtemplate := tpl.CreateTemplate(func(tpl2 *gofpdf.Tpl) { + tpl2.Image(example.ImageFile("logo.png"), 6, 86, 30, 0, false, "", 0, "") + tpl2.SetFont("Arial", "B", 16) + tpl2.Text(40, 100, "Subtemplate says hello") + tpl2.SetDrawColor(0, 200, 100) + tpl2.SetLineWidth(2.5) + tpl2.Line(102, 92, 112, 102) + }) + tpl.UseTemplate(subtemplate) + }) + + pdf.SetDrawColor(200, 100, 0) + pdf.SetLineWidth(2.5) + pdf.SetFont("Arial", "B", 16) + + pdf.AddPage() + pdf.UseTemplate(template) + pdf.UseTemplateScaled(template, gofpdf.PointType{X: 0, Y: 30}, tplSize) + pdf.UseTemplateScaled(template, gofpdf.PointType{X: 0, Y: 60}, tplSize.ScaleBy(1.4)) + pdf.Line(40, 210, 60, 210) + pdf.Text(40, 200, "Template example page 1") + + pdf.AddPage() + pdf.UseTemplate(template2) + pdf.Line(60, 210, 80, 210) + pdf.Text(40, 200, "Template example page 2") + + fileStr := example.Filename("Fpdf_CreateTemplate") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_CreateTemplate.pdf +} + +// This example demonstrate how to use embedded fonts from byte array +func ExampleFpdf_AddFontFromBytes() { + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + pdf.AddFontFromBytes("calligra", "", files.CalligraJson, files.CalligraZ) + pdf.SetFont("calligra", "", 16) + pdf.Cell(40, 10, "Hello World With Embedded Font!") + fileStr := example.Filename("Fpdf_EmbeddedFont") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_EmbeddedFont.pdf +} + +// This example demonstrate Clipped table cells +func ExampleFpdf_ClipRect() { + marginCell := 2. // margin of top/bottom of cell + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.SetFont("Arial", "", 12) + pdf.AddPage() + pagew, pageh := pdf.GetPageSize() + mleft, mright, _, mbottom := pdf.GetMargins() + + cols := []float64{60, 100, pagew - mleft - mright - 100 - 60} + rows := [][]string{} + for i := 1; i <= 50; i++ { + word := fmt.Sprintf("%d:%s", i, strings.Repeat("A", i%100)) + rows = append(rows, []string{word, word, word}) + } + + for _, row := range rows { + _, lineHt := pdf.GetFontSize() + height := lineHt + marginCell + + x, y := pdf.GetXY() + // add a new page if the height of the row doesn't fit on the page + if y+height >= pageh-mbottom { + pdf.AddPage() + x, y = pdf.GetXY() + } + for i, txt := range row { + width := cols[i] + pdf.Rect(x, y, width, height, "") + pdf.ClipRect(x, y, width, height, false) + pdf.Cell(width, height, txt) + pdf.ClipEnd() + x += width + } + pdf.Ln(-1) + } + fileStr := example.Filename("Fpdf_ClippedTableCells") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_ClippedTableCells.pdf +} + +// This example demonstrate wrapped table cells +func ExampleFpdf_Rect() { + marginCell := 2. // margin of top/bottom of cell + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.SetFont("Arial", "", 12) + pdf.AddPage() + pagew, pageh := pdf.GetPageSize() + mleft, mright, _, mbottom := pdf.GetMargins() + + cols := []float64{60, 100, pagew - mleft - mright - 100 - 60} + rows := [][]string{} + for i := 1; i <= 30; i++ { + word := fmt.Sprintf("%d:%s", i, strings.Repeat("A", i%100)) + rows = append(rows, []string{word, word, word}) + } + + for _, row := range rows { + curx, y := pdf.GetXY() + x := curx + + height := 0. + _, lineHt := pdf.GetFontSize() + + for i, txt := range row { + lines := pdf.SplitLines([]byte(txt), cols[i]) + h := float64(len(lines))*lineHt + marginCell*float64(len(lines)) + if h > height { + height = h + } + } + // add a new page if the height of the row doesn't fit on the page + if pdf.GetY()+height > pageh-mbottom { + pdf.AddPage() + y = pdf.GetY() + } + for i, txt := range row { + width := cols[i] + pdf.Rect(x, y, width, height, "") + pdf.MultiCell(width, lineHt+marginCell, txt, "", "", false) + x += width + pdf.SetXY(x, y) + } + pdf.SetXY(curx, y+height) + } + fileStr := example.Filename("Fpdf_WrappedTableCells") + err := pdf.OutputFileAndClose(fileStr) + example.Summary(err, fileStr) + // Output: + // Successfully generated pdf/Fpdf_WrappedTableCells.pdf +} |
