package main import "strconv" // TOCItem is one entry in the Inhaltsverzeichnis. type TOCItem struct { Level int Title string PageStr string // formatted page number (Roman or Arabic) } // TableItem is one entry in the Tabellenverzeichnis. type TableItem struct { Title string PageStr string } // FigureItem is one entry in the Abbildungsverzeichnis. type FigureItem struct { Title string PageStr string } // dirEntry is the internal representation used by renderDirEntries. type dirEntry struct { indent int // indentation level (0 = none) title string // translated title text pageStr string // page number string } // RecordHeader adds a heading to the TOC with the appropriate page number. // Front-matter headings use Roman numerals; main-body headings use Arabic. // Headings on the title page (NumNone) are not recorded. func (r *IHKRenderer) RecordHeader(level int, title string) { var pageStr string switch r.numType { case NumRoman: pageStr = toRoman(r.pdf.PageNo()) case NumArabic: dp := r.pdf.PageNo() - r.pageOffset if dp <= 0 { dp = 1 } pageStr = strconv.Itoa(dp) default: return } r.tocItems = append(r.tocItems, TOCItem{Level: level, Title: title, PageStr: pageStr}) } // RecordTable adds an entry to the Tabellenverzeichnis. func (r *IHKRenderer) RecordTable(title string) { dp := r.pdf.PageNo() - r.pageOffset if dp <= 0 { dp = 1 } r.tableItems = append(r.tableItems, TableItem{Title: title, PageStr: strconv.Itoa(dp)}) } // RecordFigure adds an entry to the Abbildungsverzeichnis. func (r *IHKRenderer) RecordFigure(title string) { dp := r.pdf.PageNo() - r.pageOffset if dp <= 0 { dp = 1 } r.figureItems = append(r.figureItems, FigureItem{Title: title, PageStr: strconv.Itoa(dp)}) } // RenderTOC renders the Inhaltsverzeichnis on a new Roman-numbered page. // In pass 1 the list is empty (no tocItems yet); pass 2 fills it in. // Note: if the TOC spans more pages than in pass 1, subsequent page numbers // will be off by the difference — an inherent two-pass limitation. func (r *IHKRenderer) RenderTOC() { r.numType = NumRoman r.pdf.AddPage() r.pdf.SetFont("Helvetica", "B", dinFontHeading) r.pdf.CellFormat(0, dinLineHtHeading+4, r.tr("Inhaltsverzeichnis"), "", 1, "L", false, 0, "") r.pdf.Ln(dinSpaceAfterHeading) if len(r.tocItems) == 0 { return } // Column header row uw := r.usableWidth() r.pdf.SetFont("Helvetica", "B", dinFontBody) r.pdf.CellFormat(uw-20, dinLineHtBody, r.tr("Inhalt"), "", 0, "L", false, 0, "") r.pdf.CellFormat(20, dinLineHtBody, r.tr("Seite"), "", 1, "R", false, 0, "") r.pdf.Ln(2) entries := make([]dirEntry, len(r.tocItems)) for i, item := range r.tocItems { entries[i] = dirEntry{ indent: item.Level - 1, title: item.Title, pageStr: item.PageStr, } } r.renderDirEntries(entries) } // RenderListOfTables renders the Tabellenverzeichnis if any tables were recorded. func (r *IHKRenderer) RenderListOfTables() { if len(r.tableItems) == 0 { return } r.pdf.AddPage() r.pdf.SetFont("Helvetica", "B", dinFontHeading) r.pdf.CellFormat(0, dinLineHtHeading+4, r.tr("Tabellenverzeichnis"), "", 1, "L", false, 0, "") r.pdf.Ln(dinSpaceAfterHeading) entries := make([]dirEntry, len(r.tableItems)) for i, item := range r.tableItems { entries[i] = dirEntry{indent: 0, title: item.Title, pageStr: item.PageStr} } r.renderDirEntries(entries) } // RenderListOfFigures renders the Abbildungsverzeichnis if any figures were recorded. func (r *IHKRenderer) RenderListOfFigures() { if len(r.figureItems) == 0 { return } r.pdf.AddPage() r.pdf.SetFont("Helvetica", "B", dinFontHeading) r.pdf.CellFormat(0, dinLineHtHeading+4, r.tr("Abbildungsverzeichnis"), "", 1, "L", false, 0, "") r.pdf.Ln(dinSpaceAfterHeading) entries := make([]dirEntry, len(r.figureItems)) for i, item := range r.figureItems { entries[i] = dirEntry{indent: 0, title: item.Title, pageStr: item.PageStr} } r.renderDirEntries(entries) } // renderDirEntries renders a list of title/page entries with dot leaders, // per DIN 5008 Inhaltsverzeichnis layout. func (r *IHKRenderer) renderDirEntries(entries []dirEntry) { uw := r.usableWidth() lm, _, _, _ := r.pdf.GetMargins() r.pdf.SetFont("Helvetica", "", dinFontBody) for _, e := range entries { indent := float64(e.indent * 8) r.pdf.SetX(lm + indent) title := r.tr(e.title) pageStr := e.pageStr tw := r.pdf.GetStringWidth(title) pw := r.pdf.GetStringWidth(pageStr) avail := uw - indent - tw - pw - 6 r.pdf.CellFormat(tw+2, dinLineHtBody, title, "", 0, "L", false, 0, "") if avail > 0 { dots := "" dw := r.pdf.GetStringWidth(".") if dw > 0 { for float64(len([]rune(dots)))*dw < avail { dots += "." } } r.pdf.CellFormat(avail, dinLineHtBody, dots, "", 0, "L", false, 0, "") } r.pdf.CellFormat(pw+4, dinLineHtBody, pageStr, "", 1, "R", false, 0, "") } }