github.com/phpdave11/gofpdf@v1.4.2/fpdf_test.go (about) 1 /* 2 * Copyright (c) 2013-2015 Kurt Jung (Gmail: kurt.w.jung) 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 package gofpdf_test 18 19 import ( 20 "bufio" 21 "bytes" 22 "fmt" 23 "io" 24 "io/ioutil" 25 "math" 26 "math/rand" 27 "net/http" 28 "os" 29 "path/filepath" 30 "strconv" 31 "strings" 32 "testing" 33 "time" 34 35 "github.com/phpdave11/gofpdf" 36 "github.com/phpdave11/gofpdf/internal/example" 37 "github.com/phpdave11/gofpdf/internal/files" 38 ) 39 40 func init() { 41 cleanup() 42 } 43 44 func cleanup() { 45 filepath.Walk(example.PdfDir(), 46 func(path string, info os.FileInfo, err error) (reterr error) { 47 if info.Mode().IsRegular() { 48 dir, _ := filepath.Split(path) 49 if "reference" != filepath.Base(dir) { 50 if len(path) > 3 { 51 if path[len(path)-4:] == ".pdf" { 52 os.Remove(path) 53 } 54 } 55 } 56 } 57 return 58 }) 59 } 60 61 func TestFpdfImplementPdf(t *testing.T) { 62 // this will not compile if Fpdf and Tpl 63 // do not implement Pdf 64 var _ gofpdf.Pdf = (*gofpdf.Fpdf)(nil) 65 var _ gofpdf.Pdf = (*gofpdf.Tpl)(nil) 66 } 67 68 // TestPagedTemplate ensures new paged templates work 69 func TestPagedTemplate(t *testing.T) { 70 pdf := gofpdf.New("P", "mm", "A4", "") 71 tpl := pdf.CreateTemplate(func(t *gofpdf.Tpl) { 72 // this will be the second page, as a page is already 73 // created by default 74 t.AddPage() 75 t.AddPage() 76 t.AddPage() 77 }) 78 79 if tpl.NumPages() != 4 { 80 t.Fatalf("The template does not have the correct number of pages %d", tpl.NumPages()) 81 } 82 83 tplPages := tpl.FromPages() 84 for x := 0; x < len(tplPages); x++ { 85 pdf.AddPage() 86 pdf.UseTemplate(tplPages[x]) 87 } 88 89 // get the last template 90 tpl2, err := tpl.FromPage(tpl.NumPages()) 91 if err != nil { 92 t.Fatal(err) 93 } 94 95 // the objects should be the exact same, as the 96 // template will represent the last page by default 97 // therefore no new id should be set, and the object 98 // should be the same object 99 if fmt.Sprintf("%p", tpl2) != fmt.Sprintf("%p", tpl) { 100 t.Fatal("Template no longer respecting initial template object") 101 } 102 } 103 104 // TestIssue0116 addresses issue 116 in which library silently fails after 105 // calling CellFormat when no font has been set. 106 func TestIssue0116(t *testing.T) { 107 var pdf *gofpdf.Fpdf 108 109 pdf = gofpdf.New("P", "mm", "A4", "") 110 pdf.AddPage() 111 pdf.SetFont("Arial", "B", 16) 112 pdf.Cell(40, 10, "OK") 113 if pdf.Error() != nil { 114 t.Fatalf("not expecting error when rendering text") 115 } 116 117 pdf = gofpdf.New("P", "mm", "A4", "") 118 pdf.AddPage() 119 pdf.Cell(40, 10, "Not OK") // Font not set 120 if pdf.Error() == nil { 121 t.Fatalf("expecting error when rendering text without having set font") 122 } 123 } 124 125 // TestIssue0193 addresses issue 193 in which the error io.EOF is incorrectly 126 // assigned to the FPDF instance error. 127 func TestIssue0193(t *testing.T) { 128 var png []byte 129 var pdf *gofpdf.Fpdf 130 var err error 131 var rdr *bytes.Reader 132 133 png, err = ioutil.ReadFile(example.ImageFile("sweden.png")) 134 if err == nil { 135 rdr = bytes.NewReader(png) 136 pdf = gofpdf.New("P", "mm", "A4", "") 137 pdf.AddPage() 138 _ = pdf.RegisterImageOptionsReader("sweden", gofpdf.ImageOptions{ImageType: "png", ReadDpi: true}, rdr) 139 err = pdf.Error() 140 } 141 if err != nil { 142 t.Fatalf("issue 193 error: %s", err) 143 } 144 145 } 146 147 // TestIssue0209SplitLinesEqualMultiCell addresses issue 209 148 // make SplitLines and MultiCell split at the same place 149 func TestIssue0209SplitLinesEqualMultiCell(t *testing.T) { 150 var pdf *gofpdf.Fpdf 151 152 pdf = gofpdf.New("P", "mm", "A4", "") 153 pdf.AddPage() 154 pdf.SetFont("Arial", "", 8) 155 // this sentence should not be splited 156 str := "Guochin Amandine" 157 lines := pdf.SplitLines([]byte(str), 26) 158 _, FontSize := pdf.GetFontSize() 159 y_start := pdf.GetY() 160 pdf.MultiCell(26, FontSize, str, "", "L", false) 161 y_end := pdf.GetY() 162 163 if len(lines) != 1 { 164 t.Fatalf("expect SplitLines split in one line") 165 } 166 if int(y_end-y_start) != int(FontSize) { 167 t.Fatalf("expect MultiCell split in one line %.2f != %.2f", y_end-y_start, FontSize) 168 } 169 170 // this sentence should be splited in two lines 171 str = "Guiochini Amandine" 172 lines = pdf.SplitLines([]byte(str), 26) 173 y_start = pdf.GetY() 174 pdf.MultiCell(26, FontSize, str, "", "L", false) 175 y_end = pdf.GetY() 176 177 if len(lines) != 2 { 178 t.Fatalf("expect SplitLines split in two lines") 179 } 180 if int(y_end-y_start) != int(FontSize*2) { 181 t.Fatalf("expect MultiCell split in two lines %.2f != %.2f", y_end-y_start, FontSize*2) 182 } 183 } 184 185 // TestFooterFuncLpi tests to make sure the footer is not call twice and SetFooterFuncLpi can work 186 // without SetFooterFunc. 187 func TestFooterFuncLpi(t *testing.T) { 188 pdf := gofpdf.New("P", "mm", "A4", "") 189 var ( 190 oldFooterFnc = "oldFooterFnc" 191 bothPages = "bothPages" 192 firstPageOnly = "firstPageOnly" 193 lastPageOnly = "lastPageOnly" 194 ) 195 196 // This set just for testing, only set SetFooterFuncLpi. 197 pdf.SetFooterFunc(func() { 198 pdf.SetY(-15) 199 pdf.SetFont("Arial", "I", 8) 200 pdf.CellFormat(0, 10, oldFooterFnc, 201 "", 0, "C", false, 0, "") 202 }) 203 pdf.SetFooterFuncLpi(func(lastPage bool) { 204 pdf.SetY(-15) 205 pdf.SetFont("Arial", "I", 8) 206 pdf.CellFormat(0, 10, bothPages, "", 0, "L", false, 0, "") 207 if !lastPage { 208 pdf.CellFormat(0, 10, firstPageOnly, "", 0, "C", false, 0, "") 209 } else { 210 pdf.CellFormat(0, 10, lastPageOnly, "", 0, "C", false, 0, "") 211 } 212 }) 213 pdf.AddPage() 214 pdf.SetFont("Arial", "B", 16) 215 for j := 1; j <= 40; j++ { 216 pdf.CellFormat(0, 10, fmt.Sprintf("Printing line number %d", j), 217 "", 1, "", false, 0, "") 218 } 219 if pdf.Error() != nil { 220 t.Fatalf("not expecting error when rendering text") 221 } 222 w := &bytes.Buffer{} 223 if err := pdf.Output(w); err != nil { 224 t.Errorf("unexpected err: %s", err) 225 } 226 b := w.Bytes() 227 if bytes.Contains(b, []byte(oldFooterFnc)) { 228 t.Errorf("not expecting %s render on pdf when FooterFncLpi is set", oldFooterFnc) 229 } 230 got := bytes.Count(b, []byte("bothPages")) 231 if got != 2 { 232 t.Errorf("footer %s should render on two page got:%d", bothPages, got) 233 } 234 got = bytes.Count(b, []byte(firstPageOnly)) 235 if got != 1 { 236 t.Errorf("footer %s should render only on first page got: %d", firstPageOnly, got) 237 } 238 got = bytes.Count(b, []byte(lastPageOnly)) 239 if got != 1 { 240 t.Errorf("footer %s should render only on first page got: %d", lastPageOnly, got) 241 } 242 f := bytes.Index(b, []byte(firstPageOnly)) 243 l := bytes.Index(b, []byte(lastPageOnly)) 244 if f > l { 245 t.Errorf("index %d (%s) should less than index %d (%s)", f, firstPageOnly, l, lastPageOnly) 246 } 247 } 248 249 type fontResourceType struct { 250 } 251 252 func (f fontResourceType) Open(name string) (rdr io.Reader, err error) { 253 var buf []byte 254 buf, err = ioutil.ReadFile(example.FontFile(name)) 255 if err == nil { 256 rdr = bytes.NewReader(buf) 257 fmt.Printf("Generalized font loader reading %s\n", name) 258 } 259 return 260 } 261 262 // strDelimit converts 'ABCDEFG' to, for example, 'A,BCD,EFG' 263 func strDelimit(str string, sepstr string, sepcount int) string { 264 pos := len(str) - sepcount 265 for pos > 0 { 266 str = str[:pos] + sepstr + str[pos:] 267 pos = pos - sepcount 268 } 269 return str 270 } 271 272 func loremList() []string { 273 return []string{ 274 "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod " + 275 "tempor incididunt ut labore et dolore magna aliqua.", 276 "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " + 277 "aliquip ex ea commodo consequat.", 278 "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum " + 279 "dolore eu fugiat nulla pariatur.", 280 "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui " + 281 "officia deserunt mollit anim id est laborum.", 282 } 283 } 284 285 func lorem() string { 286 return strings.Join(loremList(), " ") 287 } 288 289 // Example demonstrates the generation of a simple PDF document. Note that 290 // since only core fonts are used (in this case Arial, a synonym for 291 // Helvetica), an empty string can be specified for the font directory in the 292 // call to New(). Note also that the example.Filename() and example.Summary() 293 // functions belong to a separate, internal package and are not part of the 294 // gofpdf library. If an error occurs at some point during the construction of 295 // the document, subsequent method calls exit immediately and the error is 296 // finally retrieved with the output call where it can be handled by the 297 // application. 298 func Example() { 299 pdf := gofpdf.New(gofpdf.OrientationPortrait, "mm", "A4", "") 300 pdf.AddPage() 301 pdf.SetFont("Arial", "B", 16) 302 pdf.Cell(40, 10, "Hello World!") 303 fileStr := example.Filename("basic") 304 err := pdf.OutputFileAndClose(fileStr) 305 example.Summary(err, fileStr) 306 // Output: 307 // Successfully generated pdf/basic.pdf 308 } 309 310 // ExampleFpdf_AddPage demonsrates the generation of headers, footers and page breaks. 311 func ExampleFpdf_AddPage() { 312 pdf := gofpdf.New("P", "mm", "A4", "") 313 pdf.SetTopMargin(30) 314 pdf.SetHeaderFuncMode(func() { 315 pdf.Image(example.ImageFile("logo.png"), 10, 6, 30, 0, false, "", 0, "") 316 pdf.SetY(5) 317 pdf.SetFont("Arial", "B", 15) 318 pdf.Cell(80, 0, "") 319 pdf.CellFormat(30, 10, "Title", "1", 0, "C", false, 0, "") 320 pdf.Ln(20) 321 }, true) 322 pdf.SetFooterFunc(func() { 323 pdf.SetY(-15) 324 pdf.SetFont("Arial", "I", 8) 325 pdf.CellFormat(0, 10, fmt.Sprintf("Page %d/{nb}", pdf.PageNo()), 326 "", 0, "C", false, 0, "") 327 }) 328 pdf.AliasNbPages("") 329 pdf.AddPage() 330 pdf.SetFont("Times", "", 12) 331 for j := 1; j <= 40; j++ { 332 pdf.CellFormat(0, 10, fmt.Sprintf("Printing line number %d", j), 333 "", 1, "", false, 0, "") 334 } 335 fileStr := example.Filename("Fpdf_AddPage") 336 err := pdf.OutputFileAndClose(fileStr) 337 example.Summary(err, fileStr) 338 // Output: 339 // Successfully generated pdf/Fpdf_AddPage.pdf 340 } 341 342 // ExampleFpdf_MultiCell demonstrates word-wrapping, line justification and 343 // page-breaking. 344 func ExampleFpdf_MultiCell() { 345 pdf := gofpdf.New("P", "mm", "A4", "") 346 titleStr := "20000 Leagues Under the Seas" 347 pdf.SetTitle(titleStr, false) 348 pdf.SetAuthor("Jules Verne", false) 349 pdf.SetHeaderFunc(func() { 350 // Arial bold 15 351 pdf.SetFont("Arial", "B", 15) 352 // Calculate width of title and position 353 wd := pdf.GetStringWidth(titleStr) + 6 354 pdf.SetX((210 - wd) / 2) 355 // Colors of frame, background and text 356 pdf.SetDrawColor(0, 80, 180) 357 pdf.SetFillColor(230, 230, 0) 358 pdf.SetTextColor(220, 50, 50) 359 // Thickness of frame (1 mm) 360 pdf.SetLineWidth(1) 361 // Title 362 pdf.CellFormat(wd, 9, titleStr, "1", 1, "C", true, 0, "") 363 // Line break 364 pdf.Ln(10) 365 }) 366 pdf.SetFooterFunc(func() { 367 // Position at 1.5 cm from bottom 368 pdf.SetY(-15) 369 // Arial italic 8 370 pdf.SetFont("Arial", "I", 8) 371 // Text color in gray 372 pdf.SetTextColor(128, 128, 128) 373 // Page number 374 pdf.CellFormat(0, 10, fmt.Sprintf("Page %d", pdf.PageNo()), 375 "", 0, "C", false, 0, "") 376 }) 377 chapterTitle := func(chapNum int, titleStr string) { 378 // // Arial 12 379 pdf.SetFont("Arial", "", 12) 380 // Background color 381 pdf.SetFillColor(200, 220, 255) 382 // Title 383 pdf.CellFormat(0, 6, fmt.Sprintf("Chapter %d : %s", chapNum, titleStr), 384 "", 1, "L", true, 0, "") 385 // Line break 386 pdf.Ln(4) 387 } 388 chapterBody := func(fileStr string) { 389 // Read text file 390 txtStr, err := ioutil.ReadFile(fileStr) 391 if err != nil { 392 pdf.SetError(err) 393 } 394 // Times 12 395 pdf.SetFont("Times", "", 12) 396 // Output justified text 397 pdf.MultiCell(0, 5, string(txtStr), "", "", false) 398 // Line break 399 pdf.Ln(-1) 400 // Mention in italics 401 pdf.SetFont("", "I", 0) 402 pdf.Cell(0, 5, "(end of excerpt)") 403 } 404 printChapter := func(chapNum int, titleStr, fileStr string) { 405 pdf.AddPage() 406 chapterTitle(chapNum, titleStr) 407 chapterBody(fileStr) 408 } 409 printChapter(1, "A RUNAWAY REEF", example.TextFile("20k_c1.txt")) 410 printChapter(2, "THE PROS AND CONS", example.TextFile("20k_c2.txt")) 411 fileStr := example.Filename("Fpdf_MultiCell") 412 err := pdf.OutputFileAndClose(fileStr) 413 example.Summary(err, fileStr) 414 // Output: 415 // Successfully generated pdf/Fpdf_MultiCell.pdf 416 } 417 418 // ExampleFpdf_SetLeftMargin demonstrates the generation of a PDF document that has multiple 419 // columns. This is accomplished with the SetLeftMargin() and Cell() methods. 420 func ExampleFpdf_SetLeftMargin() { 421 var y0 float64 422 var crrntCol int 423 pdf := gofpdf.New("P", "mm", "A4", "") 424 pdf.SetDisplayMode("fullpage", "TwoColumnLeft") 425 titleStr := "20000 Leagues Under the Seas" 426 pdf.SetTitle(titleStr, false) 427 pdf.SetAuthor("Jules Verne", false) 428 setCol := func(col int) { 429 // Set position at a given column 430 crrntCol = col 431 x := 10.0 + float64(col)*65.0 432 pdf.SetLeftMargin(x) 433 pdf.SetX(x) 434 } 435 chapterTitle := func(chapNum int, titleStr string) { 436 // Arial 12 437 pdf.SetFont("Arial", "", 12) 438 // Background color 439 pdf.SetFillColor(200, 220, 255) 440 // Title 441 pdf.CellFormat(0, 6, fmt.Sprintf("Chapter %d : %s", chapNum, titleStr), 442 "", 1, "L", true, 0, "") 443 // Line break 444 pdf.Ln(4) 445 y0 = pdf.GetY() 446 } 447 chapterBody := func(fileStr string) { 448 // Read text file 449 txtStr, err := ioutil.ReadFile(fileStr) 450 if err != nil { 451 pdf.SetError(err) 452 } 453 // Font 454 pdf.SetFont("Times", "", 12) 455 // Output text in a 6 cm width column 456 pdf.MultiCell(60, 5, string(txtStr), "", "", false) 457 pdf.Ln(-1) 458 // Mention 459 pdf.SetFont("", "I", 0) 460 pdf.Cell(0, 5, "(end of excerpt)") 461 // Go back to first column 462 setCol(0) 463 } 464 printChapter := func(num int, titleStr, fileStr string) { 465 // Add chapter 466 pdf.AddPage() 467 chapterTitle(num, titleStr) 468 chapterBody(fileStr) 469 } 470 pdf.SetAcceptPageBreakFunc(func() bool { 471 // Method accepting or not automatic page break 472 if crrntCol < 2 { 473 // Go to next column 474 setCol(crrntCol + 1) 475 // Set ordinate to top 476 pdf.SetY(y0) 477 // Keep on page 478 return false 479 } 480 // Go back to first column 481 setCol(0) 482 // Page break 483 return true 484 }) 485 pdf.SetHeaderFunc(func() { 486 // Arial bold 15 487 pdf.SetFont("Arial", "B", 15) 488 // Calculate width of title and position 489 wd := pdf.GetStringWidth(titleStr) + 6 490 pdf.SetX((210 - wd) / 2) 491 // Colors of frame, background and text 492 pdf.SetDrawColor(0, 80, 180) 493 pdf.SetFillColor(230, 230, 0) 494 pdf.SetTextColor(220, 50, 50) 495 // Thickness of frame (1 mm) 496 pdf.SetLineWidth(1) 497 // Title 498 pdf.CellFormat(wd, 9, titleStr, "1", 1, "C", true, 0, "") 499 // Line break 500 pdf.Ln(10) 501 // Save ordinate 502 y0 = pdf.GetY() 503 }) 504 pdf.SetFooterFunc(func() { 505 // Position at 1.5 cm from bottom 506 pdf.SetY(-15) 507 // Arial italic 8 508 pdf.SetFont("Arial", "I", 8) 509 // Text color in gray 510 pdf.SetTextColor(128, 128, 128) 511 // Page number 512 pdf.CellFormat(0, 10, fmt.Sprintf("Page %d", pdf.PageNo()), 513 "", 0, "C", false, 0, "") 514 }) 515 printChapter(1, "A RUNAWAY REEF", example.TextFile("20k_c1.txt")) 516 printChapter(2, "THE PROS AND CONS", example.TextFile("20k_c2.txt")) 517 fileStr := example.Filename("Fpdf_SetLeftMargin_multicolumn") 518 err := pdf.OutputFileAndClose(fileStr) 519 example.Summary(err, fileStr) 520 // Output: 521 // Successfully generated pdf/Fpdf_SetLeftMargin_multicolumn.pdf 522 } 523 524 // ExampleFpdf_SplitLines_tables demonstrates word-wrapped table cells 525 func ExampleFpdf_SplitLines_tables() { 526 const ( 527 colCount = 3 528 colWd = 60.0 529 marginH = 15.0 530 lineHt = 5.5 531 cellGap = 2.0 532 ) 533 // var colStrList [colCount]string 534 type cellType struct { 535 str string 536 list [][]byte 537 ht float64 538 } 539 var ( 540 cellList [colCount]cellType 541 cell cellType 542 ) 543 544 pdf := gofpdf.New("P", "mm", "A4", "") // 210 x 297 545 header := [colCount]string{"Column A", "Column B", "Column C"} 546 alignList := [colCount]string{"L", "C", "R"} 547 strList := loremList() 548 pdf.SetMargins(marginH, 15, marginH) 549 pdf.SetFont("Arial", "", 14) 550 pdf.AddPage() 551 552 // Headers 553 pdf.SetTextColor(224, 224, 224) 554 pdf.SetFillColor(64, 64, 64) 555 for colJ := 0; colJ < colCount; colJ++ { 556 pdf.CellFormat(colWd, 10, header[colJ], "1", 0, "CM", true, 0, "") 557 } 558 pdf.Ln(-1) 559 pdf.SetTextColor(24, 24, 24) 560 pdf.SetFillColor(255, 255, 255) 561 562 // Rows 563 y := pdf.GetY() 564 count := 0 565 for rowJ := 0; rowJ < 2; rowJ++ { 566 maxHt := lineHt 567 // Cell height calculation loop 568 for colJ := 0; colJ < colCount; colJ++ { 569 count++ 570 if count > len(strList) { 571 count = 1 572 } 573 cell.str = strings.Join(strList[0:count], " ") 574 cell.list = pdf.SplitLines([]byte(cell.str), colWd-cellGap-cellGap) 575 cell.ht = float64(len(cell.list)) * lineHt 576 if cell.ht > maxHt { 577 maxHt = cell.ht 578 } 579 cellList[colJ] = cell 580 } 581 // Cell render loop 582 x := marginH 583 for colJ := 0; colJ < colCount; colJ++ { 584 pdf.Rect(x, y, colWd, maxHt+cellGap+cellGap, "D") 585 cell = cellList[colJ] 586 cellY := y + cellGap + (maxHt-cell.ht)/2 587 for splitJ := 0; splitJ < len(cell.list); splitJ++ { 588 pdf.SetXY(x+cellGap, cellY) 589 pdf.CellFormat(colWd-cellGap-cellGap, lineHt, string(cell.list[splitJ]), "", 0, 590 alignList[colJ], false, 0, "") 591 cellY += lineHt 592 } 593 x += colWd 594 } 595 y += maxHt + cellGap + cellGap 596 } 597 598 fileStr := example.Filename("Fpdf_SplitLines_tables") 599 err := pdf.OutputFileAndClose(fileStr) 600 example.Summary(err, fileStr) 601 // Output: 602 // Successfully generated pdf/Fpdf_SplitLines_tables.pdf 603 } 604 605 // ExampleFpdf_CellFormat_tables demonstrates various table styles. 606 func ExampleFpdf_CellFormat_tables() { 607 pdf := gofpdf.New("P", "mm", "A4", "") 608 type countryType struct { 609 nameStr, capitalStr, areaStr, popStr string 610 } 611 countryList := make([]countryType, 0, 8) 612 header := []string{"Country", "Capital", "Area (sq km)", "Pop. (thousands)"} 613 loadData := func(fileStr string) { 614 fl, err := os.Open(fileStr) 615 if err == nil { 616 scanner := bufio.NewScanner(fl) 617 var c countryType 618 for scanner.Scan() { 619 // Austria;Vienna;83859;8075 620 lineStr := scanner.Text() 621 list := strings.Split(lineStr, ";") 622 if len(list) == 4 { 623 c.nameStr = list[0] 624 c.capitalStr = list[1] 625 c.areaStr = list[2] 626 c.popStr = list[3] 627 countryList = append(countryList, c) 628 } else { 629 err = fmt.Errorf("error tokenizing %s", lineStr) 630 } 631 } 632 fl.Close() 633 if len(countryList) == 0 { 634 err = fmt.Errorf("error loading data from %s", fileStr) 635 } 636 } 637 if err != nil { 638 pdf.SetError(err) 639 } 640 } 641 // Simple table 642 basicTable := func() { 643 left := (210.0 - 4*40) / 2 644 pdf.SetX(left) 645 for _, str := range header { 646 pdf.CellFormat(40, 7, str, "1", 0, "", false, 0, "") 647 } 648 pdf.Ln(-1) 649 for _, c := range countryList { 650 pdf.SetX(left) 651 pdf.CellFormat(40, 6, c.nameStr, "1", 0, "", false, 0, "") 652 pdf.CellFormat(40, 6, c.capitalStr, "1", 0, "", false, 0, "") 653 pdf.CellFormat(40, 6, c.areaStr, "1", 0, "", false, 0, "") 654 pdf.CellFormat(40, 6, c.popStr, "1", 0, "", false, 0, "") 655 pdf.Ln(-1) 656 } 657 } 658 // Better table 659 improvedTable := func() { 660 // Column widths 661 w := []float64{40.0, 35.0, 40.0, 45.0} 662 wSum := 0.0 663 for _, v := range w { 664 wSum += v 665 } 666 left := (210 - wSum) / 2 667 // Header 668 pdf.SetX(left) 669 for j, str := range header { 670 pdf.CellFormat(w[j], 7, str, "1", 0, "C", false, 0, "") 671 } 672 pdf.Ln(-1) 673 // Data 674 for _, c := range countryList { 675 pdf.SetX(left) 676 pdf.CellFormat(w[0], 6, c.nameStr, "LR", 0, "", false, 0, "") 677 pdf.CellFormat(w[1], 6, c.capitalStr, "LR", 0, "", false, 0, "") 678 pdf.CellFormat(w[2], 6, strDelimit(c.areaStr, ",", 3), 679 "LR", 0, "R", false, 0, "") 680 pdf.CellFormat(w[3], 6, strDelimit(c.popStr, ",", 3), 681 "LR", 0, "R", false, 0, "") 682 pdf.Ln(-1) 683 } 684 pdf.SetX(left) 685 pdf.CellFormat(wSum, 0, "", "T", 0, "", false, 0, "") 686 } 687 // Colored table 688 fancyTable := func() { 689 // Colors, line width and bold font 690 pdf.SetFillColor(255, 0, 0) 691 pdf.SetTextColor(255, 255, 255) 692 pdf.SetDrawColor(128, 0, 0) 693 pdf.SetLineWidth(.3) 694 pdf.SetFont("", "B", 0) 695 // Header 696 w := []float64{40, 35, 40, 45} 697 wSum := 0.0 698 for _, v := range w { 699 wSum += v 700 } 701 left := (210 - wSum) / 2 702 pdf.SetX(left) 703 for j, str := range header { 704 pdf.CellFormat(w[j], 7, str, "1", 0, "C", true, 0, "") 705 } 706 pdf.Ln(-1) 707 // Color and font restoration 708 pdf.SetFillColor(224, 235, 255) 709 pdf.SetTextColor(0, 0, 0) 710 pdf.SetFont("", "", 0) 711 // Data 712 fill := false 713 for _, c := range countryList { 714 pdf.SetX(left) 715 pdf.CellFormat(w[0], 6, c.nameStr, "LR", 0, "", fill, 0, "") 716 pdf.CellFormat(w[1], 6, c.capitalStr, "LR", 0, "", fill, 0, "") 717 pdf.CellFormat(w[2], 6, strDelimit(c.areaStr, ",", 3), 718 "LR", 0, "R", fill, 0, "") 719 pdf.CellFormat(w[3], 6, strDelimit(c.popStr, ",", 3), 720 "LR", 0, "R", fill, 0, "") 721 pdf.Ln(-1) 722 fill = !fill 723 } 724 pdf.SetX(left) 725 pdf.CellFormat(wSum, 0, "", "T", 0, "", false, 0, "") 726 } 727 loadData(example.TextFile("countries.txt")) 728 pdf.SetFont("Arial", "", 14) 729 pdf.AddPage() 730 basicTable() 731 pdf.AddPage() 732 improvedTable() 733 pdf.AddPage() 734 fancyTable() 735 fileStr := example.Filename("Fpdf_CellFormat_tables") 736 err := pdf.OutputFileAndClose(fileStr) 737 example.Summary(err, fileStr) 738 // Output: 739 // Successfully generated pdf/Fpdf_CellFormat_tables.pdf 740 } 741 742 // ExampleFpdf_HTMLBasicNew demonstrates internal and external links with and without basic 743 // HTML. 744 func ExampleFpdf_HTMLBasicNew() { 745 pdf := gofpdf.New("P", "mm", "A4", "") 746 // First page: manual local link 747 pdf.AddPage() 748 pdf.SetFont("Helvetica", "", 20) 749 _, lineHt := pdf.GetFontSize() 750 pdf.Write(lineHt, "To find out what's new in this tutorial, click ") 751 pdf.SetFont("", "U", 0) 752 link := pdf.AddLink() 753 pdf.WriteLinkID(lineHt, "here", link) 754 pdf.SetFont("", "", 0) 755 // Second page: image link and basic HTML with link 756 pdf.AddPage() 757 pdf.SetLink(link, 0, -1) 758 pdf.Image(example.ImageFile("logo.png"), 10, 12, 30, 0, false, "", 0, "http://www.fpdf.org") 759 pdf.SetLeftMargin(45) 760 pdf.SetFontSize(14) 761 _, lineHt = pdf.GetFontSize() 762 htmlStr := `You can now easily print text mixing different styles: <b>bold</b>, ` + 763 `<i>italic</i>, <u>underlined</u>, or <b><i><u>all at once</u></i></b>!<br><br>` + 764 `<center>You can also center text.</center>` + 765 `<right>Or align it to the right.</right>` + 766 `You can also insert links on text, such as ` + 767 `<a href="http://www.fpdf.org">www.fpdf.org</a>, or on an image: click on the logo.` 768 html := pdf.HTMLBasicNew() 769 html.Write(lineHt, htmlStr) 770 fileStr := example.Filename("Fpdf_HTMLBasicNew") 771 err := pdf.OutputFileAndClose(fileStr) 772 example.Summary(err, fileStr) 773 // Output: 774 // Successfully generated pdf/Fpdf_HTMLBasicNew.pdf 775 } 776 777 // ExampleFpdf_AddFont demonstrates the use of a non-standard font. 778 func ExampleFpdf_AddFont() { 779 pdf := gofpdf.New("P", "mm", "A4", example.FontDir()) 780 pdf.AddFont("Calligrapher", "", "calligra.json") 781 pdf.AddPage() 782 pdf.SetFont("Calligrapher", "", 35) 783 pdf.Cell(0, 10, "Enjoy new fonts with FPDF!") 784 fileStr := example.Filename("Fpdf_AddFont") 785 err := pdf.OutputFileAndClose(fileStr) 786 example.Summary(err, fileStr) 787 // Output: 788 // Successfully generated pdf/Fpdf_AddFont.pdf 789 } 790 791 // ExampleFpdf_WriteAligned demonstrates how to align text with the Write function. 792 func ExampleFpdf_WriteAligned() { 793 pdf := gofpdf.New("P", "mm", "A4", example.FontDir()) 794 pdf.SetLeftMargin(50.0) 795 pdf.SetRightMargin(50.0) 796 pdf.AddPage() 797 pdf.SetFont("Helvetica", "", 12) 798 pdf.WriteAligned(0, 35, "This text is the default alignment, Left", "") 799 pdf.Ln(35) 800 pdf.WriteAligned(0, 35, "This text is aligned Left", "L") 801 pdf.Ln(35) 802 pdf.WriteAligned(0, 35, "This text is aligned Center", "C") 803 pdf.Ln(35) 804 pdf.WriteAligned(0, 35, "This text is aligned Right", "R") 805 pdf.Ln(35) 806 line := "This can by used to write justified text" 807 leftMargin, _, rightMargin, _ := pdf.GetMargins() 808 pageWidth, _ := pdf.GetPageSize() 809 pageWidth -= leftMargin + rightMargin 810 pdf.SetWordSpacing((pageWidth - pdf.GetStringWidth(line)) / float64(strings.Count(line, " "))) 811 pdf.WriteAligned(pageWidth, 35, line, "L") 812 fileStr := example.Filename("Fpdf_WriteAligned") 813 err := pdf.OutputFileAndClose(fileStr) 814 example.Summary(err, fileStr) 815 // Output: 816 // Successfully generated pdf/Fpdf_WriteAligned.pdf 817 } 818 819 // ExampleFpdf_Image demonstrates how images are included in documents. 820 func ExampleFpdf_Image() { 821 pdf := gofpdf.New("P", "mm", "A4", "") 822 pdf.AddPage() 823 pdf.SetFont("Arial", "", 11) 824 pdf.Image(example.ImageFile("logo.png"), 10, 10, 30, 0, false, "", 0, "") 825 pdf.Text(50, 20, "logo.png") 826 pdf.Image(example.ImageFile("logo.gif"), 10, 40, 30, 0, false, "", 0, "") 827 pdf.Text(50, 50, "logo.gif") 828 pdf.Image(example.ImageFile("logo-gray.png"), 10, 70, 30, 0, false, "", 0, "") 829 pdf.Text(50, 80, "logo-gray.png") 830 pdf.Image(example.ImageFile("logo-rgb.png"), 10, 100, 30, 0, false, "", 0, "") 831 pdf.Text(50, 110, "logo-rgb.png") 832 pdf.Image(example.ImageFile("logo.jpg"), 10, 130, 30, 0, false, "", 0, "") 833 pdf.Text(50, 140, "logo.jpg") 834 fileStr := example.Filename("Fpdf_Image") 835 err := pdf.OutputFileAndClose(fileStr) 836 example.Summary(err, fileStr) 837 // Output: 838 // Successfully generated pdf/Fpdf_Image.pdf 839 } 840 841 // ExampleFpdf_ImageOptions demonstrates how the AllowNegativePosition field of the 842 // ImageOption struct can be used to affect horizontal image placement. 843 func ExampleFpdf_ImageOptions() { 844 var opt gofpdf.ImageOptions 845 846 pdf := gofpdf.New("P", "mm", "A4", "") 847 pdf.AddPage() 848 pdf.SetFont("Arial", "", 11) 849 pdf.SetX(60) 850 opt.ImageType = "png" 851 pdf.ImageOptions(example.ImageFile("logo.png"), -10, 10, 30, 0, false, opt, 0, "") 852 opt.AllowNegativePosition = true 853 pdf.ImageOptions(example.ImageFile("logo.png"), -10, 50, 30, 0, false, opt, 0, "") 854 fileStr := example.Filename("Fpdf_ImageOptions") 855 err := pdf.OutputFileAndClose(fileStr) 856 example.Summary(err, fileStr) 857 // Output: 858 // Successfully generated pdf/Fpdf_ImageOptions.pdf 859 } 860 861 // ExampleFpdf_RegisterImageOptionsReader demonstrates how to load an image 862 // from a io.Reader (in this case, a file) and register it with options. 863 func ExampleFpdf_RegisterImageOptionsReader() { 864 var ( 865 opt gofpdf.ImageOptions 866 pdfStr string 867 fl *os.File 868 err error 869 ) 870 871 pdfStr = example.Filename("Fpdf_RegisterImageOptionsReader") 872 pdf := gofpdf.New("P", "mm", "A4", "") 873 pdf.AddPage() 874 pdf.SetFont("Arial", "", 11) 875 fl, err = os.Open(example.ImageFile("logo.png")) 876 if err == nil { 877 opt.ImageType = "png" 878 opt.AllowNegativePosition = true 879 _ = pdf.RegisterImageOptionsReader("logo", opt, fl) 880 fl.Close() 881 for x := -20.0; x <= 40.0; x += 5 { 882 pdf.ImageOptions("logo", x, x+30, 0, 0, false, opt, 0, "") 883 } 884 err = pdf.OutputFileAndClose(pdfStr) 885 } 886 example.Summary(err, pdfStr) 887 // Output: 888 // Successfully generated pdf/Fpdf_RegisterImageOptionsReader.pdf 889 } 890 891 // This example demonstrates Landscape mode with images. 892 func ExampleFpdf_SetAcceptPageBreakFunc() { 893 var y0 float64 894 var crrntCol int 895 loremStr := lorem() 896 pdf := gofpdf.New("L", "mm", "A4", "") 897 const ( 898 pageWd = 297.0 // A4 210.0 x 297.0 899 margin = 10.0 900 gutter = 4 901 colNum = 3 902 colWd = (pageWd - 2*margin - (colNum-1)*gutter) / colNum 903 ) 904 setCol := func(col int) { 905 crrntCol = col 906 x := margin + float64(col)*(colWd+gutter) 907 pdf.SetLeftMargin(x) 908 pdf.SetX(x) 909 } 910 pdf.SetHeaderFunc(func() { 911 titleStr := "gofpdf" 912 pdf.SetFont("Helvetica", "B", 48) 913 wd := pdf.GetStringWidth(titleStr) + 6 914 pdf.SetX((pageWd - wd) / 2) 915 pdf.SetTextColor(128, 128, 160) 916 pdf.Write(12, titleStr[:2]) 917 pdf.SetTextColor(128, 128, 128) 918 pdf.Write(12, titleStr[2:]) 919 pdf.Ln(20) 920 y0 = pdf.GetY() 921 }) 922 pdf.SetAcceptPageBreakFunc(func() bool { 923 if crrntCol < colNum-1 { 924 setCol(crrntCol + 1) 925 pdf.SetY(y0) 926 // Start new column, not new page 927 return false 928 } 929 setCol(0) 930 return true 931 }) 932 pdf.AddPage() 933 pdf.SetFont("Times", "", 12) 934 for j := 0; j < 20; j++ { 935 if j == 1 { 936 pdf.Image(example.ImageFile("fpdf.png"), -1, 0, colWd, 0, true, "", 0, "") 937 } else if j == 5 { 938 pdf.Image(example.ImageFile("golang-gopher.png"), 939 -1, 0, colWd, 0, true, "", 0, "") 940 } 941 pdf.MultiCell(colWd, 5, loremStr, "", "", false) 942 pdf.Ln(-1) 943 } 944 fileStr := example.Filename("Fpdf_SetAcceptPageBreakFunc_landscape") 945 err := pdf.OutputFileAndClose(fileStr) 946 example.Summary(err, fileStr) 947 // Output: 948 // Successfully generated pdf/Fpdf_SetAcceptPageBreakFunc_landscape.pdf 949 } 950 951 // This example tests corner cases as reported by the gocov tool. 952 func ExampleFpdf_SetKeywords() { 953 var err error 954 fileStr := example.Filename("Fpdf_SetKeywords") 955 err = gofpdf.MakeFont(example.FontFile("CalligrapherRegular.pfb"), 956 example.FontFile("cp1252.map"), example.FontDir(), nil, true) 957 if err == nil { 958 pdf := gofpdf.New("", "", "", "") 959 pdf.SetFontLocation(example.FontDir()) 960 pdf.SetTitle("世界", true) 961 pdf.SetAuthor("世界", true) 962 pdf.SetSubject("世界", true) 963 pdf.SetCreator("世界", true) 964 pdf.SetKeywords("世界", true) 965 pdf.AddFont("Calligrapher", "", "CalligrapherRegular.json") 966 pdf.AddPage() 967 pdf.SetFont("Calligrapher", "", 16) 968 pdf.Writef(5, "\x95 %s \x95", pdf) 969 err = pdf.OutputFileAndClose(fileStr) 970 } 971 example.Summary(err, fileStr) 972 // Output: 973 // Successfully generated pdf/Fpdf_SetKeywords.pdf 974 } 975 976 // ExampleFpdf_Circle demonstrates the construction of various geometric figures, 977 func ExampleFpdf_Circle() { 978 const ( 979 thin = 0.2 980 thick = 3.0 981 ) 982 pdf := gofpdf.New("", "", "", "") 983 pdf.SetFont("Helvetica", "", 12) 984 pdf.SetFillColor(200, 200, 220) 985 pdf.AddPage() 986 987 y := 15.0 988 pdf.Text(10, y, "Circles") 989 pdf.SetFillColor(200, 200, 220) 990 pdf.SetLineWidth(thin) 991 pdf.Circle(20, y+15, 10, "D") 992 pdf.Circle(45, y+15, 10, "F") 993 pdf.Circle(70, y+15, 10, "FD") 994 pdf.SetLineWidth(thick) 995 pdf.Circle(95, y+15, 10, "FD") 996 pdf.SetLineWidth(thin) 997 998 y += 40.0 999 pdf.Text(10, y, "Ellipses") 1000 pdf.SetFillColor(220, 200, 200) 1001 pdf.Ellipse(30, y+15, 20, 10, 0, "D") 1002 pdf.Ellipse(75, y+15, 20, 10, 0, "F") 1003 pdf.Ellipse(120, y+15, 20, 10, 0, "FD") 1004 pdf.SetLineWidth(thick) 1005 pdf.Ellipse(165, y+15, 20, 10, 0, "FD") 1006 pdf.SetLineWidth(thin) 1007 1008 y += 40.0 1009 pdf.Text(10, y, "Curves (quadratic)") 1010 pdf.SetFillColor(220, 220, 200) 1011 pdf.Curve(10, y+30, 15, y-20, 40, y+30, "D") 1012 pdf.Curve(45, y+30, 50, y-20, 75, y+30, "F") 1013 pdf.Curve(80, y+30, 85, y-20, 110, y+30, "FD") 1014 pdf.SetLineWidth(thick) 1015 pdf.Curve(115, y+30, 120, y-20, 145, y+30, "FD") 1016 pdf.SetLineCapStyle("round") 1017 pdf.Curve(150, y+30, 155, y-20, 180, y+30, "FD") 1018 pdf.SetLineWidth(thin) 1019 pdf.SetLineCapStyle("butt") 1020 1021 y += 40.0 1022 pdf.Text(10, y, "Curves (cubic)") 1023 pdf.SetFillColor(220, 200, 220) 1024 pdf.CurveBezierCubic(10, y+30, 15, y-20, 10, y+30, 40, y+30, "D") 1025 pdf.CurveBezierCubic(45, y+30, 50, y-20, 45, y+30, 75, y+30, "F") 1026 pdf.CurveBezierCubic(80, y+30, 85, y-20, 80, y+30, 110, y+30, "FD") 1027 pdf.SetLineWidth(thick) 1028 pdf.CurveBezierCubic(115, y+30, 120, y-20, 115, y+30, 145, y+30, "FD") 1029 pdf.SetLineCapStyle("round") 1030 pdf.CurveBezierCubic(150, y+30, 155, y-20, 150, y+30, 180, y+30, "FD") 1031 pdf.SetLineWidth(thin) 1032 pdf.SetLineCapStyle("butt") 1033 1034 y += 40.0 1035 pdf.Text(10, y, "Arcs") 1036 pdf.SetFillColor(200, 220, 220) 1037 pdf.SetLineWidth(thick) 1038 pdf.Arc(45, y+35, 20, 10, 0, 0, 180, "FD") 1039 pdf.SetLineWidth(thin) 1040 pdf.Arc(45, y+35, 25, 15, 0, 90, 270, "D") 1041 pdf.SetLineWidth(thick) 1042 pdf.Arc(45, y+35, 30, 20, 0, 0, 360, "D") 1043 pdf.SetLineCapStyle("round") 1044 pdf.Arc(135, y+35, 20, 10, 135, 0, 180, "FD") 1045 pdf.SetLineWidth(thin) 1046 pdf.Arc(135, y+35, 25, 15, 135, 90, 270, "D") 1047 pdf.SetLineWidth(thick) 1048 pdf.Arc(135, y+35, 30, 20, 135, 0, 360, "D") 1049 pdf.SetLineWidth(thin) 1050 pdf.SetLineCapStyle("butt") 1051 1052 fileStr := example.Filename("Fpdf_Circle_figures") 1053 err := pdf.OutputFileAndClose(fileStr) 1054 example.Summary(err, fileStr) 1055 // Output: 1056 // Successfully generated pdf/Fpdf_Circle_figures.pdf 1057 } 1058 1059 // ExampleFpdf_SetAlpha demonstrates alpha transparency. 1060 func ExampleFpdf_SetAlpha() { 1061 const ( 1062 gapX = 10.0 1063 gapY = 9.0 1064 rectW = 40.0 1065 rectH = 58.0 1066 pageW = 210 1067 pageH = 297 1068 ) 1069 modeList := []string{"Normal", "Multiply", "Screen", "Overlay", 1070 "Darken", "Lighten", "ColorDodge", "ColorBurn", "HardLight", "SoftLight", 1071 "Difference", "Exclusion", "Hue", "Saturation", "Color", "Luminosity"} 1072 pdf := gofpdf.New("", "", "", "") 1073 pdf.SetLineWidth(2) 1074 pdf.SetAutoPageBreak(false, 0) 1075 pdf.AddPage() 1076 pdf.SetFont("Helvetica", "", 18) 1077 pdf.SetXY(0, gapY) 1078 pdf.SetTextColor(0, 0, 0) 1079 pdf.CellFormat(pageW, gapY, "Alpha Blending Modes", "", 0, "C", false, 0, "") 1080 j := 0 1081 y := 3 * gapY 1082 for col := 0; col < 4; col++ { 1083 x := gapX 1084 for row := 0; row < 4; row++ { 1085 pdf.Rect(x, y, rectW, rectH, "D") 1086 pdf.SetFont("Helvetica", "B", 12) 1087 pdf.SetFillColor(0, 0, 0) 1088 pdf.SetTextColor(250, 250, 230) 1089 pdf.SetXY(x, y+rectH-4) 1090 pdf.CellFormat(rectW, 5, modeList[j], "", 0, "C", true, 0, "") 1091 pdf.SetFont("Helvetica", "I", 150) 1092 pdf.SetTextColor(80, 80, 120) 1093 pdf.SetXY(x, y+2) 1094 pdf.CellFormat(rectW, rectH, "A", "", 0, "C", false, 0, "") 1095 pdf.SetAlpha(0.5, modeList[j]) 1096 pdf.Image(example.ImageFile("golang-gopher.png"), 1097 x-gapX, y, rectW+2*gapX, 0, false, "", 0, "") 1098 pdf.SetAlpha(1.0, "Normal") 1099 x += rectW + gapX 1100 j++ 1101 } 1102 y += rectH + gapY 1103 } 1104 fileStr := example.Filename("Fpdf_SetAlpha_transparency") 1105 err := pdf.OutputFileAndClose(fileStr) 1106 example.Summary(err, fileStr) 1107 // Output: 1108 // Successfully generated pdf/Fpdf_SetAlpha_transparency.pdf 1109 } 1110 1111 // ExampleFpdf_LinearGradient deomstrates various gradients. 1112 func ExampleFpdf_LinearGradient() { 1113 pdf := gofpdf.New("", "", "", "") 1114 pdf.SetFont("Helvetica", "", 12) 1115 pdf.AddPage() 1116 pdf.LinearGradient(0, 0, 210, 100, 250, 250, 255, 220, 220, 225, 0, 0, 0, .5) 1117 pdf.LinearGradient(20, 25, 75, 75, 220, 220, 250, 80, 80, 220, 0, .2, 0, .8) 1118 pdf.Rect(20, 25, 75, 75, "D") 1119 pdf.LinearGradient(115, 25, 75, 75, 220, 220, 250, 80, 80, 220, 0, 0, 1, 1) 1120 pdf.Rect(115, 25, 75, 75, "D") 1121 pdf.RadialGradient(20, 120, 75, 75, 220, 220, 250, 80, 80, 220, 1122 0.25, 0.75, 0.25, 0.75, 1) 1123 pdf.Rect(20, 120, 75, 75, "D") 1124 pdf.RadialGradient(115, 120, 75, 75, 220, 220, 250, 80, 80, 220, 1125 0.25, 0.75, 0.75, 0.75, 0.75) 1126 pdf.Rect(115, 120, 75, 75, "D") 1127 fileStr := example.Filename("Fpdf_LinearGradient_gradient") 1128 err := pdf.OutputFileAndClose(fileStr) 1129 example.Summary(err, fileStr) 1130 // Output: 1131 // Successfully generated pdf/Fpdf_LinearGradient_gradient.pdf 1132 } 1133 1134 // ExampleFpdf_ClipText demonstrates clipping. 1135 func ExampleFpdf_ClipText() { 1136 pdf := gofpdf.New("", "", "", "") 1137 y := 10.0 1138 pdf.AddPage() 1139 1140 pdf.SetFont("Helvetica", "", 24) 1141 pdf.SetXY(0, y) 1142 pdf.ClipText(10, y+12, "Clipping examples", false) 1143 pdf.RadialGradient(10, y, 100, 20, 128, 128, 160, 32, 32, 48, 1144 0.25, 0.5, 0.25, 0.5, 0.2) 1145 pdf.ClipEnd() 1146 1147 y += 12 1148 pdf.SetFont("Helvetica", "B", 120) 1149 pdf.SetDrawColor(64, 80, 80) 1150 pdf.SetLineWidth(.5) 1151 pdf.ClipText(10, y+40, pdf.String(), true) 1152 pdf.RadialGradient(10, y, 200, 50, 220, 220, 250, 80, 80, 220, 1153 0.25, 0.5, 0.25, 0.5, 1) 1154 pdf.ClipEnd() 1155 1156 y += 55 1157 pdf.ClipRect(10, y, 105, 20, true) 1158 pdf.SetFillColor(255, 255, 255) 1159 pdf.Rect(10, y, 105, 20, "F") 1160 pdf.ClipCircle(40, y+10, 15, false) 1161 pdf.RadialGradient(25, y, 30, 30, 220, 250, 220, 40, 60, 40, 0.3, 1162 0.85, 0.3, 0.85, 0.5) 1163 pdf.ClipEnd() 1164 pdf.ClipEllipse(80, y+10, 20, 15, false) 1165 pdf.RadialGradient(60, y, 40, 30, 250, 220, 220, 60, 40, 40, 0.3, 1166 0.85, 0.3, 0.85, 0.5) 1167 pdf.ClipEnd() 1168 pdf.ClipEnd() 1169 1170 y += 28 1171 pdf.ClipEllipse(26, y+10, 16, 10, true) 1172 pdf.Image(example.ImageFile("logo.jpg"), 10, y, 32, 0, false, "JPG", 0, "") 1173 pdf.ClipEnd() 1174 1175 pdf.ClipCircle(60, y+10, 10, true) 1176 pdf.RadialGradient(50, y, 20, 20, 220, 220, 250, 40, 40, 60, 0.3, 1177 0.7, 0.3, 0.7, 0.5) 1178 pdf.ClipEnd() 1179 1180 pdf.ClipPolygon([]gofpdf.PointType{{X: 80, Y: y + 20}, {X: 90, Y: y}, 1181 {X: 100, Y: y + 20}}, true) 1182 pdf.LinearGradient(80, y, 20, 20, 250, 220, 250, 60, 40, 60, 0.5, 1183 1, 0.5, 0.5) 1184 pdf.ClipEnd() 1185 1186 y += 30 1187 pdf.SetLineWidth(.1) 1188 pdf.SetDrawColor(180, 180, 180) 1189 pdf.ClipRoundedRect(10, y, 120, 20, 5, true) 1190 pdf.RadialGradient(10, y, 120, 20, 255, 255, 255, 240, 240, 220, 1191 0.25, 0.75, 0.25, 0.75, 0.5) 1192 pdf.SetXY(5, y-5) 1193 pdf.SetFont("Times", "", 12) 1194 pdf.MultiCell(130, 5, lorem(), "", "", false) 1195 pdf.ClipEnd() 1196 1197 y += 30 1198 pdf.SetDrawColor(180, 100, 180) 1199 pdf.ClipRoundedRectExt(10, y, 120, 20, 5, 10, 5, 10, true) 1200 pdf.RadialGradient(10, y, 120, 20, 255, 255, 255, 240, 240, 220, 1201 0.25, 0.75, 0.25, 0.75, 0.5) 1202 pdf.SetXY(5, y-5) 1203 pdf.SetFont("Times", "", 12) 1204 pdf.MultiCell(130, 5, lorem(), "", "", false) 1205 pdf.ClipEnd() 1206 1207 fileStr := example.Filename("Fpdf_ClipText") 1208 err := pdf.OutputFileAndClose(fileStr) 1209 example.Summary(err, fileStr) 1210 // Output: 1211 // Successfully generated pdf/Fpdf_ClipText.pdf 1212 } 1213 1214 // ExampleFpdf_PageSize generates a PDF document with various page sizes. 1215 func ExampleFpdf_PageSize() { 1216 pdf := gofpdf.NewCustom(&gofpdf.InitType{ 1217 UnitStr: "in", 1218 Size: gofpdf.SizeType{Wd: 6, Ht: 6}, 1219 FontDirStr: example.FontDir(), 1220 }) 1221 pdf.SetMargins(0.5, 1, 0.5) 1222 pdf.SetFont("Times", "", 14) 1223 pdf.AddPageFormat("L", gofpdf.SizeType{Wd: 3, Ht: 12}) 1224 pdf.SetXY(0.5, 1.5) 1225 pdf.CellFormat(11, 0.2, "12 in x 3 in", "", 0, "C", false, 0, "") 1226 pdf.AddPage() // Default size established in NewCustom() 1227 pdf.SetXY(0.5, 3) 1228 pdf.CellFormat(5, 0.2, "6 in x 6 in", "", 0, "C", false, 0, "") 1229 pdf.AddPageFormat("P", gofpdf.SizeType{Wd: 3, Ht: 12}) 1230 pdf.SetXY(0.5, 6) 1231 pdf.CellFormat(2, 0.2, "3 in x 12 in", "", 0, "C", false, 0, "") 1232 for j := 0; j <= 3; j++ { 1233 wd, ht, u := pdf.PageSize(j) 1234 fmt.Printf("%d: %6.2f %s, %6.2f %s\n", j, wd, u, ht, u) 1235 } 1236 fileStr := example.Filename("Fpdf_PageSize") 1237 err := pdf.OutputFileAndClose(fileStr) 1238 example.Summary(err, fileStr) 1239 // Output: 1240 // 0: 6.00 in, 6.00 in 1241 // 1: 12.00 in, 3.00 in 1242 // 2: 6.00 in, 6.00 in 1243 // 3: 3.00 in, 12.00 in 1244 // Successfully generated pdf/Fpdf_PageSize.pdf 1245 } 1246 1247 // ExampleFpdf_Bookmark demonstrates the Bookmark method. 1248 func ExampleFpdf_Bookmark() { 1249 pdf := gofpdf.New("P", "mm", "A4", "") 1250 pdf.AddPage() 1251 pdf.SetFont("Arial", "", 15) 1252 pdf.Bookmark("Page 1", 0, 0) 1253 pdf.Bookmark("Paragraph 1", 1, -1) 1254 pdf.Cell(0, 6, "Paragraph 1") 1255 pdf.Ln(50) 1256 pdf.Bookmark("Paragraph 2", 1, -1) 1257 pdf.Cell(0, 6, "Paragraph 2") 1258 pdf.AddPage() 1259 pdf.Bookmark("Page 2", 0, 0) 1260 pdf.Bookmark("Paragraph 3", 1, -1) 1261 pdf.Cell(0, 6, "Paragraph 3") 1262 fileStr := example.Filename("Fpdf_Bookmark") 1263 err := pdf.OutputFileAndClose(fileStr) 1264 example.Summary(err, fileStr) 1265 // Output: 1266 // Successfully generated pdf/Fpdf_Bookmark.pdf 1267 } 1268 1269 // ExampleFpdf_TransformBegin demonstrates various transformations. It is adapted from an 1270 // example script by Moritz Wagner and Andreas Würmser. 1271 func ExampleFpdf_TransformBegin() { 1272 const ( 1273 light = 200 1274 dark = 0 1275 ) 1276 var refX, refY float64 1277 var refStr string 1278 pdf := gofpdf.New("P", "mm", "A4", "") 1279 pdf.AddPage() 1280 color := func(val int) { 1281 pdf.SetDrawColor(val, val, val) 1282 pdf.SetTextColor(val, val, val) 1283 } 1284 reference := func(str string, x, y float64, val int) { 1285 color(val) 1286 pdf.Rect(x, y, 40, 10, "D") 1287 pdf.Text(x, y-1, str) 1288 } 1289 refDraw := func(str string, x, y float64) { 1290 refStr = str 1291 refX = x 1292 refY = y 1293 reference(str, x, y, light) 1294 } 1295 refDupe := func() { 1296 reference(refStr, refX, refY, dark) 1297 } 1298 1299 titleStr := "Transformations" 1300 titlePt := 36.0 1301 titleHt := pdf.PointConvert(titlePt) 1302 pdf.SetFont("Helvetica", "", titlePt) 1303 titleWd := pdf.GetStringWidth(titleStr) 1304 titleX := (210 - titleWd) / 2 1305 pdf.Text(titleX, 10+titleHt, titleStr) 1306 pdf.TransformBegin() 1307 pdf.TransformMirrorVertical(10 + titleHt + 0.5) 1308 pdf.ClipText(titleX, 10+titleHt, titleStr, false) 1309 // Remember that the transform will mirror the gradient box too 1310 pdf.LinearGradient(titleX, 10, titleWd, titleHt+4, 120, 120, 120, 1311 255, 255, 255, 0, 0, 0, 0.6) 1312 pdf.ClipEnd() 1313 pdf.TransformEnd() 1314 1315 pdf.SetFont("Helvetica", "", 12) 1316 1317 // Scale by 150% centered by lower left corner of the rectangle 1318 refDraw("Scale", 50, 60) 1319 pdf.TransformBegin() 1320 pdf.TransformScaleXY(150, 50, 70) 1321 refDupe() 1322 pdf.TransformEnd() 1323 1324 // Translate 7 to the right, 5 to the bottom 1325 refDraw("Translate", 125, 60) 1326 pdf.TransformBegin() 1327 pdf.TransformTranslate(7, 5) 1328 refDupe() 1329 pdf.TransformEnd() 1330 1331 // Rotate 20 degrees counter-clockwise centered by the lower left corner of 1332 // the rectangle 1333 refDraw("Rotate", 50, 110) 1334 pdf.TransformBegin() 1335 pdf.TransformRotate(20, 50, 120) 1336 refDupe() 1337 pdf.TransformEnd() 1338 1339 // Skew 30 degrees along the x-axis centered by the lower left corner of the 1340 // rectangle 1341 refDraw("Skew", 125, 110) 1342 pdf.TransformBegin() 1343 pdf.TransformSkewX(30, 125, 110) 1344 refDupe() 1345 pdf.TransformEnd() 1346 1347 // Mirror horizontally with axis of reflection at left side of the rectangle 1348 refDraw("Mirror horizontal", 50, 160) 1349 pdf.TransformBegin() 1350 pdf.TransformMirrorHorizontal(50) 1351 refDupe() 1352 pdf.TransformEnd() 1353 1354 // Mirror vertically with axis of reflection at bottom side of the rectangle 1355 refDraw("Mirror vertical", 125, 160) 1356 pdf.TransformBegin() 1357 pdf.TransformMirrorVertical(170) 1358 refDupe() 1359 pdf.TransformEnd() 1360 1361 // Reflect against a point at the lower left point of rectangle 1362 refDraw("Mirror point", 50, 210) 1363 pdf.TransformBegin() 1364 pdf.TransformMirrorPoint(50, 220) 1365 refDupe() 1366 pdf.TransformEnd() 1367 1368 // Mirror against a straight line described by a point and an angle 1369 angle := -20.0 1370 px := 120.0 1371 py := 220.0 1372 refDraw("Mirror line", 125, 210) 1373 pdf.TransformBegin() 1374 pdf.TransformRotate(angle, px, py) 1375 pdf.Line(px-1, py-1, px+1, py+1) 1376 pdf.Line(px-1, py+1, px+1, py-1) 1377 pdf.Line(px-5, py, px+60, py) 1378 pdf.TransformEnd() 1379 pdf.TransformBegin() 1380 pdf.TransformMirrorLine(angle, px, py) 1381 refDupe() 1382 pdf.TransformEnd() 1383 1384 fileStr := example.Filename("Fpdf_TransformBegin") 1385 err := pdf.OutputFileAndClose(fileStr) 1386 example.Summary(err, fileStr) 1387 // Output: 1388 // Successfully generated pdf/Fpdf_TransformBegin.pdf 1389 } 1390 1391 // ExampleFpdf_RegisterImage demonstrates Lawrence Kesteloot's image registration code. 1392 func ExampleFpdf_RegisterImage() { 1393 const ( 1394 margin = 10 1395 wd = 210 1396 ht = 297 1397 ) 1398 fileList := []string{ 1399 "logo-gray.png", 1400 "logo.jpg", 1401 "logo.png", 1402 "logo-rgb.png", 1403 "logo-progressive.jpg", 1404 } 1405 var infoPtr *gofpdf.ImageInfoType 1406 var imageFileStr string 1407 var imgWd, imgHt, lf, tp float64 1408 pdf := gofpdf.New("P", "mm", "A4", "") 1409 pdf.AddPage() 1410 pdf.SetMargins(10, 10, 10) 1411 pdf.SetFont("Helvetica", "", 15) 1412 for j, str := range fileList { 1413 imageFileStr = example.ImageFile(str) 1414 infoPtr = pdf.RegisterImage(imageFileStr, "") 1415 imgWd, imgHt = infoPtr.Extent() 1416 switch j { 1417 case 0: 1418 lf = margin 1419 tp = margin 1420 case 1: 1421 lf = wd - margin - imgWd 1422 tp = margin 1423 case 2: 1424 lf = (wd - imgWd) / 2.0 1425 tp = (ht - imgHt) / 2.0 1426 case 3: 1427 lf = margin 1428 tp = ht - imgHt - margin 1429 case 4: 1430 lf = wd - imgWd - margin 1431 tp = ht - imgHt - margin 1432 } 1433 pdf.Image(imageFileStr, lf, tp, imgWd, imgHt, false, "", 0, "") 1434 } 1435 fileStr := example.Filename("Fpdf_RegisterImage") 1436 // Test the image information retrieval method 1437 infoShow := func(imageStr string) { 1438 imageStr = example.ImageFile(imageStr) 1439 info := pdf.GetImageInfo(imageStr) 1440 if info != nil { 1441 if info.Width() > 0.0 { 1442 fmt.Printf("Image %s is registered\n", filepath.ToSlash(imageStr)) 1443 } else { 1444 fmt.Printf("Incorrect information for image %s\n", filepath.ToSlash(imageStr)) 1445 } 1446 } else { 1447 fmt.Printf("Image %s is not registered\n", filepath.ToSlash(imageStr)) 1448 } 1449 } 1450 infoShow(fileList[0]) 1451 infoShow("foo.png") 1452 err := pdf.OutputFileAndClose(fileStr) 1453 example.Summary(err, fileStr) 1454 // Output: 1455 // Image image/logo-gray.png is registered 1456 // Image image/foo.png is not registered 1457 // Successfully generated pdf/Fpdf_RegisterImage.pdf 1458 } 1459 1460 // ExampleFpdf_SplitLines demonstrates Bruno Michel's line splitting function. 1461 func ExampleFpdf_SplitLines() { 1462 const ( 1463 fontPtSize = 18.0 1464 wd = 100.0 1465 ) 1466 pdf := gofpdf.New("P", "mm", "A4", "") // A4 210.0 x 297.0 1467 pdf.SetFont("Times", "", fontPtSize) 1468 _, lineHt := pdf.GetFontSize() 1469 pdf.AddPage() 1470 pdf.SetMargins(10, 10, 10) 1471 lines := pdf.SplitLines([]byte(lorem()), wd) 1472 ht := float64(len(lines)) * lineHt 1473 y := (297.0 - ht) / 2.0 1474 pdf.SetDrawColor(128, 128, 128) 1475 pdf.SetFillColor(255, 255, 210) 1476 x := (210.0 - (wd + 40.0)) / 2.0 1477 pdf.Rect(x, y-20.0, wd+40.0, ht+40.0, "FD") 1478 pdf.SetY(y) 1479 for _, line := range lines { 1480 pdf.CellFormat(190.0, lineHt, string(line), "", 1, "C", false, 0, "") 1481 } 1482 fileStr := example.Filename("Fpdf_Splitlines") 1483 err := pdf.OutputFileAndClose(fileStr) 1484 example.Summary(err, fileStr) 1485 // Output: 1486 // Successfully generated pdf/Fpdf_Splitlines.pdf 1487 } 1488 1489 // ExampleFpdf_SVGBasicWrite demonstrates how to render a simple path-only SVG image of the 1490 // type generated by the jSignature web control. 1491 func ExampleFpdf_SVGBasicWrite() { 1492 const ( 1493 fontPtSize = 16.0 1494 wd = 100.0 1495 sigFileStr = "signature.svg" 1496 ) 1497 var ( 1498 sig gofpdf.SVGBasicType 1499 err error 1500 ) 1501 pdf := gofpdf.New("P", "mm", "A4", "") // A4 210.0 x 297.0 1502 pdf.SetFont("Times", "", fontPtSize) 1503 lineHt := pdf.PointConvert(fontPtSize) 1504 pdf.AddPage() 1505 pdf.SetMargins(10, 10, 10) 1506 htmlStr := `This example renders a simple ` + 1507 `<a href="http://www.w3.org/TR/SVG/">SVG</a> (scalable vector graphics) ` + 1508 `image that contains only basic path commands without any styling, ` + 1509 `color fill, reflection or endpoint closures. In particular, the ` + 1510 `type of vector graphic returned from a ` + 1511 `<a href="http://willowsystems.github.io/jSignature/#/demo/">jSignature</a> ` + 1512 `web control is supported and is used in this example.` 1513 html := pdf.HTMLBasicNew() 1514 html.Write(lineHt, htmlStr) 1515 sig, err = gofpdf.SVGBasicFileParse(example.ImageFile(sigFileStr)) 1516 if err == nil { 1517 scale := 100 / sig.Wd 1518 scaleY := 30 / sig.Ht 1519 if scale > scaleY { 1520 scale = scaleY 1521 } 1522 pdf.SetLineCapStyle("round") 1523 pdf.SetLineWidth(0.25) 1524 pdf.SetDrawColor(0, 0, 128) 1525 pdf.SetXY((210.0-scale*sig.Wd)/2.0, pdf.GetY()+10) 1526 pdf.SVGBasicWrite(&sig, scale) 1527 } else { 1528 pdf.SetError(err) 1529 } 1530 fileStr := example.Filename("Fpdf_SVGBasicWrite") 1531 err = pdf.OutputFileAndClose(fileStr) 1532 example.Summary(err, fileStr) 1533 // Output: 1534 // Successfully generated pdf/Fpdf_SVGBasicWrite.pdf 1535 } 1536 1537 // ExampleFpdf_CellFormat_align demonstrates Stefan Schroeder's code to control vertical 1538 // alignment. 1539 func ExampleFpdf_CellFormat_align() { 1540 type recType struct { 1541 align, txt string 1542 } 1543 recList := []recType{ 1544 {"TL", "top left"}, 1545 {"TC", "top center"}, 1546 {"TR", "top right"}, 1547 {"LM", "middle left"}, 1548 {"CM", "middle center"}, 1549 {"RM", "middle right"}, 1550 {"BL", "bottom left"}, 1551 {"BC", "bottom center"}, 1552 {"BR", "bottom right"}, 1553 } 1554 recListBaseline := []recType{ 1555 {"AL", "baseline left"}, 1556 {"AC", "baseline center"}, 1557 {"AR", "baseline right"}, 1558 } 1559 var formatRect = func(pdf *gofpdf.Fpdf, recList []recType) { 1560 linkStr := "" 1561 for pageJ := 0; pageJ < 2; pageJ++ { 1562 pdf.AddPage() 1563 pdf.SetMargins(10, 10, 10) 1564 pdf.SetAutoPageBreak(false, 0) 1565 borderStr := "1" 1566 for _, rec := range recList { 1567 pdf.SetXY(20, 20) 1568 pdf.CellFormat(170, 257, rec.txt, borderStr, 0, rec.align, false, 0, linkStr) 1569 borderStr = "" 1570 } 1571 linkStr = "https://github.com/phpdave11/gofpdf" 1572 } 1573 } 1574 pdf := gofpdf.New("P", "mm", "A4", "") // A4 210.0 x 297.0 1575 pdf.SetFont("Helvetica", "", 16) 1576 formatRect(pdf, recList) 1577 formatRect(pdf, recListBaseline) 1578 var fr fontResourceType 1579 pdf.SetFontLoader(fr) 1580 pdf.AddFont("Calligrapher", "", "calligra.json") 1581 pdf.SetFont("Calligrapher", "", 16) 1582 formatRect(pdf, recListBaseline) 1583 fileStr := example.Filename("Fpdf_CellFormat_align") 1584 err := pdf.OutputFileAndClose(fileStr) 1585 example.Summary(err, fileStr) 1586 // Output: 1587 // Generalized font loader reading calligra.json 1588 // Generalized font loader reading calligra.z 1589 // Successfully generated pdf/Fpdf_CellFormat_align.pdf 1590 } 1591 1592 // ExampleFpdf_CellFormat_codepageescape demonstrates the use of characters in the high range of the 1593 // Windows-1252 code page (gofdpf default). See the example for CellFormat (4) 1594 // for a way to do this automatically. 1595 func ExampleFpdf_CellFormat_codepageescape() { 1596 pdf := gofpdf.New("P", "mm", "A4", "") // A4 210.0 x 297.0 1597 fontSize := 16.0 1598 pdf.SetFont("Helvetica", "", fontSize) 1599 ht := pdf.PointConvert(fontSize) 1600 write := func(str string) { 1601 pdf.CellFormat(190, ht, str, "", 1, "C", false, 0, "") 1602 pdf.Ln(ht) 1603 } 1604 pdf.AddPage() 1605 htmlStr := `Until gofpdf supports UTF-8 encoded source text, source text needs ` + 1606 `to be specified with all special characters escaped to match the code page ` + 1607 `layout of the currently selected font. By default, gofdpf uses code page 1252.` + 1608 ` See <a href="http://en.wikipedia.org/wiki/Windows-1252">Wikipedia</a> for ` + 1609 `a table of this layout.` 1610 html := pdf.HTMLBasicNew() 1611 html.Write(ht, htmlStr) 1612 pdf.Ln(2 * ht) 1613 write("Voix ambigu\xeb d'un c\x9cur qui au z\xe9phyr pr\xe9f\xe8re les jattes de kiwi.") 1614 write("Falsches \xdcben von Xylophonmusik qu\xe4lt jeden gr\xf6\xdferen Zwerg.") 1615 write("Heiz\xf6lr\xfccksto\xdfabd\xe4mpfung") 1616 write("For\xe5rsj\xe6vnd\xf8gn / Efter\xe5rsj\xe6vnd\xf8gn") 1617 fileStr := example.Filename("Fpdf_CellFormat_codepageescape") 1618 err := pdf.OutputFileAndClose(fileStr) 1619 example.Summary(err, fileStr) 1620 // Output: 1621 // Successfully generated pdf/Fpdf_CellFormat_codepageescape.pdf 1622 } 1623 1624 // ExampleFpdf_CellFormat_codepage demonstrates the automatic conversion of UTF-8 strings to an 1625 // 8-bit font encoding. 1626 func ExampleFpdf_CellFormat_codepage() { 1627 pdf := gofpdf.New("P", "mm", "A4", example.FontDir()) // A4 210.0 x 297.0 1628 // See documentation for details on how to generate fonts 1629 pdf.AddFont("Helvetica-1251", "", "helvetica_1251.json") 1630 pdf.AddFont("Helvetica-1253", "", "helvetica_1253.json") 1631 fontSize := 16.0 1632 pdf.SetFont("Helvetica", "", fontSize) 1633 ht := pdf.PointConvert(fontSize) 1634 tr := pdf.UnicodeTranslatorFromDescriptor("") // "" defaults to "cp1252" 1635 write := func(str string) { 1636 // pdf.CellFormat(190, ht, tr(str), "", 1, "C", false, 0, "") 1637 pdf.MultiCell(190, ht, tr(str), "", "C", false) 1638 pdf.Ln(ht) 1639 } 1640 pdf.AddPage() 1641 str := `Gofpdf provides a translator that will convert any UTF-8 code point ` + 1642 `that is present in the specified code page.` 1643 pdf.MultiCell(190, ht, str, "", "L", false) 1644 pdf.Ln(2 * ht) 1645 write("Voix ambiguë d'un cœur qui au zéphyr préfère les jattes de kiwi.") 1646 write("Falsches Üben von Xylophonmusik quält jeden größeren Zwerg.") 1647 write("Heizölrückstoßabdämpfung") 1648 write("Forårsjævndøgn / Efterårsjævndøgn") 1649 write("À noite, vovô Kowalsky vê o ímã cair no pé do pingüim queixoso e vovó" + 1650 "põe açúcar no chá de tâmaras do jabuti feliz.") 1651 pdf.SetFont("Helvetica-1251", "", fontSize) // Name matches one specified in AddFont() 1652 tr = pdf.UnicodeTranslatorFromDescriptor("cp1251") 1653 write("Съешь же ещё этих мягких французских булок, да выпей чаю.") 1654 1655 pdf.SetFont("Helvetica-1253", "", fontSize) 1656 tr = pdf.UnicodeTranslatorFromDescriptor("cp1253") 1657 write("Θέλει αρετή και τόλμη η ελευθερία. (Ανδρέας Κάλβος)") 1658 1659 fileStr := example.Filename("Fpdf_CellFormat_codepage") 1660 err := pdf.OutputFileAndClose(fileStr) 1661 example.Summary(err, fileStr) 1662 // Output: 1663 // Successfully generated pdf/Fpdf_CellFormat_codepage.pdf 1664 } 1665 1666 // ExampleFpdf_SetProtection demonstrates password protection for documents. 1667 func ExampleFpdf_SetProtection() { 1668 pdf := gofpdf.New("P", "mm", "A4", "") 1669 pdf.SetProtection(gofpdf.CnProtectPrint, "123", "abc") 1670 pdf.AddPage() 1671 pdf.SetFont("Arial", "", 12) 1672 pdf.Write(10, "Password-protected.") 1673 fileStr := example.Filename("Fpdf_SetProtection") 1674 err := pdf.OutputFileAndClose(fileStr) 1675 example.Summary(err, fileStr) 1676 // Output: 1677 // Successfully generated pdf/Fpdf_SetProtection.pdf 1678 } 1679 1680 // ExampleFpdf_Polygon displays equilateral polygons in a demonstration of the Polygon 1681 // function. 1682 func ExampleFpdf_Polygon() { 1683 const rowCount = 5 1684 const colCount = 4 1685 const ptSize = 36 1686 var x, y, radius, gap, advance float64 1687 var rgVal int 1688 var pts []gofpdf.PointType 1689 vertices := func(count int) (res []gofpdf.PointType) { 1690 var pt gofpdf.PointType 1691 res = make([]gofpdf.PointType, 0, count) 1692 mlt := 2.0 * math.Pi / float64(count) 1693 for j := 0; j < count; j++ { 1694 pt.Y, pt.X = math.Sincos(float64(j) * mlt) 1695 res = append(res, gofpdf.PointType{ 1696 X: x + radius*pt.X, 1697 Y: y + radius*pt.Y}) 1698 } 1699 return 1700 } 1701 pdf := gofpdf.New("P", "mm", "A4", "") // A4 210.0 x 297.0 1702 pdf.AddPage() 1703 pdf.SetFont("Helvetica", "", ptSize) 1704 pdf.SetDrawColor(0, 80, 180) 1705 gap = 12.0 1706 pdf.SetY(gap) 1707 pdf.CellFormat(190.0, gap, "Equilateral polygons", "", 1, "C", false, 0, "") 1708 radius = (210.0 - float64(colCount+1)*gap) / (2.0 * float64(colCount)) 1709 advance = gap + 2.0*radius 1710 y = 2*gap + pdf.PointConvert(ptSize) + radius 1711 rgVal = 230 1712 for row := 0; row < rowCount; row++ { 1713 pdf.SetFillColor(rgVal, rgVal, 0) 1714 rgVal -= 12 1715 x = gap + radius 1716 for col := 0; col < colCount; col++ { 1717 pts = vertices(row*colCount + col + 3) 1718 pdf.Polygon(pts, "FD") 1719 x += advance 1720 } 1721 y += advance 1722 } 1723 fileStr := example.Filename("Fpdf_Polygon") 1724 err := pdf.OutputFileAndClose(fileStr) 1725 example.Summary(err, fileStr) 1726 // Output: 1727 // Successfully generated pdf/Fpdf_Polygon.pdf 1728 } 1729 1730 // ExampleFpdf_AddLayer demonstrates document layers. The initial visibility of a layer 1731 // is specified with the second parameter to AddLayer(). The layer list 1732 // displayed by the document reader allows layer visibility to be controlled 1733 // interactively. 1734 func ExampleFpdf_AddLayer() { 1735 1736 pdf := gofpdf.New("P", "mm", "A4", "") 1737 pdf.AddPage() 1738 pdf.SetFont("Arial", "", 15) 1739 pdf.Write(8, "This line doesn't belong to any layer.\n") 1740 1741 // Define layers 1742 l1 := pdf.AddLayer("Layer 1", true) 1743 l2 := pdf.AddLayer("Layer 2", true) 1744 1745 // Open layer pane in PDF viewer 1746 pdf.OpenLayerPane() 1747 1748 // First layer 1749 pdf.BeginLayer(l1) 1750 pdf.Write(8, "This line belongs to layer 1.\n") 1751 pdf.EndLayer() 1752 1753 // Second layer 1754 pdf.BeginLayer(l2) 1755 pdf.Write(8, "This line belongs to layer 2.\n") 1756 pdf.EndLayer() 1757 1758 // First layer again 1759 pdf.BeginLayer(l1) 1760 pdf.Write(8, "This line belongs to layer 1 again.\n") 1761 pdf.EndLayer() 1762 1763 fileStr := example.Filename("Fpdf_AddLayer") 1764 err := pdf.OutputFileAndClose(fileStr) 1765 example.Summary(err, fileStr) 1766 // Output: 1767 // Successfully generated pdf/Fpdf_AddLayer.pdf 1768 } 1769 1770 // ExampleFpdf_RegisterImageReader demonstrates the use of an image that is retrieved from a web 1771 // server. 1772 func ExampleFpdf_RegisterImageReader() { 1773 1774 const ( 1775 margin = 10 1776 wd = 210 1777 ht = 297 1778 fontSize = 15 1779 urlStr = "https://github.com/phpdave11/gofpdf/blob/master/image/gofpdf.png?raw=true" 1780 msgStr = `Images from the web can be easily embedded when a PDF document is generated.` 1781 ) 1782 1783 var ( 1784 rsp *http.Response 1785 err error 1786 tp string 1787 ) 1788 1789 pdf := gofpdf.New("P", "mm", "A4", "") 1790 pdf.AddPage() 1791 pdf.SetFont("Helvetica", "", fontSize) 1792 ln := pdf.PointConvert(fontSize) 1793 pdf.MultiCell(wd-margin-margin, ln, msgStr, "", "L", false) 1794 rsp, err = http.Get(urlStr) 1795 if err == nil { 1796 tp = pdf.ImageTypeFromMime(rsp.Header["Content-Type"][0]) 1797 infoPtr := pdf.RegisterImageReader(urlStr, tp, rsp.Body) 1798 if pdf.Ok() { 1799 imgWd, imgHt := infoPtr.Extent() 1800 pdf.Image(urlStr, (wd-imgWd)/2.0, pdf.GetY()+ln, 1801 imgWd, imgHt, false, tp, 0, "") 1802 } 1803 } else { 1804 pdf.SetError(err) 1805 } 1806 fileStr := example.Filename("Fpdf_RegisterImageReader_url") 1807 err = pdf.OutputFileAndClose(fileStr) 1808 example.Summary(err, fileStr) 1809 // Output: 1810 // Successfully generated pdf/Fpdf_RegisterImageReader_url.pdf 1811 1812 } 1813 1814 // ExampleFpdf_Beziergon demonstrates the Beziergon function. 1815 func ExampleFpdf_Beziergon() { 1816 1817 const ( 1818 margin = 10 1819 wd = 210 1820 unit = (wd - 2*margin) / 6 1821 ht = 297 1822 fontSize = 15 1823 msgStr = `Demonstration of Beziergon function` 1824 coefficient = 0.6 1825 delta = coefficient * unit 1826 ln = fontSize * 25.4 / 72 1827 offsetX = (wd - 4*unit) / 2.0 1828 offsetY = offsetX + 2*ln 1829 ) 1830 1831 srcList := []gofpdf.PointType{ 1832 {X: 0, Y: 0}, 1833 {X: 1, Y: 0}, 1834 {X: 1, Y: 1}, 1835 {X: 2, Y: 1}, 1836 {X: 2, Y: 2}, 1837 {X: 3, Y: 2}, 1838 {X: 3, Y: 3}, 1839 {X: 4, Y: 3}, 1840 {X: 4, Y: 4}, 1841 {X: 1, Y: 4}, 1842 {X: 1, Y: 3}, 1843 {X: 0, Y: 3}, 1844 } 1845 1846 ctrlList := []gofpdf.PointType{ 1847 {X: 1, Y: -1}, 1848 {X: 1, Y: 1}, 1849 {X: 1, Y: 1}, 1850 {X: 1, Y: 1}, 1851 {X: 1, Y: 1}, 1852 {X: 1, Y: 1}, 1853 {X: 1, Y: 1}, 1854 {X: 1, Y: 1}, 1855 {X: -1, Y: 1}, 1856 {X: -1, Y: -1}, 1857 {X: -1, Y: -1}, 1858 {X: -1, Y: -1}, 1859 } 1860 1861 pdf := gofpdf.New("P", "mm", "A4", "") 1862 pdf.AddPage() 1863 pdf.SetFont("Helvetica", "", fontSize) 1864 for j, src := range srcList { 1865 srcList[j].X = offsetX + src.X*unit 1866 srcList[j].Y = offsetY + src.Y*unit 1867 } 1868 for j, ctrl := range ctrlList { 1869 ctrlList[j].X = ctrl.X * delta 1870 ctrlList[j].Y = ctrl.Y * delta 1871 } 1872 jPrev := len(srcList) - 1 1873 srcPrev := srcList[jPrev] 1874 curveList := []gofpdf.PointType{srcPrev} // point [, control 0, control 1, point]* 1875 control := func(x, y float64) { 1876 curveList = append(curveList, gofpdf.PointType{X: x, Y: y}) 1877 } 1878 for j, src := range srcList { 1879 ctrl := ctrlList[jPrev] 1880 control(srcPrev.X+ctrl.X, srcPrev.Y+ctrl.Y) // Control 0 1881 ctrl = ctrlList[j] 1882 control(src.X-ctrl.X, src.Y-ctrl.Y) // Control 1 1883 curveList = append(curveList, src) // Destination 1884 jPrev = j 1885 srcPrev = src 1886 } 1887 pdf.MultiCell(wd-margin-margin, ln, msgStr, "", "C", false) 1888 pdf.SetDashPattern([]float64{0.8, 0.8}, 0) 1889 pdf.SetDrawColor(160, 160, 160) 1890 pdf.Polygon(srcList, "D") 1891 pdf.SetDashPattern([]float64{}, 0) 1892 pdf.SetDrawColor(64, 64, 128) 1893 pdf.SetLineWidth(pdf.GetLineWidth() * 3) 1894 pdf.Beziergon(curveList, "D") 1895 fileStr := example.Filename("Fpdf_Beziergon") 1896 err := pdf.OutputFileAndClose(fileStr) 1897 example.Summary(err, fileStr) 1898 // Output: 1899 // Successfully generated pdf/Fpdf_Beziergon.pdf 1900 1901 } 1902 1903 // ExampleFpdf_SetFontLoader demonstrates loading a non-standard font using a generalized 1904 // font loader. fontResourceType implements the FontLoader interface and is 1905 // defined locally in the test source code. 1906 func ExampleFpdf_SetFontLoader() { 1907 var fr fontResourceType 1908 pdf := gofpdf.New("P", "mm", "A4", "") 1909 pdf.SetFontLoader(fr) 1910 pdf.AddFont("Calligrapher", "", "calligra.json") 1911 pdf.AddPage() 1912 pdf.SetFont("Calligrapher", "", 35) 1913 pdf.Cell(0, 10, "Load fonts from any source") 1914 fileStr := example.Filename("Fpdf_SetFontLoader") 1915 err := pdf.OutputFileAndClose(fileStr) 1916 example.Summary(err, fileStr) 1917 // Output: 1918 // Generalized font loader reading calligra.json 1919 // Generalized font loader reading calligra.z 1920 // Successfully generated pdf/Fpdf_SetFontLoader.pdf 1921 } 1922 1923 // ExampleFpdf_MoveTo demonstrates the Path Drawing functions, such as: MoveTo, 1924 // LineTo, CurveTo, ..., ClosePath and DrawPath. 1925 func ExampleFpdf_MoveTo() { 1926 pdf := gofpdf.New("P", "mm", "A4", "") 1927 pdf.AddPage() 1928 pdf.MoveTo(20, 20) 1929 pdf.LineTo(170, 20) 1930 pdf.ArcTo(170, 40, 20, 20, 0, 90, 0) 1931 pdf.CurveTo(190, 100, 105, 100) 1932 pdf.CurveBezierCubicTo(20, 100, 105, 200, 20, 200) 1933 pdf.ClosePath() 1934 pdf.SetFillColor(200, 200, 200) 1935 pdf.SetLineWidth(3) 1936 pdf.DrawPath("DF") 1937 fileStr := example.Filename("Fpdf_MoveTo_path") 1938 err := pdf.OutputFileAndClose(fileStr) 1939 example.Summary(err, fileStr) 1940 // Output: 1941 // Successfully generated pdf/Fpdf_MoveTo_path.pdf 1942 } 1943 1944 // ExampleFpdf_SetLineJoinStyle demonstrates various line cap and line join styles. 1945 func ExampleFpdf_SetLineJoinStyle() { 1946 const offset = 75.0 1947 pdf := gofpdf.New("L", "mm", "A4", "") 1948 pdf.AddPage() 1949 var draw = func(cap, join string, x0, y0, x1, y1 float64) { 1950 // transform begin & end needed to isolate caps and joins 1951 pdf.SetLineCapStyle(cap) 1952 pdf.SetLineJoinStyle(join) 1953 1954 // Draw thick line 1955 pdf.SetDrawColor(0x33, 0x33, 0x33) 1956 pdf.SetLineWidth(30.0) 1957 pdf.MoveTo(x0, y0) 1958 pdf.LineTo((x0+x1)/2+offset, (y0+y1)/2) 1959 pdf.LineTo(x1, y1) 1960 pdf.DrawPath("D") 1961 1962 // Draw thin helping line 1963 pdf.SetDrawColor(0xFF, 0x33, 0x33) 1964 pdf.SetLineWidth(2.56) 1965 pdf.MoveTo(x0, y0) 1966 pdf.LineTo((x0+x1)/2+offset, (y0+y1)/2) 1967 pdf.LineTo(x1, y1) 1968 pdf.DrawPath("D") 1969 1970 } 1971 x := 35.0 1972 caps := []string{"butt", "square", "round"} 1973 joins := []string{"bevel", "miter", "round"} 1974 for i := range caps { 1975 draw(caps[i], joins[i], x, 50, x, 160) 1976 x += offset 1977 } 1978 fileStr := example.Filename("Fpdf_SetLineJoinStyle_caps") 1979 err := pdf.OutputFileAndClose(fileStr) 1980 example.Summary(err, fileStr) 1981 // Output: 1982 // Successfully generated pdf/Fpdf_SetLineJoinStyle_caps.pdf 1983 } 1984 1985 // ExampleFpdf_DrawPath demonstrates various fill modes. 1986 func ExampleFpdf_DrawPath() { 1987 pdf := gofpdf.New("P", "mm", "A4", "") 1988 pdf.SetDrawColor(0xff, 0x00, 0x00) 1989 pdf.SetFillColor(0x99, 0x99, 0x99) 1990 pdf.SetFont("Helvetica", "", 15) 1991 pdf.AddPage() 1992 pdf.SetAlpha(1, "Multiply") 1993 var ( 1994 polygon = func(cx, cy, r, n, dir float64) { 1995 da := 2 * math.Pi / n 1996 pdf.MoveTo(cx+r, cy) 1997 pdf.Text(cx+r, cy, "0") 1998 i := 1 1999 for a := da; a < 2*math.Pi; a += da { 2000 x, y := cx+r*math.Cos(dir*a), cy+r*math.Sin(dir*a) 2001 pdf.LineTo(x, y) 2002 pdf.Text(x, y, strconv.Itoa(i)) 2003 i++ 2004 } 2005 pdf.ClosePath() 2006 } 2007 polygons = func(cx, cy, r, n, dir float64) { 2008 d := 1.0 2009 for rf := r; rf > 0; rf -= 10 { 2010 polygon(cx, cy, rf, n, d) 2011 d *= dir 2012 } 2013 } 2014 star = func(cx, cy, r, n float64) { 2015 da := 4 * math.Pi / n 2016 pdf.MoveTo(cx+r, cy) 2017 for a := da; a < 4*math.Pi+da; a += da { 2018 x, y := cx+r*math.Cos(a), cy+r*math.Sin(a) 2019 pdf.LineTo(x, y) 2020 } 2021 pdf.ClosePath() 2022 } 2023 ) 2024 // triangle 2025 polygons(55, 45, 40, 3, 1) 2026 pdf.DrawPath("B") 2027 pdf.Text(15, 95, "B (same direction, non zero winding)") 2028 2029 // square 2030 polygons(155, 45, 40, 4, 1) 2031 pdf.DrawPath("B*") 2032 pdf.Text(115, 95, "B* (same direction, even odd)") 2033 2034 // pentagon 2035 polygons(55, 145, 40, 5, -1) 2036 pdf.DrawPath("B") 2037 pdf.Text(15, 195, "B (different direction, non zero winding)") 2038 2039 // hexagon 2040 polygons(155, 145, 40, 6, -1) 2041 pdf.DrawPath("B*") 2042 pdf.Text(115, 195, "B* (different direction, even odd)") 2043 2044 // star 2045 star(55, 245, 40, 5) 2046 pdf.DrawPath("B") 2047 pdf.Text(15, 290, "B (non zero winding)") 2048 2049 // star 2050 star(155, 245, 40, 5) 2051 pdf.DrawPath("B*") 2052 pdf.Text(115, 290, "B* (even odd)") 2053 2054 fileStr := example.Filename("Fpdf_DrawPath_fill") 2055 err := pdf.OutputFileAndClose(fileStr) 2056 example.Summary(err, fileStr) 2057 // Output: 2058 // Successfully generated pdf/Fpdf_DrawPath_fill.pdf 2059 } 2060 2061 // ExampleFpdf_CreateTemplate demonstrates creating and using templates 2062 func ExampleFpdf_CreateTemplate() { 2063 pdf := gofpdf.New("P", "mm", "A4", "") 2064 pdf.SetCompression(false) 2065 // pdf.SetFont("Times", "", 12) 2066 template := pdf.CreateTemplate(func(tpl *gofpdf.Tpl) { 2067 tpl.Image(example.ImageFile("logo.png"), 6, 6, 30, 0, false, "", 0, "") 2068 tpl.SetFont("Arial", "B", 16) 2069 tpl.Text(40, 20, "Template says hello") 2070 tpl.SetDrawColor(0, 100, 200) 2071 tpl.SetLineWidth(2.5) 2072 tpl.Line(95, 12, 105, 22) 2073 }) 2074 _, tplSize := template.Size() 2075 // fmt.Println("Size:", tplSize) 2076 // fmt.Println("Scaled:", tplSize.ScaleBy(1.5)) 2077 2078 template2 := pdf.CreateTemplate(func(tpl *gofpdf.Tpl) { 2079 tpl.UseTemplate(template) 2080 subtemplate := tpl.CreateTemplate(func(tpl2 *gofpdf.Tpl) { 2081 tpl2.Image(example.ImageFile("logo.png"), 6, 86, 30, 0, false, "", 0, "") 2082 tpl2.SetFont("Arial", "B", 16) 2083 tpl2.Text(40, 100, "Subtemplate says hello") 2084 tpl2.SetDrawColor(0, 200, 100) 2085 tpl2.SetLineWidth(2.5) 2086 tpl2.Line(102, 92, 112, 102) 2087 }) 2088 tpl.UseTemplate(subtemplate) 2089 }) 2090 2091 pdf.SetDrawColor(200, 100, 0) 2092 pdf.SetLineWidth(2.5) 2093 pdf.SetFont("Arial", "B", 16) 2094 2095 // serialize and deserialize template 2096 b, _ := template2.Serialize() 2097 template3, _ := gofpdf.DeserializeTemplate(b) 2098 2099 pdf.AddPage() 2100 pdf.UseTemplate(template3) 2101 pdf.UseTemplateScaled(template3, gofpdf.PointType{X: 0, Y: 30}, tplSize) 2102 pdf.Line(40, 210, 60, 210) 2103 pdf.Text(40, 200, "Template example page 1") 2104 2105 pdf.AddPage() 2106 pdf.UseTemplate(template2) 2107 pdf.UseTemplateScaled(template3, gofpdf.PointType{X: 0, Y: 30}, tplSize.ScaleBy(1.4)) 2108 pdf.Line(60, 210, 80, 210) 2109 pdf.Text(40, 200, "Template example page 2") 2110 2111 fileStr := example.Filename("Fpdf_CreateTemplate") 2112 err := pdf.OutputFileAndClose(fileStr) 2113 example.Summary(err, fileStr) 2114 // Output: 2115 // Successfully generated pdf/Fpdf_CreateTemplate.pdf 2116 } 2117 2118 // ExampleFpdf_AddFontFromBytes demonstrate how to use embedded fonts from byte array 2119 func ExampleFpdf_AddFontFromBytes() { 2120 pdf := gofpdf.New("P", "mm", "A4", "") 2121 pdf.AddPage() 2122 pdf.AddFontFromBytes("calligra", "", files.CalligraJson, files.CalligraZ) 2123 pdf.SetFont("calligra", "", 16) 2124 pdf.Cell(40, 10, "Hello World With Embedded Font!") 2125 fileStr := example.Filename("Fpdf_EmbeddedFont") 2126 err := pdf.OutputFileAndClose(fileStr) 2127 example.Summary(err, fileStr) 2128 // Output: 2129 // Successfully generated pdf/Fpdf_EmbeddedFont.pdf 2130 } 2131 2132 // This example demonstrate Clipped table cells 2133 func ExampleFpdf_ClipRect() { 2134 marginCell := 2. // margin of top/bottom of cell 2135 pdf := gofpdf.New("P", "mm", "A4", "") 2136 pdf.SetFont("Arial", "", 12) 2137 pdf.AddPage() 2138 pagew, pageh := pdf.GetPageSize() 2139 mleft, mright, _, mbottom := pdf.GetMargins() 2140 2141 cols := []float64{60, 100, pagew - mleft - mright - 100 - 60} 2142 rows := [][]string{} 2143 for i := 1; i <= 50; i++ { 2144 word := fmt.Sprintf("%d:%s", i, strings.Repeat("A", i%100)) 2145 rows = append(rows, []string{word, word, word}) 2146 } 2147 2148 for _, row := range rows { 2149 _, lineHt := pdf.GetFontSize() 2150 height := lineHt + marginCell 2151 2152 x, y := pdf.GetXY() 2153 // add a new page if the height of the row doesn't fit on the page 2154 if y+height >= pageh-mbottom { 2155 pdf.AddPage() 2156 x, y = pdf.GetXY() 2157 } 2158 for i, txt := range row { 2159 width := cols[i] 2160 pdf.Rect(x, y, width, height, "") 2161 pdf.ClipRect(x, y, width, height, false) 2162 pdf.Cell(width, height, txt) 2163 pdf.ClipEnd() 2164 x += width 2165 } 2166 pdf.Ln(-1) 2167 } 2168 fileStr := example.Filename("Fpdf_ClippedTableCells") 2169 err := pdf.OutputFileAndClose(fileStr) 2170 example.Summary(err, fileStr) 2171 // Output: 2172 // Successfully generated pdf/Fpdf_ClippedTableCells.pdf 2173 } 2174 2175 // This example demonstrate wrapped table cells 2176 func ExampleFpdf_Rect() { 2177 marginCell := 2. // margin of top/bottom of cell 2178 pdf := gofpdf.New("P", "mm", "A4", "") 2179 pdf.SetFont("Arial", "", 12) 2180 pdf.AddPage() 2181 pagew, pageh := pdf.GetPageSize() 2182 mleft, mright, _, mbottom := pdf.GetMargins() 2183 2184 cols := []float64{60, 100, pagew - mleft - mright - 100 - 60} 2185 rows := [][]string{} 2186 for i := 1; i <= 30; i++ { 2187 word := fmt.Sprintf("%d:%s", i, strings.Repeat("A", i%100)) 2188 rows = append(rows, []string{word, word, word}) 2189 } 2190 2191 for _, row := range rows { 2192 curx, y := pdf.GetXY() 2193 x := curx 2194 2195 height := 0. 2196 _, lineHt := pdf.GetFontSize() 2197 2198 for i, txt := range row { 2199 lines := pdf.SplitLines([]byte(txt), cols[i]) 2200 h := float64(len(lines))*lineHt + marginCell*float64(len(lines)) 2201 if h > height { 2202 height = h 2203 } 2204 } 2205 // add a new page if the height of the row doesn't fit on the page 2206 if pdf.GetY()+height > pageh-mbottom { 2207 pdf.AddPage() 2208 y = pdf.GetY() 2209 } 2210 for i, txt := range row { 2211 width := cols[i] 2212 pdf.Rect(x, y, width, height, "") 2213 pdf.MultiCell(width, lineHt+marginCell, txt, "", "", false) 2214 x += width 2215 pdf.SetXY(x, y) 2216 } 2217 pdf.SetXY(curx, y+height) 2218 } 2219 fileStr := example.Filename("Fpdf_WrappedTableCells") 2220 err := pdf.OutputFileAndClose(fileStr) 2221 example.Summary(err, fileStr) 2222 // Output: 2223 // Successfully generated pdf/Fpdf_WrappedTableCells.pdf 2224 } 2225 2226 // ExampleFpdf_SetJavascript demonstrates including JavaScript in the document. 2227 func ExampleFpdf_SetJavascript() { 2228 pdf := gofpdf.New("P", "mm", "A4", "") 2229 pdf.SetJavascript("print(true);") 2230 pdf.AddPage() 2231 pdf.SetFont("Arial", "", 12) 2232 pdf.Write(10, "Auto-print.") 2233 fileStr := example.Filename("Fpdf_SetJavascript") 2234 err := pdf.OutputFileAndClose(fileStr) 2235 example.Summary(err, fileStr) 2236 // Output: 2237 // Successfully generated pdf/Fpdf_SetJavascript.pdf 2238 } 2239 2240 // ExampleFpdf_AddSpotColor demonstrates spot color use 2241 func ExampleFpdf_AddSpotColor() { 2242 pdf := gofpdf.New("P", "mm", "A4", "") 2243 pdf.AddSpotColor("PANTONE 145 CVC", 0, 42, 100, 25) 2244 pdf.AddPage() 2245 pdf.SetFillSpotColor("PANTONE 145 CVC", 90) 2246 pdf.Rect(80, 40, 50, 50, "F") 2247 fileStr := example.Filename("Fpdf_AddSpotColor") 2248 err := pdf.OutputFileAndClose(fileStr) 2249 example.Summary(err, fileStr) 2250 // Output: 2251 // Successfully generated pdf/Fpdf_AddSpotColor.pdf 2252 } 2253 2254 // ExampleFpdf_RegisterAlias demonstrates how to use `RegisterAlias` to create a table of 2255 // contents. 2256 func ExampleFpdf_RegisterAlias() { 2257 pdf := gofpdf.New("P", "mm", "A4", "") 2258 pdf.SetFont("Arial", "", 12) 2259 pdf.AliasNbPages("") 2260 pdf.AddPage() 2261 2262 // Write the table of contents. We use aliases instead of the page number 2263 // because we don't know which page the section will begin on. 2264 numSections := 3 2265 for i := 1; i <= numSections; i++ { 2266 pdf.Cell(0, 10, fmt.Sprintf("Section %d begins on page {mark %d}", i, i)) 2267 pdf.Ln(10) 2268 } 2269 2270 // Write the sections. Before we start writing, we use `RegisterAlias` to 2271 // ensure that the alias written in the table of contents will be replaced 2272 // by the current page number. 2273 for i := 1; i <= numSections; i++ { 2274 pdf.AddPage() 2275 pdf.RegisterAlias(fmt.Sprintf("{mark %d}", i), fmt.Sprintf("%d", pdf.PageNo())) 2276 pdf.Write(10, fmt.Sprintf("Section %d, page %d of {nb}", i, pdf.PageNo())) 2277 } 2278 2279 fileStr := example.Filename("Fpdf_RegisterAlias") 2280 err := pdf.OutputFileAndClose(fileStr) 2281 example.Summary(err, fileStr) 2282 // Output: 2283 // Successfully generated pdf/Fpdf_RegisterAlias.pdf 2284 } 2285 2286 // ExampleFpdf_RegisterAlias_utf8 demonstrates how to use `RegisterAlias` to 2287 // create a table of contents. This particular example demonstrates the use of 2288 // UTF-8 aliases. 2289 func ExampleFpdf_RegisterAlias_utf8() { 2290 pdf := gofpdf.New("P", "mm", "A4", "") 2291 pdf.AddUTF8Font("dejavu", "", example.FontFile("DejaVuSansCondensed.ttf")) 2292 pdf.SetFont("dejavu", "", 12) 2293 pdf.AliasNbPages("{entute}") 2294 pdf.AddPage() 2295 2296 // Write the table of contents. We use aliases instead of the page number 2297 // because we don't know which page the section will begin on. 2298 numSections := 3 2299 for i := 1; i <= numSections; i++ { 2300 pdf.Cell(0, 10, fmt.Sprintf("Sekcio %d komenciĝas ĉe paĝo {ĉi tiu marko %d}", i, i)) 2301 pdf.Ln(10) 2302 } 2303 2304 // Write the sections. Before we start writing, we use `RegisterAlias` to 2305 // ensure that the alias written in the table of contents will be replaced 2306 // by the current page number. 2307 for i := 1; i <= numSections; i++ { 2308 pdf.AddPage() 2309 pdf.RegisterAlias(fmt.Sprintf("{ĉi tiu marko %d}", i), fmt.Sprintf("%d", pdf.PageNo())) 2310 pdf.Write(10, fmt.Sprintf("Sekcio %d, paĝo %d de {entute}", i, pdf.PageNo())) 2311 } 2312 2313 fileStr := example.Filename("Fpdf_RegisterAliasUTF8") 2314 err := pdf.OutputFileAndClose(fileStr) 2315 example.Summary(err, fileStr) 2316 // Output: 2317 // Successfully generated pdf/Fpdf_RegisterAliasUTF8.pdf 2318 } 2319 2320 // ExampleNewGrid demonstrates the generation of graph grids. 2321 func ExampleNewGrid() { 2322 pdf := gofpdf.New("P", "mm", "A4", "") 2323 pdf.SetFont("Arial", "", 12) 2324 pdf.AddPage() 2325 2326 gr := gofpdf.NewGrid(13, 10, 187, 130) 2327 gr.TickmarksExtentX(0, 10, 4) 2328 gr.TickmarksExtentY(0, 10, 3) 2329 gr.Grid(pdf) 2330 2331 gr = gofpdf.NewGrid(13, 154, 187, 128) 2332 gr.XLabelRotate = true 2333 gr.TickmarksExtentX(0, 1, 12) 2334 gr.XDiv = 5 2335 gr.TickmarksContainY(0, 1.1) 2336 gr.YDiv = 20 2337 // Replace X label formatter with month abbreviation 2338 gr.XTickStr = func(val float64, precision int) string { 2339 return time.Month(math.Mod(val, 12) + 1).String()[0:3] 2340 } 2341 gr.Grid(pdf) 2342 dot := func(x, y float64) { 2343 pdf.Circle(gr.X(x), gr.Y(y), 0.5, "F") 2344 } 2345 pts := []float64{0.39, 0.457, 0.612, 0.84, 0.998, 1.037, 1.015, 0.918, 0.772, 0.659, 0.593, 0.164} 2346 for month, val := range pts { 2347 dot(float64(month)+0.5, val) 2348 } 2349 pdf.SetDrawColor(255, 64, 64) 2350 pdf.SetAlpha(0.5, "Normal") 2351 pdf.SetLineWidth(1.2) 2352 gr.Plot(pdf, 0.5, 11.5, 50, func(x float64) float64 { 2353 // http://www.xuru.org/rt/PR.asp 2354 return 0.227 * math.Exp(-0.0373*x*x+0.471*x) 2355 }) 2356 pdf.SetAlpha(1.0, "Normal") 2357 pdf.SetXY(gr.X(0.5), gr.Y(1.35)) 2358 pdf.SetFontSize(14) 2359 pdf.Write(0, "Solar energy (MWh) per month, 2016") 2360 pdf.AddPage() 2361 2362 gr = gofpdf.NewGrid(13, 10, 187, 274) 2363 gr.TickmarksContainX(2.3, 3.4) 2364 gr.TickmarksContainY(10.4, 56.8) 2365 gr.Grid(pdf) 2366 2367 fileStr := example.Filename("Fpdf_Grid") 2368 err := pdf.OutputFileAndClose(fileStr) 2369 example.Summary(err, fileStr) 2370 // Output: 2371 // Successfully generated pdf/Fpdf_Grid.pdf 2372 } 2373 2374 // ExampleFpdf_SetPageBox demonstrates the use of a page box 2375 func ExampleFpdf_SetPageBox() { 2376 // pdfinfo (from http://www.xpdfreader.com) reports the following for this example: 2377 // ~ pdfinfo -box pdf/Fpdf_PageBox.pdf 2378 // Producer: FPDF 1.7 2379 // CreationDate: Sat Jan 1 00:00:00 2000 2380 // ModDate: Sat Jan 1 00:00:00 2000 2381 // Tagged: no 2382 // Form: none 2383 // Pages: 1 2384 // Encrypted: no 2385 // Page size: 493.23 x 739.85 pts (rotated 0 degrees) 2386 // MediaBox: 0.00 0.00 595.28 841.89 2387 // CropBox: 51.02 51.02 544.25 790.87 2388 // BleedBox: 51.02 51.02 544.25 790.87 2389 // TrimBox: 51.02 51.02 544.25 790.87 2390 // ArtBox: 51.02 51.02 544.25 790.87 2391 // File size: 1053 bytes 2392 // Optimized: no 2393 // PDF version: 1.3 2394 const ( 2395 wd = 210 2396 ht = 297 2397 fontsize = 6 2398 boxmargin = 3 * fontsize 2399 ) 2400 pdf := gofpdf.New("P", "mm", "A4", "") // 210mm x 297mm 2401 pdf.SetPageBox("crop", boxmargin, boxmargin, wd-2*boxmargin, ht-2*boxmargin) 2402 pdf.SetFont("Arial", "", pdf.UnitToPointConvert(fontsize)) 2403 pdf.AddPage() 2404 pdf.MoveTo(fontsize, fontsize) 2405 pdf.Write(fontsize, "This will be cropped from printed output") 2406 pdf.MoveTo(boxmargin+fontsize, boxmargin+fontsize) 2407 pdf.Write(fontsize, "This will be displayed in cropped output") 2408 fileStr := example.Filename("Fpdf_PageBox") 2409 err := pdf.OutputFileAndClose(fileStr) 2410 example.Summary(err, fileStr) 2411 // Output: 2412 // Successfully generated pdf/Fpdf_PageBox.pdf 2413 } 2414 2415 // ExampleFpdf_SubWrite demonstrates subscripted and superscripted text 2416 // Adapted from http://www.fpdf.org/en/script/script61.php 2417 func ExampleFpdf_SubWrite() { 2418 2419 const ( 2420 fontSize = 12 2421 halfX = 105 2422 ) 2423 2424 pdf := gofpdf.New("P", "mm", "A4", "") // 210mm x 297mm 2425 pdf.AddPage() 2426 pdf.SetFont("Arial", "", fontSize) 2427 _, lineHt := pdf.GetFontSize() 2428 2429 pdf.Write(lineHt, "Hello World!") 2430 pdf.SetX(halfX) 2431 pdf.Write(lineHt, "This is standard text.\n") 2432 pdf.Ln(lineHt * 2) 2433 2434 pdf.SubWrite(10, "H", 33, 0, 0, "") 2435 pdf.Write(10, "ello World!") 2436 pdf.SetX(halfX) 2437 pdf.Write(10, "This is text with a capital first letter.\n") 2438 pdf.Ln(lineHt * 2) 2439 2440 pdf.SubWrite(lineHt, "Y", 6, 0, 0, "") 2441 pdf.Write(lineHt, "ou can also begin the sentence with a small letter. And word wrap also works if the line is too long, like this one is.") 2442 pdf.SetX(halfX) 2443 pdf.Write(lineHt, "This is text with a small first letter.\n") 2444 pdf.Ln(lineHt * 2) 2445 2446 pdf.Write(lineHt, "The world has a lot of km") 2447 pdf.SubWrite(lineHt, "2", 6, 4, 0, "") 2448 pdf.SetX(halfX) 2449 pdf.Write(lineHt, "This is text with a superscripted letter.\n") 2450 pdf.Ln(lineHt * 2) 2451 2452 pdf.Write(lineHt, "The world has a lot of H") 2453 pdf.SubWrite(lineHt, "2", 6, -3, 0, "") 2454 pdf.Write(lineHt, "O") 2455 pdf.SetX(halfX) 2456 pdf.Write(lineHt, "This is text with a subscripted letter.\n") 2457 2458 fileStr := example.Filename("Fpdf_SubWrite") 2459 err := pdf.OutputFileAndClose(fileStr) 2460 example.Summary(err, fileStr) 2461 // Output: 2462 // Successfully generated pdf/Fpdf_SubWrite.pdf 2463 } 2464 2465 // ExampleFpdf_SetPage demomstrates the SetPage() method, allowing content 2466 // generation to be deferred until all pages have been added. 2467 func ExampleFpdf_SetPage() { 2468 rnd := rand.New(rand.NewSource(0)) // Make reproducible documents 2469 pdf := gofpdf.New("L", "cm", "A4", "") 2470 pdf.SetFont("Times", "", 12) 2471 2472 var time []float64 2473 temperaturesFromSensors := make([][]float64, 5) 2474 maxs := []float64{25, 41, 89, 62, 11} 2475 for i := range temperaturesFromSensors { 2476 temperaturesFromSensors[i] = make([]float64, 0) 2477 } 2478 2479 for i := 0.0; i < 100; i += 0.5 { 2480 time = append(time, i) 2481 for j, sensor := range temperaturesFromSensors { 2482 dataValue := rnd.Float64() * maxs[j] 2483 sensor = append(sensor, dataValue) 2484 temperaturesFromSensors[j] = sensor 2485 } 2486 } 2487 var graphs []gofpdf.GridType 2488 var pageNums []int 2489 xMax := time[len(time)-1] 2490 for i := range temperaturesFromSensors { 2491 //Create a new page and graph for each sensor we want to graph. 2492 pdf.AddPage() 2493 pdf.Ln(1) 2494 //Custom label per sensor 2495 pdf.WriteAligned(0, 0, "Temperature Sensor "+strconv.Itoa(i+1)+" (C) vs Time (min)", "C") 2496 pdf.Ln(0.5) 2497 graph := gofpdf.NewGrid(pdf.GetX(), pdf.GetY(), 20, 10) 2498 graph.TickmarksContainX(0, xMax) 2499 //Custom Y axis 2500 graph.TickmarksContainY(0, maxs[i]) 2501 graph.Grid(pdf) 2502 //Save references and locations. 2503 graphs = append(graphs, graph) 2504 pageNums = append(pageNums, pdf.PageNo()) 2505 } 2506 // For each X, graph the Y in each sensor. 2507 for i, currTime := range time { 2508 for j, sensor := range temperaturesFromSensors { 2509 pdf.SetPage(pageNums[j]) 2510 graph := graphs[j] 2511 temperature := sensor[i] 2512 pdf.Circle(graph.X(currTime), graph.Y(temperature), 0.04, "D") 2513 } 2514 } 2515 2516 fileStr := example.Filename("Fpdf_SetPage") 2517 err := pdf.OutputFileAndClose(fileStr) 2518 example.Summary(err, fileStr) 2519 // Output: 2520 // Successfully generated pdf/Fpdf_SetPage.pdf 2521 } 2522 2523 // ExampleFpdf_SetFillColor demonstrates how graphic attributes are properly 2524 // assigned within multiple transformations. See issue #234. 2525 func ExampleFpdf_SetFillColor() { 2526 pdf := gofpdf.New("P", "mm", "A4", "") 2527 2528 pdf.AddPage() 2529 pdf.SetFont("Arial", "", 8) 2530 2531 draw := func(trX, trY float64) { 2532 pdf.TransformBegin() 2533 pdf.TransformTranslateX(trX) 2534 pdf.TransformTranslateY(trY) 2535 pdf.SetLineJoinStyle("round") 2536 pdf.SetLineWidth(0.5) 2537 pdf.SetDrawColor(128, 64, 0) 2538 pdf.SetFillColor(255, 127, 0) 2539 pdf.SetAlpha(0.5, "Normal") 2540 pdf.SetDashPattern([]float64{5, 10}, 0) 2541 pdf.Rect(0, 0, 40, 40, "FD") 2542 pdf.SetFontSize(12) 2543 pdf.SetXY(5, 5) 2544 pdf.Write(0, "Test") 2545 pdf.TransformEnd() 2546 } 2547 2548 draw(5, 5) 2549 draw(50, 50) 2550 2551 fileStr := example.Filename("Fpdf_SetFillColor") 2552 err := pdf.OutputFileAndClose(fileStr) 2553 example.Summary(err, fileStr) 2554 // Output: 2555 // Successfully generated pdf/Fpdf_SetFillColor.pdf 2556 } 2557 2558 // ExampleFpdf_TransformRotate demonstrates how to rotate text within a header 2559 // to make a watermark that appears on each page. 2560 func ExampleFpdf_TransformRotate() { 2561 2562 loremStr := lorem() + "\n\n" 2563 pdf := gofpdf.New("P", "mm", "A4", "") 2564 margin := 25.0 2565 pdf.SetMargins(margin, margin, margin) 2566 2567 fontHt := 13.0 2568 lineHt := pdf.PointToUnitConvert(fontHt) 2569 markFontHt := 50.0 2570 markLineHt := pdf.PointToUnitConvert(markFontHt) 2571 markY := (297.0 - markLineHt) / 2.0 2572 ctrX := 210.0 / 2.0 2573 ctrY := 297.0 / 2.0 2574 2575 pdf.SetHeaderFunc(func() { 2576 pdf.SetFont("Arial", "B", markFontHt) 2577 pdf.SetTextColor(206, 216, 232) 2578 pdf.SetXY(margin, markY) 2579 pdf.TransformBegin() 2580 pdf.TransformRotate(45, ctrX, ctrY) 2581 pdf.CellFormat(0, markLineHt, "W A T E R M A R K D E M O", "", 0, "C", false, 0, "") 2582 pdf.TransformEnd() 2583 pdf.SetXY(margin, margin) 2584 }) 2585 2586 pdf.AddPage() 2587 pdf.SetFont("Arial", "", 8) 2588 for j := 0; j < 25; j++ { 2589 pdf.MultiCell(0, lineHt, loremStr, "", "L", false) 2590 } 2591 2592 fileStr := example.Filename("Fpdf_RotateText") 2593 err := pdf.OutputFileAndClose(fileStr) 2594 example.Summary(err, fileStr) 2595 // Output: 2596 // Successfully generated pdf/Fpdf_RotateText.pdf 2597 } 2598 2599 // ExampleFpdf_AddUTF8Font demonstrates how use the font 2600 // with utf-8 mode 2601 func ExampleFpdf_AddUTF8Font() { 2602 var fileStr string 2603 var txtStr []byte 2604 var err error 2605 2606 pdf := gofpdf.New("P", "mm", "A4", "") 2607 2608 pdf.AddPage() 2609 2610 pdf.AddUTF8Font("dejavu", "", example.FontFile("DejaVuSansCondensed.ttf")) 2611 pdf.AddUTF8Font("dejavu", "B", example.FontFile("DejaVuSansCondensed-Bold.ttf")) 2612 pdf.AddUTF8Font("dejavu", "I", example.FontFile("DejaVuSansCondensed-Oblique.ttf")) 2613 pdf.AddUTF8Font("dejavu", "BI", example.FontFile("DejaVuSansCondensed-BoldOblique.ttf")) 2614 2615 fileStr = example.Filename("Fpdf_AddUTF8Font") 2616 txtStr, err = ioutil.ReadFile(example.TextFile("utf-8test.txt")) 2617 if err == nil { 2618 2619 pdf.SetFont("dejavu", "B", 17) 2620 pdf.MultiCell(100, 8, "Text in different languages :", "", "C", false) 2621 pdf.SetFont("dejavu", "", 14) 2622 pdf.MultiCell(100, 5, string(txtStr), "", "C", false) 2623 pdf.Ln(15) 2624 2625 txtStr, err = ioutil.ReadFile(example.TextFile("utf-8test2.txt")) 2626 if err == nil { 2627 2628 pdf.SetFont("dejavu", "BI", 17) 2629 pdf.MultiCell(100, 8, "Greek text with alignStr = \"J\":", "", "C", false) 2630 pdf.SetFont("dejavu", "I", 14) 2631 pdf.MultiCell(100, 5, string(txtStr), "", "J", false) 2632 err = pdf.OutputFileAndClose(fileStr) 2633 2634 } 2635 } 2636 example.Summary(err, fileStr) 2637 // Output: 2638 // Successfully generated pdf/Fpdf_AddUTF8Font.pdf 2639 } 2640 2641 // ExampleUTF8CutFont demonstrates how generate a TrueType font subset. 2642 func ExampleUTF8CutFont() { 2643 var pdfFileStr, fullFontFileStr, subFontFileStr string 2644 var subFont, fullFont []byte 2645 var err error 2646 2647 pdfFileStr = example.Filename("Fpdf_UTF8CutFont") 2648 fullFontFileStr = example.FontFile("calligra.ttf") 2649 fullFont, err = ioutil.ReadFile(fullFontFileStr) 2650 if err == nil { 2651 subFontFileStr = "calligra_abcde.ttf" 2652 subFont = gofpdf.UTF8CutFont(fullFont, "abcde") 2653 err = ioutil.WriteFile(subFontFileStr, subFont, 0600) 2654 if err == nil { 2655 y := 24.0 2656 pdf := gofpdf.New("P", "mm", "A4", "") 2657 fontHt := 17.0 2658 lineHt := pdf.PointConvert(fontHt) 2659 write := func(format string, args ...interface{}) { 2660 pdf.SetXY(24.0, y) 2661 pdf.Cell(200.0, lineHt, fmt.Sprintf(format, args...)) 2662 y += lineHt 2663 } 2664 writeSize := func(fileStr string) { 2665 var info os.FileInfo 2666 var err error 2667 info, err = os.Stat(fileStr) 2668 if err == nil { 2669 write("%6d: size of %s", info.Size(), fileStr) 2670 } 2671 } 2672 pdf.AddPage() 2673 pdf.AddUTF8Font("calligra", "", subFontFileStr) 2674 pdf.SetFont("calligra", "", fontHt) 2675 write("cabbed") 2676 write("vwxyz") 2677 pdf.SetFont("courier", "", fontHt) 2678 writeSize(fullFontFileStr) 2679 writeSize(subFontFileStr) 2680 err = pdf.OutputFileAndClose(pdfFileStr) 2681 os.Remove(subFontFileStr) 2682 } 2683 } 2684 example.Summary(err, pdfFileStr) 2685 // Output: 2686 // Successfully generated pdf/Fpdf_UTF8CutFont.pdf 2687 } 2688 2689 func ExampleFpdf_RoundedRect() { 2690 const ( 2691 wd = 40.0 2692 hgap = 10.0 2693 radius = 10.0 2694 ht = 60.0 2695 vgap = 10.0 2696 ) 2697 corner := func(b1, b2, b3, b4 bool) (cstr string) { 2698 if b1 { 2699 cstr = "1" 2700 } 2701 if b2 { 2702 cstr += "2" 2703 } 2704 if b3 { 2705 cstr += "3" 2706 } 2707 if b4 { 2708 cstr += "4" 2709 } 2710 return 2711 } 2712 pdf := gofpdf.New("P", "mm", "A4", "") // 210 x 297 2713 pdf.AddPage() 2714 pdf.SetLineWidth(0.5) 2715 y := vgap 2716 r := 40 2717 g := 30 2718 b := 20 2719 for row := 0; row < 4; row++ { 2720 x := hgap 2721 for col := 0; col < 4; col++ { 2722 pdf.SetFillColor(r, g, b) 2723 pdf.RoundedRect(x, y, wd, ht, radius, corner(row&1 == 1, row&2 == 2, col&1 == 1, col&2 == 2), "FD") 2724 r += 8 2725 g += 10 2726 b += 12 2727 x += wd + hgap 2728 } 2729 y += ht + vgap 2730 } 2731 pdf.AddPage() 2732 pdf.RoundedRectExt(10, 20, 40, 80, 4., 0., 20, 0., "FD") 2733 2734 fileStr := example.Filename("Fpdf_RoundedRect") 2735 err := pdf.OutputFileAndClose(fileStr) 2736 example.Summary(err, fileStr) 2737 // Output: 2738 // Successfully generated pdf/Fpdf_RoundedRect.pdf 2739 } 2740 2741 // ExampleFpdf_SetUnderlineThickness demonstrates how to adjust the text 2742 // underline thickness. 2743 func ExampleFpdf_SetUnderlineThickness() { 2744 pdf := gofpdf.New("P", "mm", "A4", "") // 210mm x 297mm 2745 pdf.AddPage() 2746 pdf.SetFont("Arial", "U", 12) 2747 2748 pdf.SetUnderlineThickness(0.5) 2749 pdf.CellFormat(0, 10, "Thin underline", "", 1, "", false, 0, "") 2750 2751 pdf.SetUnderlineThickness(1) 2752 pdf.CellFormat(0, 10, "Normal underline", "", 1, "", false, 0, "") 2753 2754 pdf.SetUnderlineThickness(2) 2755 pdf.CellFormat(0, 10, "Thicker underline", "", 1, "", false, 0, "") 2756 2757 fileStr := example.Filename("Fpdf_UnderlineThickness") 2758 err := pdf.OutputFileAndClose(fileStr) 2759 example.Summary(err, fileStr) 2760 // Output: 2761 // Successfully generated pdf/Fpdf_UnderlineThickness.pdf 2762 } 2763 2764 // ExampleFpdf_Cell_strikeout demonstrates striked-out text 2765 func ExampleFpdf_Cell_strikeout() { 2766 2767 pdf := gofpdf.New("P", "mm", "A4", "") // 210mm x 297mm 2768 pdf.AddPage() 2769 2770 for fontSize := 4; fontSize < 40; fontSize += 10 { 2771 pdf.SetFont("Arial", "S", float64(fontSize)) 2772 pdf.SetXY(0, float64(fontSize)) 2773 pdf.Cell(40, 10, "Hello World") 2774 } 2775 2776 fileStr := example.Filename("Fpdf_Cell_strikeout") 2777 err := pdf.OutputFileAndClose(fileStr) 2778 example.Summary(err, fileStr) 2779 // Output: 2780 // Successfully generated pdf/Fpdf_Cell_strikeout.pdf 2781 } 2782 2783 // ExampleFpdf_SetTextRenderingMode demonstrates rendering modes in PDFs. 2784 func ExampleFpdf_SetTextRenderingMode() { 2785 2786 pdf := gofpdf.New("P", "mm", "A4", "") // 210mm x 297mm 2787 pdf.AddPage() 2788 fontSz := float64(16) 2789 lineSz := pdf.PointToUnitConvert(fontSz) 2790 pdf.SetFont("Times", "", fontSz) 2791 pdf.Write(lineSz, "This document demonstrates various modes of text rendering. Search for \"Mode 3\" "+ 2792 "to locate text that has been rendered invisibly. This selection can be copied "+ 2793 "into the clipboard as usual and is useful for overlaying onto non-textual elements such "+ 2794 "as images to make them searchable.\n\n") 2795 fontSz = float64(125) 2796 lineSz = pdf.PointToUnitConvert(fontSz) 2797 pdf.SetFontSize(fontSz) 2798 pdf.SetTextColor(170, 170, 190) 2799 pdf.SetDrawColor(50, 60, 90) 2800 2801 write := func(mode int) { 2802 pdf.SetTextRenderingMode(mode) 2803 pdf.CellFormat(210, lineSz, fmt.Sprintf("Mode %d", mode), "", 1, "", false, 0, "") 2804 } 2805 2806 for mode := 0; mode < 4; mode++ { 2807 write(mode) 2808 } 2809 write(0) 2810 2811 fileStr := example.Filename("Fpdf_TextRenderingMode") 2812 err := pdf.OutputFileAndClose(fileStr) 2813 example.Summary(err, fileStr) 2814 // Output: 2815 // Successfully generated pdf/Fpdf_TextRenderingMode.pdf 2816 } 2817 2818 // TestIssue0316 addresses issue 316 in which AddUTF8FromBytes modifies its argument 2819 // utf8bytes resulting in a panic if you generate two PDFs with the "same" font bytes. 2820 func TestIssue0316(t *testing.T) { 2821 pdf := gofpdf.New(gofpdf.OrientationPortrait, "mm", "A4", "") 2822 pdf.AddPage() 2823 fontBytes, _ := ioutil.ReadFile(example.FontFile("DejaVuSansCondensed.ttf")) 2824 ofontBytes := append([]byte{}, fontBytes...) 2825 pdf.AddUTF8FontFromBytes("dejavu", "", fontBytes) 2826 pdf.SetFont("dejavu", "", 16) 2827 pdf.Cell(40, 10, "Hello World!") 2828 fileStr := example.Filename("TestIssue0316") 2829 err := pdf.OutputFileAndClose(fileStr) 2830 example.Summary(err, fileStr) 2831 pdf.AddPage() 2832 if !bytes.Equal(fontBytes, ofontBytes) { 2833 t.Fatal("Font data changed during pdf generation") 2834 } 2835 } 2836 2837 func TestMultiCellUnsupportedChar(t *testing.T) { 2838 pdf := gofpdf.New("P", "mm", "A4", "") 2839 pdf.AddPage() 2840 fontBytes, _ := ioutil.ReadFile(example.FontFile("DejaVuSansCondensed.ttf")) 2841 pdf.AddUTF8FontFromBytes("dejavu", "", fontBytes) 2842 pdf.SetFont("dejavu", "", 16) 2843 2844 defer func() { 2845 if r := recover(); r != nil { 2846 t.Errorf("unexpected panic: %v", r) 2847 } 2848 }() 2849 2850 pdf.MultiCell(0, 5, "😀", "", "", false) 2851 2852 fileStr := example.Filename("TestMultiCellUnsupportedChar") 2853 pdf.OutputFileAndClose(fileStr) 2854 } 2855 2856 // ExampleFpdf_SetTextRenderingMode demonstrates embedding files in PDFs, 2857 // at the top-level. 2858 func ExampleFpdf_SetAttachments() { 2859 pdf := gofpdf.New("P", "mm", "A4", "") 2860 2861 // Global attachments 2862 file, err := ioutil.ReadFile("grid.go") 2863 if err != nil { 2864 pdf.SetError(err) 2865 } 2866 a1 := gofpdf.Attachment{Content: file, Filename: "grid.go"} 2867 file, err = ioutil.ReadFile("LICENSE") 2868 if err != nil { 2869 pdf.SetError(err) 2870 } 2871 a2 := gofpdf.Attachment{Content: file, Filename: "License"} 2872 pdf.SetAttachments([]gofpdf.Attachment{a1, a2}) 2873 2874 fileStr := example.Filename("Fpdf_EmbeddedFiles") 2875 err = pdf.OutputFileAndClose(fileStr) 2876 example.Summary(err, fileStr) 2877 // Output: 2878 // Successfully generated pdf/Fpdf_EmbeddedFiles.pdf 2879 } 2880 2881 func ExampleFpdf_AddAttachmentAnnotation() { 2882 pdf := gofpdf.New("P", "mm", "A4", "") 2883 pdf.SetFont("Arial", "", 12) 2884 pdf.AddPage() 2885 2886 // Per page attachment 2887 file, err := ioutil.ReadFile("grid.go") 2888 if err != nil { 2889 pdf.SetError(err) 2890 } 2891 a := gofpdf.Attachment{Content: file, Filename: "grid.go", Description: "Some amazing code !"} 2892 2893 pdf.SetXY(5, 10) 2894 pdf.Rect(2, 10, 50, 15, "D") 2895 pdf.AddAttachmentAnnotation(&a, 2, 10, 50, 15) 2896 pdf.Cell(50, 15, "A first link") 2897 2898 pdf.SetXY(5, 80) 2899 pdf.Rect(2, 80, 50, 15, "D") 2900 pdf.AddAttachmentAnnotation(&a, 2, 80, 50, 15) 2901 pdf.Cell(50, 15, "A second link (no copy)") 2902 2903 fileStr := example.Filename("Fpdf_FileAnnotations") 2904 err = pdf.OutputFileAndClose(fileStr) 2905 example.Summary(err, fileStr) 2906 // Output: 2907 // Successfully generated pdf/Fpdf_FileAnnotations.pdf 2908 } 2909 2910 func ExampleFpdf_SetModificationDate() { 2911 // pdfinfo (from http://www.xpdfreader.com) reports the following for this example : 2912 // ~ pdfinfo -box pdf/Fpdf_PageBox.pdf 2913 // Producer: FPDF 1.7 2914 // CreationDate: Sat Jan 1 00:00:00 2000 2915 // ModDate: Sun Jan 2 10:22:30 2000 2916 pdf := gofpdf.New("", "", "", "") 2917 pdf.AddPage() 2918 pdf.SetModificationDate(time.Date(2000, 1, 2, 10, 22, 30, 0, time.UTC)) 2919 fileStr := example.Filename("Fpdf_SetModificationDate") 2920 err := pdf.OutputFileAndClose(fileStr) 2921 example.Summary(err, fileStr) 2922 // Output: 2923 // Successfully generated pdf/Fpdf_SetModificationDate.pdf 2924 }