Skip to content

Commit b4556cc

Browse files
committed
Cleanup table column paddings
1 parent 404b465 commit b4556cc

File tree

1 file changed

+123
-78
lines changed

1 file changed

+123
-78
lines changed

pkg/pdfcpu/primitives/table.go

Lines changed: 123 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
97132
type 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+
212257
func (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
640677
func (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

677715
func (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

718746
func (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

772811
func (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

Comments
 (0)