fc.extensions.itext.Writer.java Source code

Java tutorial

Introduction

Here is the source code for fc.extensions.itext.Writer.java

Source

/**
 * $Id$ [$Rev$]
 * $Author$
 * $Date$
 * $URL$
 *
 * Copyright (c) 2009 by Andersen (F.C. Huang).
 *
 * The contents of this file is available under the MIT License.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

package fc.extensions.itext;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.Barcode39;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfBorderDictionary;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfFormField;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;
import fc.extensions.itext.smart.Cell;
import fc.extensions.itext.smart.Position;
import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
import org.apache.commons.lang.StringUtils;

/**
 * A PdfWriter wrapper.
 * 
 * @author Andersen.
 */
public final class Writer extends PdfPageEventHelper {

    private final static String CONTENT_OF_PAGE_COUNT = "          ";

    private Document document = null;
    private BaseColor baseColor = null;
    private File pdfFile = null;
    private PdfWriter pdfWriter = null;
    private PdfContentByte pdfWriterCB = null;
    private BaseFont baseFont = null;
    private BaseFont engBaseFont = null;
    private PdfTemplate pageHeadTemplate = null;
    private Page pageObject = null;
    private HashMap<Integer, Font> fontMap = new HashMap<Integer, Font>();
    private HashMap<Integer, Font> ansiFontMap = new HashMap<Integer, Font>();

    public Writer(String pdfFile, Rectangle pageSize, String fontPath, String ansiFontPath) throws Exception {
        this.pdfFile = new File(pdfFile);

        document = new Document(pageSize);
        pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(this.pdfFile));
        pdfWriter.setPageEvent(this);
        document.open();
        pdfWriterCB = pdfWriter.getDirectContent();
        baseColor = BaseColor.BLACK;
        baseFont = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        engBaseFont = BaseFont.createFont(ansiFontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
    }

    private Font getFont(int fontSize) {
        if (!fontMap.containsKey(fontSize)) {
            fontMap.put(fontSize, new Font(baseFont, fontSize, Font.UNDEFINED, baseColor));
        }
        return fontMap.get(fontSize);
    }

    private Font getAnsiFont(int fontSize) {
        if (!ansiFontMap.containsKey(fontSize)) {
            ansiFontMap.put(fontSize, new Font(engBaseFont, fontSize, Font.UNDEFINED, baseColor));
        }
        return ansiFontMap.get(fontSize);
    }

    public void setDebug() {
        this.baseColor = BaseColor.RED;
    }

    public void setPage(Page page) throws Exception {
        if (pdfWriter.getCurrentPageNumber() > 1) {
            throw new Exception("ITextClient: Cannot do setPageObject() after first page !!!");
        }
        this.pageObject = page;
        float width = baseFont.getWidthPoint(CONTENT_OF_PAGE_COUNT, page.getHeader().getFontSize());
        float height = page.getHeader().getPosition().getHeight();
        pageHeadTemplate = pdfWriter.getDirectContent().createTemplate(width, height);
        pageHeadTemplate.setBoundingBox(new Rectangle(0F, 0F, width, height));
    }

    @Override
    public void onCloseDocument(PdfWriter writer, Document document) {
        if (pageObject == null) {
            return;
        }
        pageHeadTemplate.beginText();
        pageHeadTemplate.setFontAndSize(baseFont, pageObject.getHeader().getFontSize());
        pageHeadTemplate.showTextAligned(PdfContentByte.ALIGN_RIGHT,
                StringUtils.right(CONTENT_OF_PAGE_COUNT + (writer.getCurrentPageNumber() - 1), 6),
                pageHeadTemplate.getWidth(), 0F, 0);
        pageHeadTemplate.endText();
    }

    @Override
    public void onEndPage(PdfWriter writer, Document document) {
        if (pageObject == null) {
            return;
        }
        float llx = pageObject.getHeader().getPosition().getLeft();
        float lly = pageObject.getHeader().getPosition().getBottom();
        float urx = pageObject.getHeader().getPosition().getRight();
        float ury = pageObject.getHeader().getPosition().getTop();
        float alingY = pageObject.getHeader().getPosition().getTop();
        int fontSize = (int) pageObject.getHeader().getFontSize();

        String[] headerBody = pageObject.getHeader().getBody();
        try {
            pdfWriterCB.saveState();
            pdfWriterCB.beginText();
            pdfWriterCB.setFontAndSize(baseFont, fontSize);
            pdfWriterCB.setTextMatrix(llx, ury);
            pdfWriterCB.setLeading(fontSize);
            for (int i = 0; i < headerBody.length; i++) {
                alingY = alingY - getLetterHeight(fontSize);
                if (i == headerBody.length - 1) {
                    pdfWriterCB.showTextAligned(PdfContentByte.ALIGN_RIGHT,
                            headerBody[i]
                                    + StringUtils.right(CONTENT_OF_PAGE_COUNT + writer.getCurrentPageNumber(), 6)
                                    + "/          ",
                            urx, alingY, 0);
                } else {
                    pdfWriterCB.showTextAligned(PdfContentByte.ALIGN_RIGHT, headerBody[i], urx, alingY, 0);
                }
            }
            pdfWriterCB.endText();
            pdfWriterCB.addTemplate(pageHeadTemplate, urx - baseFont.getWidthPoint(CONTENT_OF_PAGE_COUNT, fontSize),
                    alingY);
        } finally {
            pdfWriterCB.restoreState();
        }
    }

    @Override
    public void onStartPage(PdfWriter writer, Document document) {
    }

    public void insertPage(int pageNumberOfTemplate) {
        document.newPage();
    }

    public float getLetterHeight(int fontSize) {
        return baseFont.getWidthPoint("", fontSize);
    }

    public float getStringWidth(String content, int fontSize) {
        return baseFont.getWidthPoint(content, fontSize);
    }

    public void writeTextArray(String[] textArray, int fontSize, float leftX, float bottomY, float rightX,
            float topY) {
        try {
            float letterHeight = getLetterHeight(fontSize);

            int arrayLength = 0;
            for (String s : textArray) {
                if (s != null) {
                    arrayLength++;
                }
            }

            pdfWriterCB.saveState();
            pdfWriterCB.beginText();
            pdfWriterCB.setFontAndSize(baseFont, fontSize);
            pdfWriterCB.setColorFill(this.baseColor);
            pdfWriterCB.setTextMatrix(leftX, getCenterViaTop(bottomY, topY, letterHeight * (float) arrayLength));
            pdfWriterCB.setLeading(letterHeight);
            for (String s : textArray) {
                if (s != null) {
                    pdfWriterCB.newlineShowText(s);
                }
            }
            pdfWriterCB.endText();
        } finally {
            pdfWriterCB.restoreState();
        }
    }

    public void writeWrapText(String text, int fontSize, float leftX, float bottomY, float rightX, float topY)
            throws Exception {
        int realTextWidth = (int) baseFont.getWidthPoint(text, fontSize);
        int columnWidth = (int) (rightX - leftX);

        if (columnWidth >= realTextWidth) {
            writeText(text, fontSize, leftX, bottomY, topY);
        } else {
            String[] textArray;
            if (realTextWidth % columnWidth == 0) {
                textArray = new String[(realTextWidth / columnWidth) + 1];
            } else {
                textArray = new String[(realTextWidth / columnWidth) + 2];
            }
            int tmpWidth = 0;
            int start = 0;
            int index = 0;
            for (int i = 0; i < text.length(); i++) {
                tmpWidth += Math.round(baseFont.getWidthPoint(text.substring(i, i + 1), fontSize));
                if (tmpWidth >= (columnWidth - fontSize)) {
                    textArray[index] = text.substring(start, i);
                    start = i;
                    index++;
                    tmpWidth = 0;
                }
            }
            if (start < text.length()) {
                textArray[index] = text.substring(start);
            }

            writeTextArray(textArray, fontSize, leftX, bottomY, rightX, topY);
        }
    }

    public void writeText(String text, int fontSize, float leftX, float bottomY, float topY) {
        try {
            float letterHeight = getLetterHeight(fontSize);
            pdfWriterCB.saveState();
            pdfWriterCB.beginText();
            pdfWriterCB.setFontAndSize(baseFont, fontSize);
            pdfWriterCB.setColorFill(this.baseColor);
            pdfWriterCB.setTextMatrix(leftX, getCenterViaBottom(bottomY, topY, letterHeight));
            pdfWriterCB.showText(text);
            pdfWriterCB.endText();
        } finally {
            pdfWriterCB.restoreState();
        }
    }

    public void writeText(String text, int fontSize, Position position) {
        try {
            position.decreaseTop(fontSize);
            pdfWriterCB.saveState();
            pdfWriterCB.beginText();
            pdfWriterCB.setFontAndSize(baseFont, fontSize);
            pdfWriterCB.setColorFill(this.baseColor);
            pdfWriterCB.setTextMatrix(position.getLeft(), position.getTop());
            pdfWriterCB.showText(text);
            pdfWriterCB.endText();
            position.decreaseTop(1);
        } finally {
            pdfWriterCB.restoreState();
        }
    }

    private static float getCenterViaBottom(float bottomY, float topY, float letterHeight) {
        float tmpY = bottomY + ((topY - bottomY) / 2F) - letterHeight * 0.35F;
        return tmpY;
    }

    private static float getCenterViaTop(float bottomY, float topY, float letterHeight) {
        float tmpY = topY - ((topY - bottomY) / 2F) + letterHeight * 0.6F;
        return tmpY;
    }

    public void writeAlignedText(String text, int fontSize, String alignment, float leftX, float bottomY,
            float rightX, float topY) throws Exception {
        try {
            float letterHeight = getLetterHeight(fontSize);
            pdfWriterCB.saveState();
            pdfWriterCB.beginText();
            pdfWriterCB.setFontAndSize(baseFont, fontSize);
            pdfWriterCB.setColorFill(this.baseColor);
            switch (alignment.charAt(0)) {
            case 'L':
                pdfWriterCB.setTextMatrix(leftX, getCenterViaBottom(bottomY, topY, letterHeight));
                pdfWriterCB.showText(text);
                break;
            case 'C':
                pdfWriterCB.showTextAligned(PdfContentByte.ALIGN_CENTER, text, leftX + ((rightX - leftX) / 2F),
                        getCenterViaBottom(bottomY, topY, letterHeight), 0);
                break;
            case 'R':
                pdfWriterCB.showTextAligned(PdfContentByte.ALIGN_RIGHT, text, rightX,
                        getCenterViaBottom(bottomY, topY, letterHeight), 0);
                break;
            default:
                throw new Exception("Invalid alignment, alignment: " + alignment);
            }
            pdfWriterCB.endText();
        } finally {
            pdfWriterCB.restoreState();
        }
    }

    public void writeBarcode(String barcode, float leftX, float bottomY) throws Exception {
        writeBarcode(barcode, leftX, bottomY, 100F, true);
    }

    public void writeBarcode(String barcode, float leftX, float bottomY, float scalePercent, boolean isShowCode)
            throws Exception {
        Barcode39 code39 = new Barcode39();
        code39.setStartStopText(false);
        code39.setTextAlignment(PdfContentByte.ALIGN_LEFT);
        if (!isShowCode) {
            code39.setFont(null);
        }
        code39.setCode(barcode);
        Image image = code39.createImageWithBarcode(pdfWriterCB, this.baseColor, this.baseColor);
        image.setAbsolutePosition(leftX, bottomY);
        image.scalePercent(scalePercent);
        pdfWriterCB.addImage(image);
    }

    public void writeImage(String imagePath, float leftX, float bottomY, float scalePercent) throws Exception {
        Image image = Image.getInstance(imagePath);
        image.setAbsolutePosition(leftX, bottomY);
        if (scalePercent > 0F) {
            image.scalePercent(scalePercent);
        }
        pdfWriterCB.addImage(image);
    }

    public void writeImage(String imagePath, float leftX, float bottomY) throws Exception {
        writeImage(imagePath, leftX, bottomY, 0F);
    }

    /**
     * write PDF annotation for debugging.
     */
    public void writeAnnotation(String title, String content, float leftX, float bottomY, float rightX, float topY)
            throws Exception {
        try {
            pdfWriterCB.saveState();
            pdfWriterCB.setRGBColorStroke(255, 255, 0);
            pdfWriterCB.setLineWidth(1F);
            pdfWriterCB.rectangle(leftX, bottomY, rightX - leftX, topY - bottomY);
            pdfWriterCB.stroke();
            PdfFormField field = PdfFormField.createTextField(pdfWriter, false, false, 0);
            field.setWidget(new Rectangle(leftX, bottomY, rightX, topY), PdfAnnotation.HIGHLIGHT_INVERT);
            field.setFlags(PdfAnnotation.FLAGS_PRINT);
            field.setFieldName(title);
            field.setPage();
            field.setValueAsString(content);
            field.setBorderStyle(new PdfBorderDictionary(0.5F, PdfBorderDictionary.STYLE_DASHED));
            pdfWriter.addAnnotation(field);
        } finally {
            pdfWriterCB.restoreState();
        }
    }

    public void drawLine(float lineWidth, float fromX, float fromY, float toX, float toY) {
        try {
            pdfWriterCB.saveState();
            pdfWriterCB.setLineWidth(lineWidth);
            pdfWriterCB.setRGBColorStroke(0, 0, 0);
            pdfWriterCB.moveTo(fromX, fromY);
            pdfWriterCB.lineTo(toX, toY);
            pdfWriterCB.stroke();
        } finally {
            pdfWriterCB.restoreState();
        }
    }

    public void drawLine(float lineWidth, Position position) {
        try {
            position.decreaseTop(lineWidth);
            pdfWriterCB.saveState();
            pdfWriterCB.setLineWidth(lineWidth);
            pdfWriterCB.setRGBColorStroke(0, 0, 0);
            pdfWriterCB.moveTo(position.getLeft(), position.getTop());
            pdfWriterCB.lineTo(position.getRight(), position.getTop());
            pdfWriterCB.stroke();
            position.decreaseTop((lineWidth + 1));
        } finally {
            pdfWriterCB.restoreState();
        }
    }

    public void drawRectangle(Position position, float lineWidth) {
        try {
            pdfWriterCB.saveState();
            pdfWriterCB.setRGBColorStroke(0, 0, 0);
            pdfWriterCB.setLineWidth(lineWidth);
            pdfWriterCB.rectangle(position.getLeft(), position.getBottom(), position.getWidth(),
                    position.getHeight());
            pdfWriterCB.stroke();
        } finally {
            pdfWriterCB.restoreState();
        }
    }

    public void drawRectangleWithVariableBorder(Position position, float lineWidth, int borderType) {
        try {
            pdfWriterCB.saveState();
            pdfWriterCB.setRGBColorStroke(0, 0, 0);
            Rectangle rectangle = new Rectangle(position.getLeft(), position.getBottom(), position.getRight(),
                    position.getTop());
            rectangle.setBorderWidth(lineWidth);
            rectangle.setBorder(borderType);
            rectangle.setUseVariableBorders(true);
            pdfWriterCB.rectangle(position.getLeft(), position.getBottom(), position.getWidth(),
                    position.getHeight());
            pdfWriterCB.stroke();
        } finally {
            pdfWriterCB.restoreState();
        }
    }

    /**
     * split the rectangle in vertical.
     */
    public void drawRectangle(Position position, float lineWidth, int splitSize) {
        float width = position.getWidth() / splitSize;
        float height = position.getHeight();
        float left = position.getLeft();
        for (int i = 1; i <= splitSize; i++) {
            try {
                pdfWriterCB.saveState();
                pdfWriterCB.setRGBColorStroke(0, 0, 0);
                pdfWriterCB.setLineWidth(lineWidth);
                pdfWriterCB.rectangle(left, position.getBottom(), width, height);
                pdfWriterCB.stroke();
            } finally {
                pdfWriterCB.restoreState();
            }
            left += width;
        }
    }

    public PdfPTable createTable(int columns, float width, int[] columnWidthScale) throws DocumentException {
        PdfPTable pdfTable = new PdfPTable(columns);
        //table.setTableEvent(null);
        pdfTable.setTotalWidth(width);
        pdfTable.setWidths(columnWidthScale);
        return pdfTable;
    }

    public void addEmptyCell(PdfPTable table, float borderWidth) {
        table.getDefaultCell().setBorderWidth(borderWidth);
        table.addCell("");
    }

    public void addCell(PdfPTable table, String content, int fontSize, float borderWidth, int columnSpan) {
        PdfPCell pCell = new PdfPCell();
        if (columnSpan > 1) {
            pCell.setColspan(columnSpan);
        }
        pCell.setBorderWidth(borderWidth);
        pCell.setPhrase(new Phrase(content, getFont(fontSize)));
        pCell.setNoWrap(false);
        pCell.setHorizontalAlignment(PdfContentByte.ALIGN_LEFT);
        pCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        table.addCell(pCell);
    }

    public void addAnsiCell(PdfPTable table, String content, int fontSize, float borderWidth, int columnSpan) {
        PdfPCell pCell = new PdfPCell();
        if (columnSpan > 1) {
            pCell.setColspan(columnSpan);
        }
        pCell.setBorderWidth(borderWidth);
        pCell.setPhrase(new Phrase(content, getAnsiFont(fontSize)));
        pCell.setNoWrap(false);
        pCell.setHorizontalAlignment(PdfContentByte.ALIGN_LEFT);
        pCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        table.addCell(pCell);
    }

    public void addCell(PdfPTable table, Cell cell) {
        PdfPCell pCell = cell.getPdfPCell();
        if (cell.getFontType() == Cell.FontType.DBCS) {
            pCell.setPhrase(new Phrase(cell.getContent(), getFont(cell.getFontSize())));
        } else {
            pCell.setPhrase(new Phrase(cell.getContent(), getAnsiFont(cell.getFontSize())));
        }
        table.addCell(pCell);
    }

    /**
     * Flush the table in memeory
     * 
     * @param table
     * @param leftX
     * @param topY
     * @return Y-coord of the bottom position of table
     */
    public float flushTable(PdfPTable table, float leftX, float topY) {
        // table.setTableEvent(null);
        return table.writeSelectedRows(0, -1, leftX, topY, pdfWriterCB);
    }

    public void close() throws Exception {
        document.close();
    }

    public int getCurrentPageNumber() {
        return pdfWriter.getCurrentPageNumber();
    }
}