unipdf/pdf/creator/creator_test.go

1528 lines
41 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"
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"
const testWts11TTFFile = "../../testfiles/wts11.ttf"
const testFreeSansTTFFile = "../../testfiles/FreeSans.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
}
}
// Test paragraph with Chinese characters.
func TestParagraphChinese(t *testing.T) {
creator := New()
lines := []string{
"你好",
"你好你好你好你好",
"河上白云",
}
for _, line := range lines {
p := NewParagraph(line)
font, err := model.NewCompositePdfFontFromTTFFile(testWts11TTFFile)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
p.SetFont(font)
err = creator.Draw(p)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
err := creator.WriteToFile("/tmp/2_p_nihao.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
// Test paragraph with composite font and various unicode characters.
func TestParagraphUnicode(t *testing.T) {
creator := New()
font, err := model.NewCompositePdfFontFromTTFFile(testFreeSansTTFFile)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
texts := []string{
"Testing of letters \u010c,\u0106,\u0160,\u017d,\u0110",
"Vous \u00eates d'o\u00f9?",
"\u00c0 tout \u00e0 l'heure. \u00c0 bient\u00f4t.",
"Je me pr\u00e9sente.",
"C'est un \u00e9tudiant.",
"\u00c7a va?",
"Il est ing\u00e9nieur. Elle est m\u00e9decin.",
"C'est une fen\u00eatre.",
"R\u00e9p\u00e9tez, s'il vous pla\u00eet.",
"Odkud jste?",
"Uvid\u00edme se za chvilku. M\u011bj se.",
"Dovolte, abych se p\u0159edstavil.",
"To je studentka.",
"V\u0161echno v po\u0159\u00e1dku?",
"On je in\u017een\u00fdr. Ona je l\u00e9ka\u0159.",
"Toto je okno.",
"Zopakujte to pros\u00edm.",
"\u041e\u0442\u043a\u0443\u0434\u0430 \u0442\u044b?",
"\u0423\u0432\u0438\u0434\u0438\u043c\u0441\u044f \u0432 \u043d\u0435\u043c\u043d\u043e\u0433\u043e. \u0423\u0432\u0438\u0434\u0438\u043c\u0441\u044f.",
"\u041f\u043e\u0437\u0432\u043e\u043b\u044c\u0442\u0435 \u043c\u043d\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c\u0441\u044f.",
"\u042d\u0442\u043e \u0441\u0442\u0443\u0434\u0435\u043d\u0442.",
"\u0425\u043e\u0440\u043e\u0448\u043e?",
"\u041e\u043d \u0438\u043d\u0436\u0435\u043d\u0435\u0440. \u041e\u043d\u0430 \u0434\u043e\u043a\u0442\u043e\u0440.",
"\u042d\u0442\u043e \u043e\u043a\u043d\u043e.",
"\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430.",
`Lorem Ipsum - это текст-"рыба", часто используемый в печати и вэб-дизайне. Lorem Ipsum является стандартной "рыбой" для текстов на латинице с начала XVI века. В то время некий безымянный печатник создал большую коллекцию размеров и форм шрифтов, используя Lorem Ipsum для распечатки образцов. Lorem Ipsum не только успешно пережил без заметных изменений пять веков, но и перешагнул в электронный дизайн. Его популяризации в новое время послужили публикация листов Letraset с образцами Lorem Ipsum в 60-х годах и, в более недавнее время, программы электронной вёрстки типа Aldus PageMaker, в шаблонах которых используется Lorem Ipsum.`,
}
for _, text := range texts {
fmt.Printf("Text: %s\n", text)
p := NewParagraph(text)
p.SetFont(font)
err = creator.Draw(p)
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
err = creator.WriteToFile("/tmp/2_p_multi.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)
err := c.WriteToFile("/tmp/4_table.pdf")
if err != nil {
t.Errorf("Fail: %v\n", err)
return
}
}
2018-07-18 00:03:18 +00:00
func TestTableCellWrapping(t *testing.T) {
c := New()
c.NewPage()
table := NewTable(4) // Mx4 table
// Default, equal column sizes (4x0.25)...
table.SetColumnWidths(0.5, 0.2, 0.2, 0.1)
cell := table.NewCell()
p := NewParagraph("A 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.")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
p.SetEnableWrap(true)
p.SetWidth(cell.Width(c.Context()))
p.SetTextAlignment(TextAlignmentJustify)
cell = table.NewCell()
cell.SetBorder(CellBorderStyleBox, 1)
p = NewParagraph("B 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.")
p.SetEnableWrap(true)
p.SetTextAlignment(TextAlignmentRight)
cell.SetContent(p)
cell = table.NewCell()
p = NewParagraph("C 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.")
2018-07-18 11:24:24 +00:00
p.SetEnableWrap(true)
2018-07-18 00:03:18 +00:00
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("1,4")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("2,1")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("2,2")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("2,2")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
//table.SkipCells(1) // Skip over 2,3.
cell = table.NewCell()
cell.SetBorder(CellBorderStyleBox, 1)
//p = NewParagraph("D 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 = NewParagraph("X")
p.SetEnableWrap(true)
cell.SetContent(p)
// Skip over two rows.
table.SkipRows(2)
cell = table.NewCell()
cell.SetBorder(CellBorderStyleBox, 1)
p = NewParagraph("4,4")
cell.SetContent(p)
// 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))
2018-07-18 11:24:24 +00:00
table.SkipRows(1)
cell = table.NewCell()
cell.SetBorder(CellBorderStyleBox, 1)
2018-07-18 11:27:11 +00:00
p = NewParagraph("This is\nnewline\nwrapped\n\nmulti")
2018-07-18 11:24:24 +00:00
p.SetEnableWrap(true)
cell.SetContent(p)
2018-07-18 00:03:18 +00:00
2018-07-18 11:24:24 +00:00
err := c.Draw(table)
2018-07-18 00:03:18 +00:00
if err != nil {
2018-07-18 11:24:24 +00:00
t.Fatalf("Error drawing: %v", err)
}
err = c.WriteToFile("/tmp/tablecell_wrap.pdf")
if err != nil {
t.Fatalf("Fail: %v\n", err)
2018-07-18 00:03:18 +00:00
}
}
// Test creating and drawing a table.
func TestBorderedTable(t *testing.T) {
table := NewTable(4) // Mx4 table
// Default, equal column sizes (4x0.25)...
table.SetColumnWidths(0.5, 0.2, 0.2, 0.1)
cell := table.NewCell()
p := NewParagraph("1,1")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("1,2")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("1,3")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("1,4")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("2,1")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
cell = table.NewCell()
p = NewParagraph("2,2")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
table.SkipCells(1) // Skip over 2,3.
cell = table.NewCell()
p = NewParagraph("2,4")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
// Skip over two rows.
table.SkipRows(2)
cell = table.NewCell()
p = NewParagraph("4,4")
cell.SetContent(p)
cell.SetBorder(CellBorderStyleBox, 1)
// 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))
cell.SetBorder(CellBorderStyleBox, 1)
c := New()
c.Draw(table)
err := c.WriteToFile("/tmp/4_table_bordered.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
}
}