unipdf/pdf/creator/creator_test.go

1602 lines
44 KiB
Go
Raw Normal View History

2017-07-07 15:37:50 +00:00
/*
* This file is subject to the terms and conditions defined in
* file 'LICENSE.md', which is part of this source code package.
*/
package creator
// This test file contains multiple tests to generate PDFs. The outputs are written into /tmp as files. The files
// themselves need to be observed to check for correctness as we don't have a good way to automatically check
// if every detail is correct.
import (
"fmt"
goimage "image"
"io/ioutil"
"math"
"testing"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/qr"
2017-07-08 23:09:52 +00:00
"github.com/unidoc/unidoc/common"
"github.com/unidoc/unidoc/pdf/core"
2017-07-07 15:37:50 +00:00
"github.com/unidoc/unidoc/pdf/model"
"github.com/unidoc/unidoc/pdf/model/fonts"
"github.com/unidoc/unidoc/pdf/model/textencoding"
2018-06-29 23:55:23 +06:00
"github.com/unidoc/unidoc/pdf/contentstream/draw"
2017-07-07 15:37:50 +00:00
)
func init() {
common.SetLogger(common.NewConsoleLogger(common.LogLevelDebug))
}
2017-07-07 15:37:50 +00:00
const testPdfFile1 = "../../testfiles/minimal.pdf"
const testPdfLoremIpsumFile = "../../testfiles/lorem.pdf"
const testPdfTemplatesFile1 = "../../testfiles/templates1.pdf"
const testImageFile1 = "../../testfiles/logo.png"
const testImageFile2 = "../../testfiles/signature.png"
2017-07-25 15:57:51 +00:00
const testRobotoRegularTTFFile = "../../testfiles/roboto/Roboto-Regular.ttf"
const testRobotoBoldTTFFile = "../../testfiles/roboto/Roboto-Bold.ttf"
2017-07-07 15:37:50 +00:00
func TestTemplate1(t *testing.T) {
creator := New()
pages, err := loadPagesFromFile(testPdfFile1)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
template, err := NewBlockFromPage(pages[0])
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
template.SetPos(0, 0)
creator.Draw(template)
template.SetAngle(45)
creator.Draw(template)
template.Scale(0.5, 0.5)
creator.Draw(template)
template.Scale(4, 4)
creator.Draw(template)
template.SetAngle(90)
template.SetPos(100, 200)
creator.Draw(template)
creator.WriteToFile("/tmp/template_1.pdf")
return
}
// TestImage1 tests loading an image and adding to file at an absolute position.
2017-07-07 15:37:50 +00:00
func TestImage1(t *testing.T) {
creator := New()
imgData, err := ioutil.ReadFile(testImageFile1)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
img, err := NewImageFromData(imgData)
2017-07-07 15:37:50 +00:00
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
img.SetPos(0, 100)
img.ScaleToWidth(1.0 * creator.Width())
err = creator.Draw(img)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
err = creator.WriteToFile("/tmp/1.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// TestImageWithEncoder tests loading inserting an image with a specified encoder.
func TestImageWithEncoder(t *testing.T) {
creator := New()
imgData, err := ioutil.ReadFile(testImageFile1)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
img, err := NewImageFromData(imgData)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
// JPEG encoder (DCT) with quality factor 70.
encoder := core.NewDCTEncoder()
encoder.Quality = 70
encoder.Width = int(img.Width())
encoder.Height = int(img.Height())
img.SetEncoder(encoder)
img.SetPos(0, 100)
img.ScaleToWidth(1.0 * creator.Width())
err = creator.Draw(img)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
err = creator.WriteToFile("/tmp/1_dct.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
func TestShapes1(t *testing.T) {
creator := New()
imgData, err := ioutil.ReadFile(testImageFile1)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
img, err := NewImageFromData(imgData)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
img.SetPos(0, 100)
img.ScaleToWidth(1.0 * creator.Width())
err = creator.Draw(img)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
// Add line.
line := NewLine(0, 0, 100, 100)
line.SetLineWidth(3.0)
2017-07-14 21:58:16 +00:00
line.SetColor(ColorRGBFromHex("#ff0000"))
err = creator.Draw(line)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
// Add rect with default params.
rect := NewRectangle(100, 100, 100, 100)
err = creator.Draw(rect)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
// Add rect with fill and large border
rect = NewRectangle(100, 500, 100, 100)
2017-07-14 21:58:16 +00:00
rect.SetBorderColor(ColorRGBFromHex("#00ff00")) // Green border
rect.SetBorderWidth(15.0)
2017-07-14 21:58:16 +00:00
rect.SetFillColor(ColorRGBFromHex("#0000ff")) // Blue fill
err = creator.Draw(rect)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
// Draw a circle. (inscribed inside the previous rectangle).
ell := NewEllipse(100, 100, 100, 100)
err = creator.Draw(ell)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
// Draw a circle around upper right page corner.
ell = NewEllipse(creator.Width(), 0, 100, 100)
err = creator.Draw(ell)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
// Draw an ellipse with fill and border.
ell = NewEllipse(500, 100, 100, 200)
2017-07-14 21:58:16 +00:00
ell.SetFillColor(ColorRGBFromHex("#ccc")) // Gray fill
ell.SetBorderWidth(10.0)
err = creator.Draw(ell)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
err = creator.WriteToFile("/tmp/1_shapes.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Example drawing image and line shape on a block and applying to pages, also demonstrating block rotation.
func TestShapesOnBlock(t *testing.T) {
creator := New()
block := NewBlock(creator.Width(), 200)
imgData, err := ioutil.ReadFile(testImageFile1)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
img, err := NewImageFromData(imgData)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
img.SetPos(50, 75)
img.ScaleToHeight(100.0)
block.Draw(img)
// Add line.
line := NewLine(0, 180, creator.Width(), 180)
line.SetLineWidth(10.0)
2017-07-14 21:58:16 +00:00
line.SetColor(ColorRGBFromHex("#ff0000"))
block.Draw(line)
creator.NewPage()
creator.MoveTo(0, 0)
creator.Draw(block)
creator.NewPage()
creator.MoveTo(0, 200)
creator.Draw(block)
creator.NewPage()
creator.MoveTo(0, 700)
block.SetAngle(90)
creator.Draw(block)
err = creator.WriteToFile("/tmp/1_shapes_on_block.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Test image wrapping between pages when using relative context mode.
2017-07-07 15:37:50 +00:00
func TestImageWrapping(t *testing.T) {
creator := New()
imgData, err := ioutil.ReadFile(testImageFile1)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
img, err := NewImageFromData(imgData)
2017-07-07 15:37:50 +00:00
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
for j := 0; j < 40; j++ {
img.ScaleToWidth(100 + 10*float64(j+1))
err = creator.Draw(img)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
err = creator.WriteToFile("/tmp/1_wrap.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Test rotating image. Rotating about upper left corner.
2017-07-07 15:37:50 +00:00
func TestImageRotation(t *testing.T) {
creator := New()
imgData, err := ioutil.ReadFile(testImageFile1)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
img, err := NewImageFromData(imgData)
2017-07-07 15:37:50 +00:00
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
//creator.MoveTo(0, 0)
img.ScaleToWidth(100)
angles := []float64{0, 90, 180, 270}
for _, angle := range angles {
creator.NewPage()
creator.MoveTo(100, 100)
img.SetAngle(angle)
err = creator.Draw(img)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
err = creator.WriteToFile("/tmp/1_rotate.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Test image, rotation and page wrapping. Disadvantage here is that content is overlapping. May be reconsidered
// in the future. And actually reconsider overall how images are used in the relative context mode.
2017-07-07 15:37:50 +00:00
func TestImageRotationAndWrap(t *testing.T) {
creator := New()
imgData, err := ioutil.ReadFile(testImageFile1)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
img, err := NewImageFromData(imgData)
2017-07-07 15:37:50 +00:00
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
img.ScaleToWidth(100)
creator.NewPage()
creator.MoveTo(100, 100)
angles := []float64{0, 90, 180, 270, 0, 90, 180, 270}
//angles := []float64{0, 0, 45, 90}
for _, angle := range angles {
img.SetAngle(angle)
err = creator.Draw(img)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
err = creator.WriteToFile("/tmp/rotate_2.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Test basic paragraph with default font.
2017-07-07 15:37:50 +00:00
func TestParagraph1(t *testing.T) {
creator := New()
p := NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt" +
"ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " +
"aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore" +
"eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt " +
"mollit anim id est laborum.")
err := creator.Draw(p)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
err = creator.WriteToFile("/tmp/2_p1.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Test paragraph and page and text wrapping with left, justify, center and right modes.
// TODO: In the future we would like the paragraph to split up between pages. Split up on line, never allowing
// less than 2 lines to go over (common practice).
// TODO: In the future we would like to implement Donald Knuth's line wrapping algorithm or something similar.
2017-07-07 15:37:50 +00:00
func TestParagraphWrapping(t *testing.T) {
creator := New()
p := NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt" +
"ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " +
"aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore" +
"eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt " +
"mollit anim id est laborum.")
p.SetMargins(0, 0, 5, 0)
alignments := []TextAlignment{TextAlignmentLeft, TextAlignmentJustify, TextAlignmentCenter, TextAlignmentRight}
for j := 0; j < 25; j++ {
//p.SetAlignment(alignments[j%4])
p.SetTextAlignment(alignments[1])
err := creator.Draw(p)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
err := creator.WriteToFile("/tmp/2_pwrap.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
func TestParagraphWrapping2(t *testing.T) {
creator := New()
p := NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt" +
"ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " +
"aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore" +
"eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt " +
"mollit anim id est laborum.")
alignments := []TextAlignment{TextAlignmentLeft, TextAlignmentJustify, TextAlignmentCenter, TextAlignmentRight}
for j := 0; j < 25; j++ {
//p.SetAlignment(alignments[j%4])
p.SetMargins(50, 50, 50, 50)
p.SetTextAlignment(alignments[1])
err := creator.Draw(p)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
err := creator.WriteToFile("/tmp/2_pwrap2.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
2017-07-25 15:57:51 +00:00
// Test writing with TTF fonts.
2017-07-07 15:37:50 +00:00
func TestParagraphFonts(t *testing.T) {
creator := New()
2017-07-25 15:57:51 +00:00
roboto, err := model.NewPdfFontFromTTFFile(testRobotoRegularTTFFile)
2017-07-07 15:37:50 +00:00
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
2017-07-25 15:57:51 +00:00
robotoBold, err := model.NewPdfFontFromTTFFile(testRobotoBoldTTFFile)
2017-07-07 15:37:50 +00:00
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
2017-07-25 15:57:51 +00:00
fonts := []fonts.Font{roboto, robotoBold, fonts.NewFontHelvetica(), roboto, robotoBold, fonts.NewFontHelvetica()}
2017-07-07 15:37:50 +00:00
for _, font := range fonts {
p := NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt" +
"ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " +
"aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore" +
"eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt " +
"mollit anim id est laborum.")
p.SetFont(font)
p.SetFontSize(14)
//p.SetWrapWidth(0.8 * creator.Width())
p.SetTextAlignment(TextAlignmentJustify)
p.SetLineHeight(1.2)
p.SetMargins(0, 0, 5, 0)
err = creator.Draw(p)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
err = creator.WriteToFile("/tmp/2_pArial.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Test writing with the 14 built in fonts.
2017-07-08 23:09:52 +00:00
func TestParagraphStandardFonts(t *testing.T) {
creator := New()
names := []string{
"Courier",
"Courier-Bold",
"Courier-BoldOblique",
"Courier-Oblique",
"Helvetica",
"Helvetica-Bold",
"Helvetica-BoldOblique",
"Helvetica-Oblique",
"Times-Roman",
2017-07-08 23:09:52 +00:00
"Times-Bold",
"Times-BoldItalic",
"Times-Italic",
"Symbol",
"ZapfDingbats",
}
fonts := []fonts.Font{
fonts.NewFontCourier(),
fonts.NewFontCourierBold(),
fonts.NewFontCourierBoldOblique(),
fonts.NewFontCourierOblique(),
fonts.NewFontHelvetica(),
fonts.NewFontHelveticaBold(),
fonts.NewFontHelveticaBoldOblique(),
fonts.NewFontHelveticaOblique(),
fonts.NewFontTimesRoman(),
2017-07-08 23:09:52 +00:00
fonts.NewFontTimesBold(),
fonts.NewFontTimesBoldItalic(),
fonts.NewFontTimesItalic(),
fonts.NewFontSymbol(),
fonts.NewFontZapfDingbats(),
}
texts := []string{
"Courier: Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
"Courier-Bold: Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
"Courier-BoldOblique: Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
"Courier-Oblique: Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
"Helvetica: Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
"Helvetica-Bold: Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
"Helvetica-BoldOblique: Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
"Helvetica-Oblique: Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
"Times-Roman: Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
"Times-Bold: Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
"Times-BoldItalic: Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
"Times-Italic: Lorem ipsum dolor sit amet, consectetur adipiscing elit...",
"\u2206\u0393\u0020\u2192\u0020\u0030", // Delta Gamma space arrowright space zero (demonstrate Symbol font)
"\u2702\u0020\u2709\u261e\u2711\u2714", // a2 (scissors) space a117 (mail) a12 (finger) a17 (pen) a20 (checkmark)
}
2017-07-08 23:09:52 +00:00
for idx, font := range fonts {
p := NewParagraph(texts[idx])
2017-07-08 23:09:52 +00:00
p.SetFont(font)
p.SetFontSize(12)
p.SetLineHeight(1.2)
p.SetMargins(0, 0, 5, 0)
if names[idx] == "Symbol" {
// For Symbol font, need to use Symbol encoder.
p.SetEncoder(textencoding.NewSymbolEncoder())
} else if names[idx] == "ZapfDingbats" {
// Font ZapfDingbats font, need to use ZapfDingbats encoder.
p.SetEncoder(textencoding.NewZapfDingbatsEncoder())
}
2017-07-08 23:09:52 +00:00
err := creator.Draw(p)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
err := creator.WriteToFile("/tmp/2_standard14fonts.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Tests creating a chapter with paragraphs.
2017-07-07 15:37:50 +00:00
func TestChapter(t *testing.T) {
c := New()
ch1 := c.NewChapter("Introduction")
p := NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt " +
"ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " +
"aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore " +
"eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt " +
"mollit anim id est laborum.")
p.SetMargins(0, 0, 10, 0)
for j := 0; j < 55; j++ {
ch1.Add(p) // Can add any drawable..
}
c.Draw(ch1)
err := c.WriteToFile("/tmp/3_chapters.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Tests creating a chapter with paragraphs.
func TestChapterMargins(t *testing.T) {
c := New()
for j := 0; j < 20; j++ {
ch := c.NewChapter(fmt.Sprintf("Chapter %d", j+1))
if j < 5 {
ch.SetMargins(3*float64(j), 3*float64(j), 5+float64(j), 0)
}
p := NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt " +
"ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " +
"aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore " +
"eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt " +
"mollit anim id est laborum.")
p.SetTextAlignment(TextAlignmentJustify)
ch.Add(p)
c.Draw(ch)
}
err := c.WriteToFile("/tmp/3_chapters_margins.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Test creating and drawing subchapters with text content.
// Also generates a front page, and a table of contents.
2017-07-07 15:37:50 +00:00
func TestSubchaptersSimple(t *testing.T) {
c := New()
ch1 := c.NewChapter("Introduction")
subchap1 := c.NewSubchapter(ch1, "The fundamentals of the mastery of the most genious experiment of all times in modern world history. The story of the maker and the maker bot and the genius cow.")
subchap1.SetMargins(0, 0, 5, 0)
//subCh1 := NewSubchapter(ch1, "Workflow")
p := NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt " +
"ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " +
"aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore " +
"eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt " +
"mollit anim id est laborum.")
p.SetTextAlignment(TextAlignmentJustify)
p.SetMargins(0, 0, 5, 0)
for j := 0; j < 1; j++ {
subchap1.Add(p)
}
subchap2 := c.NewSubchapter(ch1, "Mechanism")
subchap2.SetMargins(0, 0, 5, 0)
for j := 0; j < 1; j++ {
subchap2.Add(p)
}
subchap3 := c.NewSubchapter(ch1, "Discussion")
subchap3.SetMargins(0, 0, 5, 0)
for j := 0; j < 1; j++ {
subchap3.Add(p)
}
subchap4 := c.NewSubchapter(ch1, "Conclusion")
subchap4.SetMargins(0, 0, 5, 0)
for j := 0; j < 1; j++ {
subchap4.Add(p)
}
c.Draw(ch1)
ch2 := c.NewChapter("References")
for j := 0; j < 13; j++ {
ch2.Add(p)
}
c.Draw(ch2)
// Set a function to create the front Page.
c.CreateFrontPage(func(args FrontpageFunctionArgs) {
2017-07-07 15:37:50 +00:00
p := NewParagraph("Example Report")
p.SetWidth(c.Width())
p.SetTextAlignment(TextAlignmentCenter)
p.SetFontSize(32)
p.SetPos(0, 300)
c.Draw(p)
p.SetFontSize(22)
p.SetText("Example Report Data Results")
p.SetPos(0, 340)
c.Draw(p)
})
// Set a function to create the table of contents.
// Should be able to wrap..
c.CreateTableOfContents(func(toc *TableOfContents) (*Chapter, error) {
ch := c.NewChapter("Table of contents")
2017-07-14 21:58:16 +00:00
ch.GetHeading().SetColor(ColorRGBFromArithmetic(0.5, 0.5, 0.5))
2017-07-07 15:37:50 +00:00
ch.GetHeading().SetFontSize(28)
ch.GetHeading().SetMargins(0, 0, 0, 30)
2017-07-14 16:24:07 +00:00
table := NewTable(2) // 2 column table.
2017-07-07 15:37:50 +00:00
// Default, equal column sizes (4x0.25)...
table.SetColumnWidths(0.9, 0.1)
for _, entry := range toc.entries {
// Col 1. Chapter number, title.
var str string
if entry.Subchapter == 0 {
str = fmt.Sprintf("%d. %s", entry.Chapter, entry.Title)
} else {
str = fmt.Sprintf(" %d.%d. %s", entry.Chapter, entry.Subchapter, entry.Title)
}
p := NewParagraph(str)
p.SetFontSize(14)
2017-07-14 16:24:07 +00:00
cell := table.NewCell()
2017-07-07 15:37:50 +00:00
cell.SetContent(p)
// Set the paragraph width to the cell width.
p.SetWidth(cell.Width(c.Context()))
2017-07-14 16:24:07 +00:00
table.SetRowHeight(table.CurRow(), p.Height()*1.2)
2017-07-07 15:37:50 +00:00
// Col 1. Page number.
p = NewParagraph(fmt.Sprintf("%d", entry.PageNumber))
p.SetFontSize(14)
2017-07-14 16:24:07 +00:00
cell = table.NewCell()
2017-07-07 15:37:50 +00:00
cell.SetContent(p)
}
err := ch.Add(table)
if err != nil {
fmt.Printf("Error adding table: %v\n", err)
return nil, err
}
return ch, nil
})
err := c.WriteToFile("/tmp/3_subchapters_simple.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
func TestSubchapters(t *testing.T) {
c := New()
ch1 := c.NewChapter("Introduction")
subchap1 := c.NewSubchapter(ch1, "The fundamentals")
subchap1.SetMargins(0, 0, 5, 0)
//subCh1 := NewSubchapter(ch1, "Workflow")
p := NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt " +
"ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " +
"aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore " +
"eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt " +
"mollit anim id est laborum.")
p.SetTextAlignment(TextAlignmentJustify)
p.SetMargins(0, 0, 5, 0)
for j := 0; j < 18; j++ {
subchap1.Add(p)
}
subchap2 := c.NewSubchapter(ch1, "Mechanism")
subchap2.SetMargins(0, 0, 5, 0)
for j := 0; j < 15; j++ {
subchap2.Add(p)
}
subchap3 := c.NewSubchapter(ch1, "Discussion")
subchap3.SetMargins(0, 0, 5, 0)
for j := 0; j < 19; j++ {
subchap3.Add(p)
}
subchap4 := c.NewSubchapter(ch1, "Conclusion")
subchap4.SetMargins(0, 0, 5, 0)
for j := 0; j < 23; j++ {
subchap4.Add(p)
}
c.Draw(ch1)
for i := 0; i < 50; i++ {
ch2 := c.NewChapter("References")
for j := 0; j < 13; j++ {
ch2.Add(p)
}
c.Draw(ch2)
}
// Set a function to create the front Page.
c.CreateFrontPage(func(args FrontpageFunctionArgs) {
2017-07-07 15:37:50 +00:00
p := NewParagraph("Example Report")
p.SetWidth(c.Width())
p.SetTextAlignment(TextAlignmentCenter)
p.SetFontSize(32)
p.SetPos(0, 300)
c.Draw(p)
p.SetFontSize(22)
p.SetText("Example Report Data Results")
p.SetPos(0, 340)
c.Draw(p)
})
// Set a function to create the table of contents.
c.CreateTableOfContents(func(toc *TableOfContents) (*Chapter, error) {
ch := c.NewChapter("Table of contents")
2017-07-14 21:58:16 +00:00
ch.GetHeading().SetColor(ColorRGBFromArithmetic(0.5, 0.5, 0.5))
2017-07-07 15:37:50 +00:00
ch.GetHeading().SetFontSize(28)
ch.GetHeading().SetMargins(0, 0, 0, 30)
2017-07-14 16:24:07 +00:00
table := NewTable(2)
2017-07-07 15:37:50 +00:00
// Default, equal column sizes (4x0.25)...
table.SetColumnWidths(0.9, 0.1)
for _, entry := range toc.entries {
// Col 1. Chapter number, title.
var str string
if entry.Subchapter == 0 {
str = fmt.Sprintf("%d. %s", entry.Chapter, entry.Title)
} else {
str = fmt.Sprintf(" %d.%d. %s", entry.Chapter, entry.Subchapter, entry.Title)
}
p := NewParagraph(str)
p.SetFontSize(14)
2017-07-14 16:24:07 +00:00
cell := table.NewCell()
2017-07-07 15:37:50 +00:00
cell.SetContent(p)
// Set the paragraph width to the cell width.
p.SetWidth(cell.Width(c.Context()))
2017-07-14 16:24:07 +00:00
table.SetRowHeight(table.CurRow(), p.Height()*1.2)
2017-07-07 15:37:50 +00:00
// Col 1. Page number.
p = NewParagraph(fmt.Sprintf("%d", entry.PageNumber))
p.SetFontSize(14)
2017-07-14 16:24:07 +00:00
cell = table.NewCell()
2017-07-07 15:37:50 +00:00
cell.SetContent(p)
}
err := ch.Add(table)
if err != nil {
fmt.Printf("Error adding table: %v\n", err)
return nil, err
}
return ch, nil
})
addHeadersAndFooters(c)
err := c.WriteToFile("/tmp/3_subchapters.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Test creating and drawing a table.
2017-07-07 15:37:50 +00:00
func TestTable(t *testing.T) {
2017-07-14 16:24:07 +00:00
table := NewTable(4) // Mx4 table
2017-07-07 15:37:50 +00:00
// Default, equal column sizes (4x0.25)...
table.SetColumnWidths(0.5, 0.2, 0.2, 0.1)
2017-07-14 16:24:07 +00:00
cell := table.NewCell()
2017-07-07 15:37:50 +00:00
p := NewParagraph("1,1")
cell.SetContent(p)
2017-07-14 16:24:07 +00:00
cell = table.NewCell()
2017-07-07 15:37:50 +00:00
p = NewParagraph("1,2")
cell.SetContent(p)
2017-07-14 16:24:07 +00:00
cell = table.NewCell()
2017-07-07 15:37:50 +00:00
p = NewParagraph("1,3")
cell.SetContent(p)
2017-07-14 16:24:07 +00:00
cell = table.NewCell()
2017-07-07 15:37:50 +00:00
p = NewParagraph("1,4")
cell.SetContent(p)
2017-07-14 16:24:07 +00:00
cell = table.NewCell()
2017-07-07 15:37:50 +00:00
p = NewParagraph("2,1")
cell.SetContent(p)
2017-07-14 16:24:07 +00:00
cell = table.NewCell()
2017-07-07 15:37:50 +00:00
p = NewParagraph("2,2")
cell.SetContent(p)
2017-07-14 16:24:07 +00:00
table.SkipCells(1) // Skip over 2,3.
cell = table.NewCell()
2017-07-07 15:37:50 +00:00
p = NewParagraph("2,4")
cell.SetContent(p)
2017-07-14 16:24:07 +00:00
// Skip over two rows.
table.SkipRows(2)
cell = table.NewCell()
2017-07-07 15:37:50 +00:00
p = NewParagraph("4,4")
cell.SetContent(p)
2017-07-14 16:24:07 +00:00
// Move down 3 rows, 2 to the left.
table.SkipOver(3, -2)
cell = table.NewCell()
p = NewParagraph("7,2")
cell.SetContent(p)
cell.SetBackgroundColor(ColorRGBFrom8bit(255, 0, 0))
2017-07-14 16:24:07 +00:00
2017-07-07 15:37:50 +00:00
c := New()
c.Draw(table)
2018-06-30 00:15:51 +06:00
err := c.WriteToFile("/tmp/4_table.pdf")
2017-07-07 15:37:50 +00:00
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Test creating and drawing a table.
2018-06-25 00:30:32 +06:00
func TestBorderedTable1(t *testing.T) {
table := NewTable(4) // Mx4 table
// Default, equal column sizes (4x0.25)...
table.SetColumnWidths(0.5, 0.2, 0.2, 0.1)
2018-06-25 00:30:32 +06:00
cell1 := table.NewCell()
2018-06-29 23:55:23 +06:00
p := NewParagraph("A")
2018-06-25 00:30:32 +06:00
cell1.SetContent(p)
2018-07-06 21:11:34 +06:00
cell1.SetBorder(CellBorderStyleDoubleBox, 1) // border will be on left
2018-06-29 23:55:23 +06:00
cell1.SetBorderLineStyle(draw.LineStyleDashed)
2018-07-06 21:11:34 +06:00
table.SkipCells(1)
2018-06-30 00:06:50 +06:00
cell2 := table.NewCell()
p = NewParagraph("B")
cell2.SetContent(p)
2018-07-06 21:11:34 +06:00
cell2.SetBorder(CellBorderStyleDoubleBox, 1) // border will be around
cell2.SetBorderLineStyle(draw.LineStyleSolid)
cell2.SetBackgroundColor(ColorRed)
2018-06-30 00:06:50 +06:00
table.SkipCells(1) // Skip over 2,3.
// Skip over two rows.
table.SkipRows(2)
cell8 := table.NewCell()
p = NewParagraph("H")
cell8.SetContent(p)
2018-07-06 21:11:34 +06:00
cell8.SetBorder(CellBorderStyleRight, 1) // border will be on right
cell8.SetBorderLineStyle(draw.LineStyleSolid)
2018-06-30 00:06:50 +06:00
c := New()
c.Draw(table)
2018-06-30 00:15:51 +06:00
err := c.WriteToFile("/tmp/4_table_bordered.pdf")
2018-06-09 06:03:40 +06:00
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Test creating and drawing a table.
func TestBorderedTable2(t *testing.T) {
table := NewTable(4) // Mx4 table
// Default, equal column sizes (4x0.25)...
table.SetColumnWidths(0.5, 0.2, 0.2, 0.1)
2018-06-25 00:30:32 +06:00
cell1 := table.NewCell()
p := NewParagraph("A")
cell1.SetContent(p)
2018-07-06 21:11:34 +06:00
cell1.SetBorder(CellBorderStyleLeft, 1) // border will be on left
cell1.SetBorderLineStyle(draw.LineStyleSolid)
2018-06-12 03:41:33 +06:00
2018-06-09 06:03:40 +06:00
cell2 := table.NewCell()
2018-06-25 00:30:32 +06:00
p = NewParagraph("B")
cell2.SetContent(p)
2018-07-06 21:11:34 +06:00
cell2.SetBorder(CellBorderStyleBox, 1) // border will be around
cell2.SetBorderLineStyle(draw.LineStyleSolid)
2018-06-09 06:03:40 +06:00
2018-07-10 00:51:45 +06:00
table.SkipCells(1)
2018-06-09 06:03:40 +06:00
cell4 := table.NewCell()
2018-06-25 00:30:32 +06:00
p = NewParagraph("D")
cell4.SetContent(p)
2018-07-06 21:11:34 +06:00
cell4.SetBorder(CellBorderStyleBox, 1) // border will be around
cell4.SetBorderLineStyle(draw.LineStyleSolid)
2018-06-09 06:03:40 +06:00
2018-07-10 00:51:45 +06:00
table.SkipCells(1)
2018-06-25 00:30:32 +06:00
cell6 := table.NewCell()
p = NewParagraph("F")
cell6.SetContent(p)
2018-07-06 21:11:34 +06:00
cell6.SetBorder(CellBorderStyleLeft, 1) // border will be on left
cell6.SetBorderLineStyle(draw.LineStyleSolid)
2018-06-25 00:30:32 +06:00
table.SkipCells(1) // Skip over 2,3.
cell7 := table.NewCell()
p = NewParagraph("G")
cell7.SetContent(p)
2018-07-06 21:11:34 +06:00
cell7.SetBorder(CellBorderStyleBox, 1) // border will be around
cell7.SetBorderLineStyle(draw.LineStyleSolid)
2018-06-25 00:30:32 +06:00
// Skip over two rows.
table.SkipRows(2)
cell8 := table.NewCell()
p = NewParagraph("H")
cell8.SetContent(p)
2018-07-06 21:11:34 +06:00
cell8.SetBorder(CellBorderStyleRight, 1) // border will be on right
cell8.SetBorderLineStyle(draw.LineStyleSolid)
2018-06-25 00:30:32 +06:00
2018-06-09 06:03:40 +06:00
c := New()
c.Draw(table)
2018-06-30 00:15:51 +06:00
err := c.WriteToFile("/tmp/4_table_bordered.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
2018-07-21 01:44:26 +06:00
func newContent(text string, alignment TextAlignment, font fonts.Font, fontSize float64, color Color) *Paragraph {
p := NewParagraph(text)
p.SetFontSize(fontSize)
p.SetTextAlignment(alignment)
p.SetFont(font)
2018-07-21 01:44:26 +06:00
p.SetColor(color)
return p
}
func newBillItem(t *Table, no, date, notes, amount, con, retApplied, ret, netBill string) {
billNo := t.NewCell()
2018-07-21 01:44:26 +06:00
billNo.SetContent(newContent(no, TextAlignmentLeft, fonts.NewFontTimesBold(), 8, ColorBlack))
billDate := t.NewCell()
2018-07-21 01:44:26 +06:00
billDate.SetContent(newContent(date, TextAlignmentCenter, fonts.NewFontTimesBold(), 8, ColorBlack))
billNotes := t.NewCell()
2018-07-21 01:44:26 +06:00
billNotes.SetContent(newContent(notes, TextAlignmentLeft, fonts.NewFontTimesBold(), 8, ColorBlack))
billAmount := t.NewCell()
2018-07-21 01:44:26 +06:00
billAmount.SetContent(newContent(amount, TextAlignmentRight, fonts.NewFontTimesBold(), 8, ColorBlack))
billCon := t.NewCell()
2018-07-21 01:44:26 +06:00
billCon.SetContent(newContent(con, TextAlignmentLeft, fonts.NewFontTimesBold(), 8, ColorBlack))
billRetApplied := t.NewCell()
2018-07-21 01:44:26 +06:00
billRetApplied.SetContent(newContent(retApplied, TextAlignmentRight, fonts.NewFontTimesBold(), 8, ColorBlack))
billRet := t.NewCell()
2018-07-21 01:44:26 +06:00
billRet.SetContent(newContent(ret, TextAlignmentLeft, fonts.NewFontTimesBold(), 8, ColorBlack))
billNetBill := t.NewCell()
2018-07-21 01:44:26 +06:00
billNetBill.SetContent(newContent(netBill, TextAlignmentRight, fonts.NewFontTimesBold(), 8, ColorBlack))
}
// Test creating and drawing a table.
func TestCreatorHendricksReq1(t *testing.T) {
table := NewTable(3) // Mx4 table
// Default, equal column sizes (4x0.25)...
table.SetColumnWidths(0.35, 0.30, 0.35)
2018-07-21 01:44:26 +06:00
projectColorOne := ColorBlue
projectColorTwo := ColorRed
companyTitle := table.NewCell()
2018-07-21 01:44:26 +06:00
companyTitle.SetContent(newContent("Hendricks Consulting LLC", TextAlignmentLeft, fonts.NewFontTimesBold(), 12, projectColorOne))
table.SkipCells(1)
pageHeader := table.NewCell()
2018-07-21 01:44:26 +06:00
pageHeader.SetContent(newContent("Billing Schedule by Project", TextAlignmentCenter, fonts.NewFontTimesBold(), 12, ColorBlack))
pageHeader.SetBorder(CellBorderStyleBox, 3)
pageHeader.SetBorderLineStyle(draw.LineStyleSolid)
companyAddress := table.NewCell()
2018-07-21 01:44:26 +06:00
companyAddress.SetContent(newContent("2666 Airport Drive, Apt. 309", TextAlignmentLeft, fonts.NewFontTimesRoman(), 8, ColorBlack))
table.SkipCells(2)
companyLocation := table.NewCell()
2018-07-21 01:44:26 +06:00
companyLocation.SetContent(newContent("Portland, Oregon, 92019", TextAlignmentLeft, fonts.NewFontTimesRoman(), 8, ColorBlack))
table.SkipCells(1)
printingDate := table.NewCell()
2018-07-21 01:44:26 +06:00
printingDate.SetContent(newContent("Printed on: 22/02/2011", TextAlignmentRight, fonts.NewFontTimesRoman(), 8, ColorBlack))
companyTelAndFax := table.NewCell()
2018-07-21 01:44:26 +06:00
companyTelAndFax.SetContent(newContent("Tel: (999) 609-4032 Fax: (999) 999-9922", TextAlignmentLeft, fonts.NewFontTimesRoman(), 8, ColorBlack))
table.SkipCells(1)
pageOf := table.NewCell()
2018-07-21 01:44:26 +06:00
pageOf.SetContent(newContent("Page 10 of 10", TextAlignmentRight, fonts.NewFontTimesRoman(), 8, ColorBlack))
email := table.NewCell()
2018-07-21 01:44:26 +06:00
email.SetContent(newContent("admin@hendricks.com", TextAlignmentLeft, fonts.NewFontTimesRoman(), 8, ColorBlack))
table.SkipCells(2)
website := table.NewCell()
2018-07-21 01:44:26 +06:00
website.SetContent(newContent("www.hendricks.com", TextAlignmentLeft, fonts.NewFontTimesRoman(), 8, ColorBlack))
table2 := NewTable(5)
table2.SetColumnWidths(0.20, 0.20, 0.20, 0.20, 0.20)
table2.SkipCells(5)
projectName := table2.NewCell()
2018-07-21 01:44:26 +06:00
projectName.SetContent(newContent("Project Name (ID):", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, projectColorOne))
projectNameValue := table2.NewCell()
2018-07-21 01:44:26 +06:00
projectNameValue.SetContent(newContent("Biggi Group", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, ColorBlack))
table2.SkipCells(3)
projectID := table2.NewCell()
2018-07-21 01:44:26 +06:00
projectID.SetContent(newContent("Project ID:", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, projectColorOne))
projectIDValue := table2.NewCell()
2018-07-21 01:44:26 +06:00
projectIDValue.SetContent(newContent("BG:01", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, ColorBlack))
table2.SkipCells(1)
contractType := table2.NewCell()
2018-07-21 01:44:26 +06:00
contractType.SetContent(newContent("Contract Type:", TextAlignmentRight, fonts.NewFontTimesBold(), 8, projectColorOne))
contractTypeValue := table2.NewCell()
2018-07-21 01:44:26 +06:00
contractTypeValue.SetContent(newContent("Percentage", TextAlignmentLeft, fonts.NewFontTimesRoman(), 8, ColorBlack))
projectManager := table2.NewCell()
2018-07-21 01:44:26 +06:00
projectManager.SetContent(newContent("Manager:", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, projectColorOne))
projectManagerValue := table2.NewCell()
2018-07-21 01:44:26 +06:00
projectManagerValue.SetContent(newContent("SHH", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, ColorBlack))
table2.SkipCells(1)
contractAmount := table2.NewCell()
2018-07-21 01:44:26 +06:00
contractAmount.SetContent(newContent("Contract Amount:", TextAlignmentRight, fonts.NewFontTimesBold(), 8, projectColorOne))
contractAmountValue := table2.NewCell()
2018-07-21 01:44:26 +06:00
contractAmountValue.SetContent(newContent("$2,975.00", TextAlignmentLeft, fonts.NewFontTimesRoman(), 8, ColorBlack))
clientID := table2.NewCell()
2018-07-21 01:44:26 +06:00
clientID.SetContent(newContent("Client ID:", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, projectColorOne))
clientIDValue := table2.NewCell()
2018-07-21 01:44:26 +06:00
clientIDValue.SetContent(newContent("Baggi ehf", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, ColorBlack))
table2.SkipCells(1)
retainerAmount := table2.NewCell()
2018-07-21 01:44:26 +06:00
retainerAmount.SetContent(newContent("Retainer Amount:", TextAlignmentRight, fonts.NewFontTimesBold(), 8, projectColorOne))
retainerAmountValue := table2.NewCell()
2018-07-21 01:44:26 +06:00
retainerAmountValue.SetContent(newContent("", TextAlignmentLeft, fonts.NewFontTimesRoman(), 8, ColorBlack))
table3 := NewTable(8)
table3.SetColumnWidths(0.05, 0.10, 0.35, 0.10, 0.10, 0.10, 0.10, 0.10)
table3.SkipCells(8)
billNo := table3.NewCell()
2018-07-21 01:44:26 +06:00
billNo.SetContent(newContent("Bill #", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, projectColorOne))
billNo.SetBorder(CellBorderStyleTop, 2)
billNo.SetBorder(CellBorderStyleBottom, 1)
2018-07-21 01:44:26 +06:00
billNo.SetBorderColor(projectColorOne)
billDate := table3.NewCell()
2018-07-21 01:44:26 +06:00
billDate.SetContent(newContent("Date", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, projectColorOne))
billDate.SetBorder(CellBorderStyleTop, 2)
billDate.SetBorder(CellBorderStyleBottom, 1)
2018-07-21 01:44:26 +06:00
billDate.SetBorderColor(projectColorOne)
billNotes := table3.NewCell()
2018-07-21 01:44:26 +06:00
billNotes.SetContent(newContent("Notes", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, projectColorOne))
billNotes.SetBorder(CellBorderStyleTop, 2)
billNotes.SetBorder(CellBorderStyleBottom, 1)
2018-07-21 01:44:26 +06:00
billNotes.SetBorderColor(projectColorOne)
billAmount := table3.NewCell()
2018-07-21 01:44:26 +06:00
billAmount.SetContent(newContent("Bill Amount", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, projectColorOne))
billAmount.SetBorder(CellBorderStyleTop, 2)
billAmount.SetBorder(CellBorderStyleBottom, 1)
2018-07-21 01:44:26 +06:00
billAmount.SetBorderColor(projectColorOne)
billCon := table3.NewCell()
2018-07-21 01:44:26 +06:00
billCon.SetContent(newContent("% Con", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, projectColorOne))
billCon.SetBorder(CellBorderStyleTop, 2)
billCon.SetBorder(CellBorderStyleBottom, 1)
2018-07-21 01:44:26 +06:00
billCon.SetBorderColor(projectColorOne)
billRetApplied := table3.NewCell()
2018-07-21 01:44:26 +06:00
billRetApplied.SetContent(newContent("Ret Applied", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, projectColorOne))
billRetApplied.SetBorder(CellBorderStyleTop, 2)
billRetApplied.SetBorder(CellBorderStyleBottom, 1)
2018-07-21 01:44:26 +06:00
billRetApplied.SetBorderColor(projectColorOne)
billRet := table3.NewCell()
2018-07-21 01:44:26 +06:00
billRet.SetContent(newContent("% Ret", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, projectColorOne))
billRet.SetBorder(CellBorderStyleTop, 2)
billRet.SetBorder(CellBorderStyleBottom, 1)
2018-07-21 01:44:26 +06:00
billRet.SetBorderColor(projectColorOne)
billNetBill := table3.NewCell()
2018-07-21 01:44:26 +06:00
billNetBill.SetContent(newContent("Net Bill Amt", TextAlignmentLeft, fonts.NewFontTimesBold(), 8, projectColorOne))
billNetBill.SetBorder(CellBorderStyleTop, 2)
billNetBill.SetBorder(CellBorderStyleBottom, 1)
2018-07-21 01:44:26 +06:00
billNetBill.SetBorderColor(projectColorOne)
newBillItem(table3, "1", "1/2/2012", "", "$297.50", "", "$0.00", "", "$297.50")
newBillItem(table3, "2", "1/2/2012", "", "$595.00", "", "$0.00", "", "$595.00")
newBillItem(table3, "3", "1/3/2012", "", "$446.25", "", "$0.00", "", "$446.25")
newBillItem(table3, "4", "1/4/2012", "", "$595.00", "", "$0.00", "", "$595.00")
newBillItem(table3, "5", "1/5/2012", "", "$446.25", "", "$0.00", "", "$446.25")
newBillItem(table3, "6", "1/6/2012", "", "$892.50", "", "$0.00", "", "$892.50")
table3.SkipCells(2 + 8)
totalBill := table3.NewCell()
2018-07-21 01:44:26 +06:00
totalBill.SetContent(newContent("Total: ", TextAlignmentRight, fonts.NewFontTimesBold(), 8, projectColorTwo))
totalBillAmount := table3.NewCell()
2018-07-21 01:44:26 +06:00
totalBillAmount.SetContent(newContent("$3,272.50", TextAlignmentRight, fonts.NewFontTimesBold(), 8, projectColorTwo))
totalBillAmount.SetBorder(CellBorderStyleDoubleTop, 1)
totalBillAmount.SetBorder(CellBorderStyleBottom, 1)
table3.SkipCells(1)
totalRetAmount := table3.NewCell()
2018-07-21 01:44:26 +06:00
totalRetAmount.SetContent(newContent("$0.00", TextAlignmentRight, fonts.NewFontTimesBold(), 8, projectColorTwo))
totalRetAmount.SetBorder(CellBorderStyleDoubleTop, 1)
totalRetAmount.SetBorder(CellBorderStyleBottom, 1)
table3.SkipCells(1)
totalNetAmount := table3.NewCell()
2018-07-21 01:44:26 +06:00
totalNetAmount.SetContent(newContent("$3,272.50", TextAlignmentRight, fonts.NewFontTimesBold(), 8, projectColorTwo))
totalNetAmount.SetBorder(CellBorderStyleDoubleTop, 1)
totalNetAmount.SetBorder(CellBorderStyleBottom, 1)
2018-07-23 22:40:58 +06:00
totalNetAmount.SetBorderLineStyle(draw.LineStyleDashed)
c := New()
c.Draw(table)
c.Draw(table2)
c.Draw(table3)
2018-07-21 21:02:55 +06:00
err := c.WriteToFile("/tmp/hendricks.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
2017-07-14 17:46:01 +00:00
func TestTableInSubchapter(t *testing.T) {
c := New()
fontRegular := fonts.NewFontHelvetica()
fontBold := fonts.NewFontHelveticaBold()
ch := c.NewChapter("Document control")
ch.SetMargins(0, 0, 40, 0)
ch.GetHeading().SetFont(fontRegular)
ch.GetHeading().SetFontSize(18)
2017-07-14 21:58:16 +00:00
ch.GetHeading().SetColor(ColorRGBFrom8bit(72, 86, 95))
2017-07-14 17:46:01 +00:00
sc := c.NewSubchapter(ch, "Issuer details")
sc.SetMargins(0, 0, 5, 0)
sc.GetHeading().SetFont(fontRegular)
sc.GetHeading().SetFontSize(18)
2017-07-14 21:58:16 +00:00
sc.GetHeading().SetColor(ColorRGBFrom8bit(72, 86, 95))
2017-07-14 17:46:01 +00:00
issuerTable := NewTable(2)
p := NewParagraph("Non-Disclosure")
2017-07-14 17:46:01 +00:00
p.SetFont(fontBold)
p.SetFontSize(10)
p.SetColor(ColorWhite)
2017-07-14 17:46:01 +00:00
cell := issuerTable.NewCell()
cell.SetContent(p)
cell.SetBackgroundColor(ColorBlack)
cell.SetBorder(CellBorderStyleBox, 1.0)
cell.SetIndent(5)
2017-07-14 17:46:01 +00:00
p = NewParagraph("Company Inc.")
p.SetFont(fontRegular)
p.SetFontSize(10)
p.SetColor(ColorGreen)
cell = issuerTable.NewCell()
cell.SetContent(p)
cell.SetBackgroundColor(ColorRed)
cell.SetBorder(CellBorderStyleBox, 1.0)
cell.SetIndent(5)
p = NewParagraph("Belongs to")
p.SetFont(fontBold)
p.SetFontSize(10)
p.SetColor(ColorWhite)
cell = issuerTable.NewCell()
cell.SetContent(p)
cell.SetBackgroundColor(ColorBlack)
cell.SetBorder(CellBorderStyleBox, 1.0)
cell.SetIndent(5)
p = NewParagraph("Bezt business bureu")
p.SetFont(fontRegular)
p.SetFontSize(10)
p.SetColor(ColorGreen)
2017-07-14 17:46:01 +00:00
cell = issuerTable.NewCell()
cell.SetContent(p)
cell.SetBackgroundColor(ColorRed)
cell.SetBorder(CellBorderStyleBox, 1.0)
cell.SetIndent(5)
cell.SetHorizontalAlignment(CellHorizontalAlignmentCenter)
//cell.SetVerticalAlignment(CellVerticalAlignmentMiddle)
2017-07-14 17:46:01 +00:00
issuerTable.SetMargins(5, 5, 10, 10)
2017-07-14 17:46:01 +00:00
ch.Add(issuerTable)
sc = c.NewSubchapter(ch, "My Statement")
//sc.SetMargins(0, 0, 5, 0)
2017-07-14 17:46:01 +00:00
sc.GetHeading().SetFont(fontRegular)
sc.GetHeading().SetFontSize(18)
2017-07-14 21:58:16 +00:00
sc.GetHeading().SetColor(ColorRGBFrom8bit(72, 86, 95))
2017-07-14 17:46:01 +00:00
myText := "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt " +
"ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " +
"aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore " +
"eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt " +
"mollit anim id est laborum."
myPara := NewParagraph(myText)
myPara.SetFont(fontRegular)
myPara.SetFontSize(10)
2017-07-14 21:58:16 +00:00
myPara.SetColor(ColorRGBFrom8bit(72, 86, 95))
2017-07-14 17:46:01 +00:00
myPara.SetTextAlignment(TextAlignmentJustify)
myPara.SetLineHeight(1.5)
sc.Add(myPara)
err := c.Draw(ch)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
err = c.WriteToFile("/tmp/4_tables_in_subchap.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Add headers and footers via creator.
2017-07-07 15:37:50 +00:00
func addHeadersAndFooters(c *Creator) {
c.DrawHeader(func(header *Block, args HeaderFunctionArgs) {
2017-07-07 15:37:50 +00:00
/*
if pageNum == 1 {
// Skip on front Page.
return
}
*/
// Add Page number
p := NewParagraph(fmt.Sprintf("Page %d / %d", args.PageNum, args.TotalPages))
p.SetPos(0.8*header.Width(), 20)
header.Draw(p)
2017-07-07 15:37:50 +00:00
// Draw on the template...
img, err := NewImageFromFile(testImageFile1)
if err != nil {
fmt.Printf("ERROR : %v\n", err)
}
img.ScaleToHeight(0.4 * c.pageMargins.top)
img.SetPos(20, 10)
header.Draw(img)
2017-07-07 15:37:50 +00:00
})
c.DrawFooter(func(footer *Block, args FooterFunctionArgs) {
2017-07-07 15:37:50 +00:00
/*
if pageNum == 1 {
// Skip on front Page.
return
}
*/
// Add company name.
companyName := "Company inc."
p := NewParagraph(companyName)
p.SetPos(0.1*footer.Width(), 10)
footer.Draw(p)
2017-07-07 15:37:50 +00:00
p = NewParagraph("July 2017")
p.SetPos(0.8*footer.Width(), 10)
footer.Draw(p)
2017-07-07 15:37:50 +00:00
})
}
// Test creating headers and footers.
2017-07-07 15:37:50 +00:00
func TestHeadersAndFooters(t *testing.T) {
c := New()
ch1 := c.NewChapter("Introduction")
p := NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt " +
"ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " +
"aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore " +
"eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt " +
"mollit anim id est laborum.")
p.SetMargins(0, 0, 10, 0)
for j := 0; j < 55; j++ {
ch1.Add(p) // Can add any drawable..
}
c.Draw(ch1)
// Make unidoc headers and footers.
addHeadersAndFooters(c)
err := c.WriteToFile("/tmp/4_headers.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
func makeQrCodeImage(text string, width float64, oversampling int) (goimage.Image, error) {
qrCode, err := qr.Encode(text, qr.M, qr.Auto)
if err != nil {
return nil, err
}
pixelWidth := oversampling * int(math.Ceil(width))
2017-07-07 15:37:50 +00:00
qrCode, err = barcode.Scale(qrCode, pixelWidth, pixelWidth)
if err != nil {
return nil, err
}
return qrCode, nil
}
func TestQRCodeOnNewPage(t *testing.T) {
creator := New()
qrCode, err := makeQrCodeImage("HELLO", 40, 5)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
img, err := NewImageFromGoImage(qrCode)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
// Sets positioning to absolute coordinates.
img.SetWidth(40)
img.SetHeight(40)
for i := 0; i < 5; i++ {
img.SetPos(100.0*float64(i), 100.0*float64(i))
creator.Draw(img)
}
creator.WriteToFile("/tmp/3_barcode_qr_newpage.pdf")
}
// Example of using a template Page, generating and applying QR
func TestQRCodeOnTemplate(t *testing.T) {
pages, err := loadPagesFromFile(testPdfTemplatesFile1)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
if len(pages) < 2 {
t.Errorf("Fail: %v\n", err)
return
}
// Load Page 1 as template.
tpl, err := NewBlockFromPage(pages[1])
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
tpl.SetPos(0, 0)
// Generate QR code.
qrCode, err := makeQrCodeImage("HELLO", 50, 5)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
// Prepare content image.
image, err := NewImageFromGoImage(qrCode)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
image.SetWidth(50)
image.SetHeight(50)
image.SetPos(480, 100)
tpl.Draw(image)
creator := New()
creator.NewPage()
creator.Draw(tpl)
// Add another Page where the template has been rotated.
creator.NewPage()
tpl.SetAngle(90)
tpl.SetPos(-50, 750)
creator.Draw(tpl)
// Add another Page where the template is rotated 90 degrees.
loremPages, err := loadPagesFromFile(testPdfLoremIpsumFile)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
if len(loremPages) != 1 {
t.Errorf("Pages != 1")
return
}
// Add another Page where another Page is embedded on the Page. The other Page is scaled and shifted to fit
// on the right of the template.
loremTpl, err := NewBlockFromPage(loremPages[0])
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
loremTpl.ScaleToWidth(0.8 * creator.Width())
loremTpl.SetPos(100, 100)
creator.Draw(loremTpl)
// Write the example to file.
creator.WriteToFile("/tmp/4_barcode_on_tpl.pdf")
}
// Test adding encryption to output.
func TestEncrypting1(t *testing.T) {
c := New()
ch1 := c.NewChapter("Introduction")
p := NewParagraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt " +
"ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " +
"aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore " +
"eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt " +
"mollit anim id est laborum.")
p.SetMargins(0, 0, 10, 0)
for j := 0; j < 55; j++ {
ch1.Add(p) // Can add any drawable..
}
c.Draw(ch1)
c.SetPdfWriterAccessFunc(func(w *model.PdfWriter) error {
userPass := []byte("password")
ownerPass := []byte("password")
err := w.Encrypt(userPass, ownerPass, nil)
return err
})
err := c.WriteToFile("/tmp/6_chapters_encrypted_password.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}