@@ -42,8 +42,28 @@ type TableHeader struct {
4242 RTL bool
4343}
4444
45- func (th * TableHeader ) validate (pdf * PDF , cols int ) error {
45+ func (th * TableHeader ) validateColumnPaddings (cols int ) error {
46+ if len (th .ColPaddings ) == 0 {
47+ return nil
48+ }
49+
50+ if len (th .ColPaddings ) != cols {
51+ return errors .New ("pdfcpu: table header colPaddings must be specified for each column." )
52+ }
53+
54+ for i , p := range th .ColPaddings {
55+ if p == nil {
56+ continue
57+ }
58+ if err := p .validate (); err != nil {
59+ return errors .Errorf ("%s on table header colPaddings index %d" , err .Error (), i )
60+ }
61+ }
4662
63+ return nil
64+ }
65+
66+ func (th * TableHeader ) validate (pdf * PDF , cols int ) error {
4767 if th .Values == nil || len (th .Values ) != cols {
4868 return errors .Errorf ("pdfcpu: wants %d table header values" , cols )
4969 }
@@ -62,18 +82,8 @@ func (th *TableHeader) validate(pdf *PDF, cols int) error {
6282 }
6383 }
6484
65- if len (th .ColPaddings ) > 0 {
66- if len (th .ColPaddings ) != cols {
67- return errors .New ("pdfcpu: table header colPaddings must be specified for each column." )
68- }
69- for i , p := range th .ColPaddings {
70- if p == nil {
71- continue
72- }
73- if err := p .validate (); err != nil {
74- return errors .Errorf ("%s on table header colPaddings index %d" , err .Error (), i )
75- }
76- }
85+ if err := th .validateColumnPaddings (cols ); err != nil {
86+ return err
7787 }
7888
7989 if th .Font != nil {
@@ -93,6 +103,31 @@ func (th *TableHeader) validate(pdf *PDF, cols int) error {
93103 return nil
94104}
95105
106+ func applyTextDescriptorPadding (td * model.TextDescriptor , p * Padding ) {
107+ if p == nil {
108+ return
109+ }
110+
111+ if p .Width > 0 {
112+ td .MTop = p .Width
113+ td .MRight = p .Width
114+ td .MBot = p .Width
115+ td .MLeft = p .Width
116+ return
117+ }
118+
119+ td .MTop = p .Top
120+ td .MRight = p .Right
121+ td .MBot = p .Bottom
122+ td .MLeft = p .Left
123+ }
124+
125+ func (th * TableHeader ) calcColumnPadding (td * model.TextDescriptor , col int ) {
126+ if len (th .ColPaddings ) > 0 && th .ColPaddings [col ] != nil {
127+ applyTextDescriptorPadding (td , th .ColPaddings [col ])
128+ }
129+ }
130+
96131// Table represents a positioned fillable data grid including a header row.
97132type Table struct {
98133 pdf * PDF
@@ -209,6 +244,16 @@ func (t *Table) validateColPaddings() error {
209244 return nil
210245}
211246
247+ func (t * Table ) validateColumns () error {
248+ if err := t .validateColWidths (); err != nil {
249+ return err
250+ }
251+ if err := t .validateColAnchors (); err != nil {
252+ return err
253+ }
254+ return t .validateColPaddings ()
255+ }
256+
212257func (t * Table ) validateValues () error {
213258 if t .Values != nil {
214259 if len (t .Values ) > t .Rows {
@@ -334,15 +379,7 @@ func (t *Table) validate() error {
334379 }
335380 }
336381
337- if err := t .validateColWidths (); err != nil {
338- return err
339- }
340-
341- if err := t .validateColAnchors (); err != nil {
342- return err
343- }
344-
345- if err := t .validateColPaddings (); err != nil {
382+ if err := t .validateColumns (); err != nil {
346383 return err
347384 }
348385
@@ -640,15 +677,17 @@ func (t *Table) renderBackground(p *model.Page, bWidth float64, r *types.Rectang
640677func (t * Table ) prepareColWidths (bWidth float64 ) []float64 {
641678 colWidths := make ([]float64 , t .Cols )
642679 w := t .Width - 2 * bWidth
680+
643681 if len (t .ColWidths ) > 0 {
644682 for i := 0 ; i < t .Cols ; i ++ {
645683 colWidths [i ] = float64 (t .ColWidths [i ]) / 100 * w
646684 }
647- } else {
648- colw := w / float64 (t .Cols )
649- for i := 0 ; i < t .Cols ; i ++ {
650- colWidths [i ] = colw
651- }
685+ return colWidths
686+ }
687+
688+ colw := w / float64 (t .Cols )
689+ for i := 0 ; i < t .Cols ; i ++ {
690+ colWidths [i ] = colw
652691 }
653692 return colWidths
654693}
@@ -669,54 +708,44 @@ func (t *Table) renderGrid(p *model.Page, colWidths []float64, bWidth float64, b
669708 y := r .LL .Y + bWidth / 2
670709 for i := 1 ; i < maxRows ; i ++ {
671710 y += float64 (t .LineHeight )
672- //y := r.LL.Y + bWidth/2 + float64(i*t.LineHeight)
673711 draw .DrawLine (p .Buf , r .LL .X , y , r .UR .X , y , 0 , bCol , nil )
674712 }
675713}
676714
677715func (t * Table ) prepareTextDescriptor () (model.TextDescriptor , error ) {
678716 td := model.TextDescriptor {
679- Scale : 1. ,
680- ScaleAbs : true ,
681- // ShowTextBB: true ,
682- // ShowBorder: true ,
717+ Scale : 1. ,
718+ ScaleAbs : true ,
719+ ShowTextBB : false ,
720+ ShowBorder : false ,
683721 //ShowBackground: true,
684722 //BackgroundCol: pdfcpu.White,
685723 }
686724
687- return t .applyTextDescriptorPadding (td , t .Padding )
725+ applyTextDescriptorPadding (& td , t .Padding )
726+
727+ return td , nil
688728}
689729
690- func (t * Table ) applyTextDescriptorPadding (td model.TextDescriptor , padding * Padding ) (model.TextDescriptor , error ) {
691- if padding != nil {
692- p := padding
693- if p .Name != "" && p .Name [0 ] == '$' {
694- // use named padding
695- pName := p .Name [1 :]
696- p0 := t .padding (pName )
697- if p0 == nil {
698- return td , errors .Errorf ("pdfcpu: unknown named padding %s" , pName )
699- }
700- p .mergeIn (p0 )
701- }
702-
703- if p .Width > 0 {
704- td .MTop = p .Width
705- td .MRight = p .Width
706- td .MBot = p .Width
707- td .MLeft = p .Width
708- } else {
709- td .MTop = p .Top
710- td .MRight = p .Right
711- td .MBot = p .Bottom
712- td .MLeft = p .Left
730+ func (t * Table ) calcTextDescriptorPadding (td * model.TextDescriptor , p * Padding ) error {
731+ if p .Name != "" && p .Name [0 ] == '$' {
732+ // use named padding
733+ pName := p .Name [1 :]
734+ p0 := t .padding (pName )
735+ if p0 == nil {
736+ return errors .Errorf ("pdfcpu: unknown named padding %s" , pName )
713737 }
738+ p .mergeIn (p0 )
714739 }
715- return td , nil
740+
741+ applyTextDescriptorPadding (td , p )
742+
743+ return nil
716744}
717745
718746func (t * Table ) renderValues (p * model.Page , pageNr int , fonts model.FontMap , colWidths []float64 , td model.TextDescriptor , ll func (row , col int ) (float64 , float64 )) error {
719747 pdf := t .pdf
748+
720749 f := t .Font
721750 id , err := pdf .idForFontName (f .Name , f .Lang , p .Fm , fonts , pageNr )
722751 if err != nil {
@@ -732,35 +761,45 @@ func (t *Table) renderValues(p *model.Page, pageNr int, fonts model.FontMap, col
732761
733762 // Render values
734763 for i := 0 ; i < t .Rows ; i ++ {
764+
735765 if len (t .Values ) < i + 1 {
736766 break
737767 }
768+
738769 for j := 0 ; j < t .Cols ; j ++ {
770+
739771 if len (t .Values [i ]) < j + 1 {
740772 break
741773 }
774+
742775 s := t.Values [i ][j ]
743776 if len (strings .TrimSpace (s )) == 0 {
744777 continue
745778 }
779+
746780 colTd := td
747- if len (t .ColPaddings ) > j {
748- colTd , err = t .applyTextDescriptorPadding (colTd , t .ColPaddings [j ])
749- if err != nil {
781+ if len (t .ColPaddings ) > 0 && t .ColPaddings [j ] != nil {
782+ if err = t .calcTextDescriptorPadding (& colTd , t .ColPaddings [j ]); err != nil {
750783 return err
751784 }
752785 }
786+
753787 colTd .Text , _ = format .Text (s , pdf .TimestampFormat , pageNr , pdf .pageCount ())
788+
754789 row := i
755790 if t .Header != nil {
756791 row ++
757792 }
793+
758794 x , y := ll (row , j )
759- r1 := types .RectForWidthAndHeight (x , y , colWidths [j ], float64 (t .LineHeight ))
760- bb := model .WriteMultiLineAnchored (pdf .XRefTable , p .Buf , r1 , nil , colTd , t .colAnchors [j ])
795+ r := types .RectForWidthAndHeight (x , y , colWidths [j ], float64 (t .LineHeight ))
796+
797+ bb := model .WriteMultiLineAnchored (pdf .XRefTable , p .Buf , r , nil , colTd , t .colAnchors [j ])
798+
761799 if bb .Width () > colWidths [j ] {
762800 return errors .Errorf ("pdfcpu: table cell width overflow - reduce padding or text: %s" , colTd .Text )
763801 }
802+
764803 if bb .Height () > float64 (t .LineHeight ) {
765804 return errors .Errorf ("pdfcpu: table cell height overflow - reduce padding or text: %s" , colTd .Text )
766805 }
@@ -770,10 +809,12 @@ func (t *Table) renderValues(p *model.Page, pageNr int, fonts model.FontMap, col
770809}
771810
772811func (t * Table ) renderHeader (p * model.Page , pageNr int , fonts model.FontMap , colWidths []float64 , td model.TextDescriptor , ll func (row , col int ) (float64 , float64 )) error {
773- h := t .Header
812+ pdf := t .pdf
813+ th := t .Header
814+
774815 f1 := * t .Font
775- if h .Font != nil {
776- f1 = * h .Font
816+ if th .Font != nil {
817+ f1 = * th .Font
777818 }
778819 if f1 .Name [0 ] == '$' {
779820 // use named font
@@ -803,38 +844,40 @@ func (t *Table) renderHeader(p *model.Page, pageNr int, fonts model.FontMap, col
803844 td .FontName = f1 .Name
804845 td .FontKey = id
805846 td .FontSize = f1 .Size
806- td .RTL = h .RTL
847+ td .RTL = th .RTL
807848 td .StrokeCol = * f1 .col
808849 td .FillCol = * f1 .col
809850
810- pdf := t .content .page .pdf
851+ // Render header values.
852+ for i , s := range th .Values {
811853
812- for i , s := range t .Header .Values {
813854 if len (strings .TrimSpace (s )) == 0 {
814855 continue
815856 }
857+
816858 colTd := td
817- if len (t .Header .ColPaddings ) > i {
818- colTd , err = t .applyTextDescriptorPadding (colTd , t .Header .ColPaddings [i ])
819- if err != nil {
820- return err
821- }
822- }
859+ th .calcColumnPadding (& colTd , i )
823860 colTd .Text , _ = format .Text (s , pdf .TimestampFormat , pageNr , pdf .pageCount ())
861+
824862 x , y := ll (0 , i )
825- r1 := types .RectForWidthAndHeight (x , y , colWidths [i ], float64 (t .LineHeight ))
863+ r := types .RectForWidthAndHeight (x , y , colWidths [i ], float64 (t .LineHeight ))
864+
826865 a := t .colAnchors [i ]
827- if len (t . Header .colAnchors ) > 0 {
828- a = t . Header .colAnchors [i ]
866+ if len (th .colAnchors ) > 0 {
867+ a = th .colAnchors [i ]
829868 }
830- bb := model .WriteMultiLineAnchored (t .pdf .XRefTable , p .Buf , r1 , nil , colTd , a )
869+
870+ bb := model .WriteMultiLineAnchored (pdf .XRefTable , p .Buf , r , nil , colTd , a )
871+
831872 if bb .Width () > colWidths [i ] {
832873 return errors .Errorf ("pdfcpu: table header cell width overflow - reduce padding or text: %s" , colTd .Text )
833874 }
875+
834876 if bb .Height () > float64 (t .LineHeight ) {
835877 return errors .Errorf ("pdfcpu: table header cell height overflow - reduce padding or text: %s" , colTd .Text )
836878 }
837879 }
880+
838881 return nil
839882}
840883
@@ -907,10 +950,12 @@ func (t *Table) render(p *model.Page, pageNr int, fonts model.FontMap) error {
907950 return err
908951 }
909952 }
953+
910954 if t .pdf .Debug {
911955 draw .DrawCircle (p .Buf , r .LL .X , r .LL .Y , 5 , color .Black , & color .Red )
912956 }
913957
914958 fmt .Fprint (p .Buf , "Q " )
959+
915960 return nil
916961}
0 commit comments