diff --git a/gopdf.go b/gopdf.go index 6e3364b..5d177fa 100644 --- a/gopdf.go +++ b/gopdf.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "compress/zlib" // for constants + "errors" "fmt" "image" "image/jpeg" @@ -16,8 +17,6 @@ import ( "strings" "time" - "errors" - "github.com/phpdave11/gofpdi" ) @@ -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 @@ -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 diff --git a/gopdf_test.go b/gopdf_test.go index 2142fc9..2d0ad5b 100644 --- a/gopdf_test.go +++ b/gopdf_test.go @@ -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 + } +} diff --git a/table.go b/table.go index a0abd71..1135e07 100644 --- a/table.go +++ b/table.go @@ -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