package gutenberg.itext; import com.google.common.base.Function; import com.itextpdf.text.BaseColor; import com.itextpdf.text.Document; import com.itextpdf.text.Element; import com.itextpdf.text.Font; import com.itextpdf.text.Phrase; import com.itextpdf.text.Rectangle; import com.itextpdf.text.pdf.PdfContentByte; import com.itextpdf.text.pdf.PdfPageEventHelper; import com.itextpdf.text.pdf.PdfWriter; import static com.itextpdf.text.pdf.ColumnText.showTextAligned; import static org.apache.commons.lang3.StringUtils.defaultString; /** * @author <a href="http://twitter.com/aloyer">@aloyer</a> */ public class HeaderFooter extends PdfPageEventHelper { public static Function<PageInfos, Phrase> none() { return new Function<PageInfos, Phrase>() { @Override public Phrase apply(PageInfos pageInfos) { return null; } }; } public static Function<PageInfos, Phrase> create(final Styles styles, final Object fontKey, final String firstPageTemplate, final String otherPageTemplate, final Phrase otherPage) { return new Function<PageInfos, Phrase>() { @Override public Phrase apply(PageInfos pageInfos) { Font font = styles.getFontOrDefault(fontKey); if (pageInfos.getRawPageNumber() == 1) { if (firstPageTemplate != null) { return new Phrase(firstPageTemplate, font); } } else { if (otherPage != null) return otherPage; else if (otherPageTemplate != null) { String text = otherPageTemplate; text = text.replace("${chapterTitle}", defaultString(pageInfos.chapterTitle())); text = text.replace("${sectionTitle}", defaultString(pageInfos.sectionTitle())); return new Phrase(text, font); } } return null; } }; } public static final String HEADER_FONT = "header-font"; public static final String FOOTER_FONT = "footer-font"; public static final String HEADER_LINE_COLOR = "header-line-color"; private final PageNumber pageNumber; private final Styles styles; private final Function<PageInfos, Phrase> header; private final Function<PageInfos, Phrase> footer; private boolean footerOnFirstPage = false; private Rectangle rect; private boolean drawLine = true; public HeaderFooter(PageNumber pageNumber, Styles styles, Function<PageInfos, Phrase> header, Function<PageInfos, Phrase> footer) { this.pageNumber = pageNumber; this.styles = styles; this.header = header; this.footer = footer; } public HeaderFooter footerOnFirstPage(boolean footerOnFirstPage) { this.footerOnFirstPage = footerOnFirstPage; return this; } @Override public void onEndPage(PdfWriter writer, Document document) { if (rect == null) rect = writer.getBoxSize("art"); PdfContentByte canvas = writer.getDirectContent(); PageInfos pageInfos = pageNumber.pageInfos(); drawHeader(canvas, pageInfos); drawFooter(canvas, pageInfos); } public void drawHeader(PdfContentByte canvas, PageInfos pageInfos) { float top = rect.getTop() + 20; Phrase header = headerText(pageInfos); if (header != null) { showTextAligned(canvas, Element.ALIGN_CENTER, header, (rect.getLeft() + rect.getRight()) / 2, top, 0); } } public void drawFooter(PdfContentByte canvas, PageInfos pageInfos) { if (pageInfos.getRawPageNumber() == 1 && !footerOnFirstPage) return; if (drawLine) { BaseColor lineColor = styles.getColorOrDefault(HEADER_LINE_COLOR); canvas.saveState(); canvas.setColorStroke(lineColor); canvas.setLineWidth(1.2f); canvas.moveTo(rect.getLeft(), rect.getBottom() - 6); canvas.lineTo(rect.getRight(), rect.getBottom() - 6); canvas.stroke(); canvas.restoreState(); } float bottom = rect.getBottom() - 20; Phrase footer = footerText(pageInfos); if (footer != null) { showTextAligned(canvas, Element.ALIGN_LEFT, footer, rect.getLeft(), bottom, 0); } Font footerFont = styles.getFontOrDefault(FOOTER_FONT); Phrase page = new Phrase(pageInfos.getFormattedPageNumber(), footerFont); showTextAligned(canvas, Element.ALIGN_RIGHT, page, rect.getRight(), bottom, 0); } private Phrase headerText(PageInfos pageInfos) { return header.apply(pageInfos); } private Phrase footerText(PageInfos pageInfos) { return footer.apply(pageInfos); } }