Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import all pages from existing pdf file, Fix table border corners and Set current page method #310

Merged
merged 5 commits into from
Oct 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 87 additions & 2 deletions gopdf.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bufio"
"bytes"
"compress/zlib" // for constants
"errors"
"fmt"
"image"
"image/jpeg"
Expand All @@ -16,8 +17,6 @@ import (
"strings"
"time"

"errors"

"github.com/phpdave11/gofpdi"
)

Expand Down Expand Up @@ -1575,6 +1574,75 @@ func (gp *GoPdf) UseImportedTemplate(tplid int, x float64, y float64, w float64,
gp.getContent().AppendStreamImportedTemplate(tplName, scaleX, scaleY, tX, tY)
}

// ImportPagesFromSource imports pages from a source pdf.
// The source can be a file path, byte slice, or (*)io.ReadSeeker.
func (gp *GoPdf) ImportPagesFromSource(source interface{}, box string) error {
switch v := source.(type) {
case string:
// Set source file for fpdi
gp.fpdi.SetSourceFile(v)
case []byte:
// Set source stream for fpdi
rs := io.ReadSeeker(bytes.NewReader(v))
gp.fpdi.SetSourceStream(&rs)
case io.ReadSeeker:
// Set source stream for fpdi
gp.fpdi.SetSourceStream(&v)
case *io.ReadSeeker:
// Set source stream for fpdi
gp.fpdi.SetSourceStream(v)
default:
return errors.New("source type not supported")
}

// Get number of pages from source file
pages := gp.fpdi.GetNumPages()

// Get page sizes from source file
sizes := gp.fpdi.GetPageSizes()

for i := 0; i < pages; i++ {
pageno := i + 1

// Get the size of the page
size, ok := sizes[pageno][box]
if !ok {
return errors.New("can not get page size")
}

// Add a new page to the document
gp.AddPage()

// gofpdi needs to know where to start the object id at.
// By default, it starts at 1, but gopdf adds a few objects initially.
startObjID := gp.GetNextObjectID()

// Set gofpdi next object ID to whatever the value of startObjID is
gp.fpdi.SetNextObjectID(startObjID)

// Import page
tpl := gp.fpdi.ImportPage(pageno, box)

// Import objects into current pdf document
tplObjIDs := gp.fpdi.PutFormXobjects()

// Set template names and ids in gopdf
gp.ImportTemplates(tplObjIDs)

// Get a map[int]string of the imported objects.
// The map keys will be the ID of each object.
imported := gp.fpdi.GetImportedObjects()

// Import gofpdi objects into gopdf, starting at whatever the value of startObjID is
gp.ImportObjects(imported, startObjID)

// Draws the imported template on the current page
gp.UseImportedTemplate(tpl, 0, 0, size["w"], size["h"])
}

return nil
}

// GetNextObjectID gets the next object ID so that gofpdi knows where to start the object IDs.
func (gp *GoPdf) GetNextObjectID() int {
return len(gp.pdfObjs) + 1
Expand Down Expand Up @@ -2343,4 +2411,21 @@ func (gp *GoPdf) IsCurrFontContainGlyph(r rune) (bool, error) {
return true, nil
}

// SetPage set current page
func (gp *GoPdf) SetPage(pageno int) error {
var pageIndex int
for i := 0; i < len(gp.pdfObjs); i++ {
switch gp.pdfObjs[i].(type) {
case *ContentObj:
pageIndex += 1
if pageIndex == pageno {
gp.indexOfContent = i
return nil
}
}
}

return errors.New("invalid page number")
}

//tool for validate pdf https://www.pdf-online.com/osa/validate.aspx
64 changes: 64 additions & 0 deletions gopdf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -802,3 +802,67 @@ func setupDefaultA4PDF(t *testing.T) *GoPdf {
}
return &pdf
}

func TestImportPagesFromFile(t *testing.T) {
err := os.MkdirAll("./test/out", 0777)
if err != nil {
t.Error(err)
return
}

pdf := GoPdf{}
pdf.Start(Config{PageSize: *PageSizeA4})

err = pdf.ImportPagesFromSource("./examples/outline_example/outline_demo.pdf", "/MediaBox")
if err != nil {
t.Error(err)
return
}

err = pdf.AddTTFFont("LiberationSerif-Regular", "./test/res/LiberationSerif-Regular.ttf")
if err != nil {
t.Error(err)
return
}
err = pdf.SetFont("LiberationSerif-Regular", "", 14)

err = pdf.SetPage(1)
if err != nil {
t.Error(err)
return
}
pdf.SetXY(350, 50)
err = pdf.Cell(&Rect{W: 20, H: 30}, "Hello World")
if err != nil {
t.Error(err)
return
}
err = pdf.SetPage(2)
if err != nil {
t.Error(err)
return
}
pdf.SetXY(350, 50)
err = pdf.Cell(&Rect{W: 20, H: 30}, "Hello World")
if err != nil {
t.Error(err)
return
}
err = pdf.SetPage(3)
if err != nil {
t.Error(err)
return
}
pdf.SetXY(350, 50)
err = pdf.Cell(&Rect{W: 20, H: 30}, "Hello World")
if err != nil {
t.Error(err)
return
}

err = pdf.WritePdf("./test/out/open-existing-pdf.pdf")
if err != nil {
t.Error(err)
return
}
}
9 changes: 5 additions & 4 deletions table.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,19 +240,20 @@ func (t *tableLayout) drawCell(x, y, width, height float64, content, align strin
func (t *tableLayout) drawBorder(x1, y1, x2, y2 float64, borderStyle BorderStyle) error {
t.pdf.SetLineWidth(borderStyle.Width)
t.pdf.SetStrokeColor(borderStyle.RGBColor.R, borderStyle.RGBColor.G, borderStyle.RGBColor.B)
half := borderStyle.Width / 2

// Draw each side of the border if specified
if borderStyle.Top {
t.pdf.Line(x1, y1, x2, y1)
t.pdf.Line(x1-half, y1, x2+half, y1)
}
if borderStyle.Bottom {
t.pdf.Line(x1, y2, x2, y2)
t.pdf.Line(x1-half, y2, x2+half, y2)
}
if borderStyle.Left {
t.pdf.Line(x1, y1, x1, y2)
t.pdf.Line(x1, y1-half, x1, y2+half)
}
if borderStyle.Right {
t.pdf.Line(x2, y1, x2, y2)
t.pdf.Line(x2, y1-half, x2, y2+half)
}

return nil
Expand Down
Loading