From 2a72ef83c31c943506a04d645d8b6049defe7760 Mon Sep 17 00:00:00 2001 From: Adrian-George Bostan Date: Thu, 1 Aug 2019 00:58:14 +0300 Subject: [PATCH] Creator optimize drawing blocks (#136) * Merge blocks and draw to page once * Adapt stream compression test case * Preserve original behavior of the raw stream compression test case --- creator/creator.go | 28 +++++++++++++++++++++++----- creator/creator_test.go | 24 ++++++++++++++++-------- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/creator/creator.go b/creator/creator.go index 150b0636..c5bb1547 100644 --- a/creator/creator.go +++ b/creator/creator.go @@ -20,6 +20,8 @@ import ( // content onto imported PDF pages, etc. type Creator struct { pages []*model.PdfPage + pageBlocks map[*model.PdfPage]*Block + activePage *model.PdfPage pagesize PageSize @@ -116,6 +118,7 @@ type margins struct { func New() *Creator { c := &Creator{} c.pages = []*model.PdfPage{} + c.pageBlocks = map[*model.PdfPage]*Block{} c.SetPageSize(PageSizeLetter) m := 0.1 * c.pageWidth @@ -513,6 +516,15 @@ func (c *Creator) finalize() error { return err } } + + // Draw blocks to pages. + block, ok := c.pageBlocks[page] + if !ok { + return errors.New("could not find page block") + } + if err := block.drawToPage(page); err != nil { + return err + } } c.finalized = true @@ -559,15 +571,21 @@ func (c *Creator) Draw(d Drawable) error { return err } - for idx, blk := range blocks { + for idx, block := range blocks { if idx > 0 { c.NewPage() } - p := c.getActivePage() - err := blk.drawToPage(p) - if err != nil { - return err + page := c.getActivePage() + if pageBlock, ok := c.pageBlocks[page]; ok { + if err := pageBlock.mergeBlocks(block); err != nil { + return err + } + if err := mergeResources(block.resources, pageBlock.resources); err != nil { + return err + } + } else { + c.pageBlocks[page] = block } } diff --git a/creator/creator_test.go b/creator/creator_test.go index 677f5df2..e26600fd 100644 --- a/creator/creator_test.go +++ b/creator/creator_test.go @@ -2740,11 +2740,17 @@ func TestCompressStreams(t *testing.T) { c.Draw(p) //c.NewPage() - page := c.pages[0] - // Need to add Arial to the page resources to avoid generating invalid PDF (avoid build fail). - times := model.NewStandard14FontMustCompile(model.TimesRomanName) - page.Resources.SetFontByName("Times", times.ToPdfObject()) - rawContent := ` + c.SetPdfWriterAccessFunc(func(w *model.PdfWriter) error { + page := c.pages[0] + + // Need to add Times to the page resources as it is used in the raw content stream. + times, err := model.NewStandard14Font(model.TimesRomanName) + if err != nil { + return err + } + page.Resources.SetFontByName("Times", times.ToPdfObject()) + + rawContent := ` BT /Times 56 Tf 20 600 Td @@ -2762,15 +2768,17 @@ BT (example text)' ET ` - { + cstreams, err := page.GetContentStreams() if err != nil { - panic(err) + return err } cstreams = append(cstreams, rawContent) + // Set streams with raw encoder (not encoded). page.SetContentStreams(cstreams, core.NewRawEncoder()) - } + return nil + }) return c }