iText实战--根据绝对位置添加内容

3.1 direct content 概念简介

pdf内容的4个层级

层级1:在text和graphics底下,PdfWriter.getDirectContentUnder()

层级2:graphics层,Chunk, Images背景,PdfPCell的边界等

层级3:text层,Chunks, Phrases, Paragraphs 内容等

层级4:在text和graphics顶上,PdfWriter.getDirectContent()

iText实战--根据绝对位置添加内容_第1张图片

import java.io.FileOutputStream;
import java.io.IOException;

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.Paragraph;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfWriter;

public class FestivalOpening {

    /** The resulting PDF. */
    public static final String RESULT
        = "D:/data/iText/inAction/chapter03/festival_opening.pdf";
    /** The movie poster. */
    public static final String RESOURCE = "E:/study/PDF/SourceCodeiText/itext-book/book/resources/img/loa.jpg";

    /**
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
    	// step 1
        Document document = new Document(PageSize.POSTCARD, 30, 30, 30, 30);
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        // step 3
        document.open();
        // step 4
        // Create and add a Paragraph
        Paragraph p
            = new Paragraph("Foobar Film Festival", new Font(FontFamily.HELVETICA, 22));
        p.setAlignment(Element.ALIGN_CENTER);
        document.add(p);
        // Create and add an Image
        Image img = Image.getInstance(RESOURCE);
        img.setAbsolutePosition(
            (PageSize.POSTCARD.getWidth() - img.getScaledWidth()) / 2,
            (PageSize.POSTCARD.getHeight() - img.getScaledHeight()) / 2);
        document.add(img);
        
        // Now we go to the next page
        document.newPage();
        document.add(p);
        document.add(img);
        // Add text on top of the image
        PdfContentByte over = writer.getDirectContent();
        over.saveState();
        float sinus = (float)Math.sin(Math.PI / 60);
        float cosinus = (float)Math.cos(Math.PI / 60);
        BaseFont bf = BaseFont.createFont();
        over.beginText();
        over.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE);
        over.setLineWidth(1.5f);
        over.setRGBColorStroke(0xFF, 0x00, 0x00);
        over.setRGBColorFill(0xFF, 0xFF, 0xFF);
        over.setFontAndSize(bf, 36);
        over.setTextMatrix(cosinus, sinus, -sinus, cosinus, 50, 324);
        over.showText("SOLD OUT");
        over.endText();
        over.restoreState();
        // Add a rectangle under the image
        PdfContentByte under = writer.getDirectContentUnder();
        under.saveState();
        under.setRGBColorFill(0xFF, 0xD7, 0x00);
        under.rectangle(5, 5,
            PageSize.POSTCARD.getWidth() - 10, PageSize.POSTCARD.getHeight() - 10);
        under.fill();
        under.restoreState();
        // step 5
        document.close();
    }
}

iText实战--根据绝对位置添加内容_第2张图片

Graphics 状态

1、fill()填充四方形,并根据setRGBColorFill()填充,默认无边框

2、fillStroke()填充四方形,并根据setLineWidth()和默认black画边框

3、setRGBColorStroke() 设置边框颜色

4、current transformation matrix(CTM)当前转换矩阵

5、stroke() 仅画边框

6、saveState/rrestoreState 对应入栈、出栈

iText实战--根据绝对位置添加内容_第3张图片

iText实战--根据绝对位置添加内容_第4张图片

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfWriter;

public class GraphicsStateStack {
    
    /** The resulting PDF. */
    public static final String RESULT
        = "D:/data/iText/inAction/chapter03/graphics_state.pdf";

    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
    	// step 1
        Document document = new Document(new Rectangle(200, 120));
        // step 2
        PdfWriter writer
             = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        // step 3
        document.open();
        // step 4
        PdfContentByte canvas = writer.getDirectContent();
        // state 1:
        canvas.setRGBColorFill(0xFF, 0x45, 0x00);
        // fill a rectangle in state 1
        canvas.rectangle(10, 10, 60, 60);
        canvas.fill();
        canvas.saveState();
        // state 2;
        canvas.setLineWidth(3);
        canvas.setRGBColorFill(0x8B, 0x00, 0x00);
        // fill and stroke a rectangle in state 2
        canvas.rectangle(40, 20, 60, 60);
        canvas.fillStroke();
        canvas.saveState();
        // state 3:
        canvas.concatCTM(1, 0, 0.1f, 1, 0, 0);
        canvas.setRGBColorStroke(0xFF, 0x45, 0x00);
        canvas.setRGBColorFill(0xFF, 0xD7, 0x00);
        // fill and stroke a rectangle in state 3
        canvas.rectangle(70, 30, 60, 60);
        canvas.fillStroke();
        canvas.restoreState();
        // stroke a rectangle in state 2
        canvas.rectangle(100, 40, 60, 60);
        canvas.stroke();
        canvas.restoreState();
        // fill and stroke a rectangle in state 1
        canvas.rectangle(130, 50, 60, 60);
        canvas.fillStroke();
        // step 5
        document.close();
    }
}

Text 状态

1、showText(),设置显示的文本

2、setTextRenderingMode()设置边框模式,setLineWidth()设置边框宽度,默认无边框

3、setFontAndSize() 设置字体和大小

4、setTextMatrix() 设置字体矩阵

5、setRGBColorStoke() 设置边框颜色

6、setRGBColorFill() 设置填充颜色

3.2 根据绝对定位添加Text

PdfContentByte.showTextAligned()

iText实战--根据绝对位置添加内容_第5张图片

测量字符串

        Chunk c;
        String foobar = "Foobar Film Festival";
        // Measuring a String in Helvetica
        Font helvetica = new Font(FontFamily.HELVETICA, 12);
        BaseFont bf_helv = helvetica.getCalculatedBaseFont(false);
        float width_helv = bf_helv.getWidthPoint(foobar, 12);
        c = new Chunk(foobar + ": " + width_helv, helvetica);
        document.add(new Paragraph(c));
        document.add(new Paragraph(String.format("Chunk width: %f", c.getWidthPoint())));
        // Measuring a String in Times
        BaseFont bf_times = BaseFont.createFont(
            "c:/windows/fonts/times.ttf", BaseFont.WINANSI, BaseFont.EMBEDDED);
        Font times = new Font(bf_times, 12);
        float width_times = bf_times.getWidthPoint(foobar, 12);
        c = new Chunk(foobar + ": " + width_times, times);
        document.add(new Paragraph(c));
        document.add(new Paragraph(String.format("Chunk width: %f", c.getWidthPoint())));
        document.add(Chunk.NEWLINE);

字符串上行空间和下行空间

注意:字体大小不是某个字符的高度,而是一行的垂直空间

        // Ascent and descent of the String
        document.add(new Paragraph("Ascent Helvetica: "
                + bf_helv.getAscentPoint(foobar, 12)));
        document.add(new Paragraph("Ascent Times: "
                + bf_times.getAscentPoint(foobar, 12)));
        document.add(new Paragraph("Descent Helvetica: "
                + bf_helv.getDescentPoint(foobar, 12)));
        document.add(new Paragraph("Descent Times: "
                + bf_times.getDescentPoint(foobar, 12)));

字符串定位

        PdfContentByte canvas = writer.getDirectContent();        
        // Adding text with PdfContentByte.showTextAligned()
        canvas.beginText();
        canvas.setFontAndSize(bf_helv, 12);
        canvas.showTextAligned(Element.ALIGN_LEFT, foobar, 400, 788, 0);
        canvas.showTextAligned(Element.ALIGN_RIGHT, foobar, 400, 752, 0);
        canvas.showTextAligned(Element.ALIGN_CENTER, foobar, 400, 716, 0);
        canvas.showTextAligned(Element.ALIGN_CENTER, foobar, 400, 680, 30);
        canvas.showTextAlignedKerned(Element.ALIGN_LEFT, foobar, 400, 644, 0);
        canvas.endText();

字距调整(KERNING

        // Kerned text
        width_helv = bf_helv.getWidthPointKerned(foobar, 12);
        c = new Chunk(foobar + ": " + width_helv, helvetica);
        document.add(new Paragraph(c));

ColumnText.showTextAligned()

iText实战--根据绝对位置添加内容_第6张图片

        // Adding text with ColumnText.showTextAligned()
        Phrase phrase = new Phrase(foobar, times);
        ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, phrase, 200, 572, 0);
        ColumnText.showTextAligned(canvas, Element.ALIGN_RIGHT, phrase, 200, 536, 0);
        ColumnText.showTextAligned(canvas, Element.ALIGN_CENTER, phrase, 200, 500, 0);
        ColumnText.showTextAligned(canvas, Element.ALIGN_CENTER, phrase, 200, 464, 30);
        ColumnText.showTextAligned(canvas, Element.ALIGN_CENTER, phrase, 200, 428, -30);

短句(Phrase)定位

一个短句(Phrase)能够包含一系列的块(Chunk)。添加短句(Phrase)到绝对定位,可以方便地选择字体、字号和颜色,iText会自动计算短句(Phrase)内每个块(Chunk)的间距。

块:缩放、倾斜、渲染模式(Chunks: Scaling、Skewing、Rendering Mode)

1、setScaling(float scale) 设置缩放比例

2、setSkew(float arg1, float arg2) 设置倾斜,arg1:基线的角度,arg2:字符对基线的角度

3、setTextRenderMode() 设置文本渲染模式

PdfContentByte.TEXT_RENDER_MODE_FILL,默认填充字符形状,无边框
PdfContentByte.TEXT_RENDER_MODE_STROKE,不填充字符,仅边框
PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE,填充字符,带边框
PdfContentByte.TEXT_RENDER_MODE_INVISIBLE,文本不可见
        // Chunk attributes
        c = new Chunk(foobar, times);
        c.setHorizontalScaling(0.5f);
        phrase = new Phrase(c);
        ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, phrase, 400, 572, 0);
        c = new Chunk(foobar, times);
        c.setSkew(15, 15);
        phrase = new Phrase(c);
        ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, phrase, 400, 536, 0);
        c = new Chunk(foobar, times);
        c.setSkew(0, 25);
        phrase = new Phrase(c);
        ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, phrase, 400, 500, 0);
        c = new Chunk(foobar, times);
        c.setTextRenderMode(PdfContentByte.TEXT_RENDER_MODE_STROKE, 0.1f, BaseColor.RED);
        phrase = new Phrase(c);
        ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, phrase, 400, 464, 0);
        c = new Chunk(foobar, times);
        c.setTextRenderMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE, 1, null);
        phrase = new Phrase(c);
        ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, phrase, 400, 428, -0);

完整示例

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.BaseColor;

public class FoobarFilmFestival {

    public static final String RESULT
        = "D:/data/iText/inAction/chapter03/foobar_film_festival.pdf";

    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
    	// step 1
        Document document = new Document();
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        // step 3
        document.open();
        // step 4
        Chunk c;
        String foobar = "Foobar Film Festival";
        // Measuring a String in Helvetica
        Font helvetica = new Font(FontFamily.HELVETICA, 12);
        BaseFont bf_helv = helvetica.getCalculatedBaseFont(false);
        float width_helv = bf_helv.getWidthPoint(foobar, 12);
        c = new Chunk(foobar + ": " + width_helv, helvetica);
        document.add(new Paragraph(c));
        document.add(new Paragraph(String.format("Chunk width: %f", c.getWidthPoint())));
        // Measuring a String in Times
        BaseFont bf_times = BaseFont.createFont(
            "c:/windows/fonts/times.ttf", BaseFont.WINANSI, BaseFont.EMBEDDED);
        Font times = new Font(bf_times, 12);
        float width_times = bf_times.getWidthPoint(foobar, 12);
        c = new Chunk(foobar + ": " + width_times, times);
        document.add(new Paragraph(c));
        document.add(new Paragraph(String.format("Chunk width: %f", c.getWidthPoint())));
        document.add(Chunk.NEWLINE);
        // Ascent and descent of the String
        document.add(new Paragraph("Ascent Helvetica: "
                + bf_helv.getAscentPoint(foobar, 12)));
        document.add(new Paragraph("Ascent Times: "
                + bf_times.getAscentPoint(foobar, 12)));
        document.add(new Paragraph("Descent Helvetica: "
                + bf_helv.getDescentPoint(foobar, 12)));
        document.add(new Paragraph("Descent Times: "
                + bf_times.getDescentPoint(foobar, 12)));
        document.add(Chunk.NEWLINE);
        // Kerned text
        width_helv = bf_helv.getWidthPointKerned(foobar, 12);
        c = new Chunk(foobar + ": " + width_helv, helvetica);
        document.add(new Paragraph(c));
        // Drawing lines to see where the text is added
        PdfContentByte canvas = writer.getDirectContent();
        canvas.saveState();
        canvas.setLineWidth(0.05f);
        canvas.moveTo(400, 806);
        canvas.lineTo(400, 626);
        canvas.moveTo(508.7f, 806);
        canvas.lineTo(508.7f, 626);
        canvas.moveTo(280, 788);
        canvas.lineTo(520, 788);
        canvas.moveTo(280, 752);
        canvas.lineTo(520, 752);
        canvas.moveTo(280, 716);
        canvas.lineTo(520, 716);
        canvas.moveTo(280, 680);
        canvas.lineTo(520, 680);
        canvas.moveTo(280, 644);
        canvas.lineTo(520, 644);
        canvas.stroke();
        canvas.restoreState();
        // Adding text with PdfContentByte.showTextAligned()
        canvas.beginText();
        canvas.setFontAndSize(bf_helv, 12);
        canvas.showTextAligned(Element.ALIGN_LEFT, foobar, 400, 788, 0);
        canvas.showTextAligned(Element.ALIGN_RIGHT, foobar, 400, 752, 0);
        canvas.showTextAligned(Element.ALIGN_CENTER, foobar, 400, 716, 0);
        canvas.showTextAligned(Element.ALIGN_CENTER, foobar, 400, 680, 30);
        canvas.showTextAlignedKerned(Element.ALIGN_LEFT, foobar, 400, 644, 0);
        canvas.endText();
        // More lines to see where the text is added
        canvas.saveState();
        canvas.setLineWidth(0.05f);
        canvas.moveTo(200, 590);
        canvas.lineTo(200, 410);
        canvas.moveTo(400, 590);
        canvas.lineTo(400, 410);
        canvas.moveTo(80, 572);
        canvas.lineTo(520, 572);
        canvas.moveTo(80, 536);
        canvas.lineTo(520, 536);
        canvas.moveTo(80, 500);
        canvas.lineTo(520, 500);
        canvas.moveTo(80, 464);
        canvas.lineTo(520, 464);
        canvas.moveTo(80, 428);
        canvas.lineTo(520, 428);
        canvas.stroke();
        canvas.restoreState();
        // Adding text with ColumnText.showTextAligned()
        Phrase phrase = new Phrase(foobar, times);
        ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, phrase, 200, 572, 0);
        ColumnText.showTextAligned(canvas, Element.ALIGN_RIGHT, phrase, 200, 536, 0);
        ColumnText.showTextAligned(canvas, Element.ALIGN_CENTER, phrase, 200, 500, 0);
        ColumnText.showTextAligned(canvas, Element.ALIGN_CENTER, phrase, 200, 464, 30);
        ColumnText.showTextAligned(canvas, Element.ALIGN_CENTER, phrase, 200, 428, -30);
        // Chunk attributes
        c = new Chunk(foobar, times);
        c.setHorizontalScaling(0.5f);
        phrase = new Phrase(c);
        ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, phrase, 400, 572, 0);
        c = new Chunk(foobar, times);
        c.setSkew(15, 15);
        phrase = new Phrase(c);
        ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, phrase, 400, 536, 0);
        c = new Chunk(foobar, times);
        c.setSkew(0, 25);
        phrase = new Phrase(c);
        ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, phrase, 400, 500, 0);
        c = new Chunk(foobar, times);
        c.setTextRenderMode(PdfContentByte.TEXT_RENDER_MODE_STROKE, 0.1f, BaseColor.RED);
        phrase = new Phrase(c);
        ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, phrase, 400, 464, 0);
        c = new Chunk(foobar, times);
        c.setTextRenderMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE, 1, null);
        phrase = new Phrase(c);
        ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, phrase, 400, 428, -0);
        // step 5
        document.close();
    }
}

3.3 使用ColumnText对象

在文本模式下使用ColumnText

在复合模式中使用ColumnText

3.4 创建可重复使用的内容

如何在文档重复添加image?PDF图片的字节存储在单独区域,页面包含一个图片的引用,指向external object(XObject)

Image XObjects

添加图片到顶层

顶层的图片遮盖住文本:Foobar Film Festival

iText实战--根据绝对位置添加内容_第7张图片

import java.io.FileOutputStream;
import java.io.IOException;

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.Paragraph;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.PdfWriter;

public class ImageDirect {

    /** The resulting PDF. */
    public static final String RESULT
        = "D:/data/iText/inAction/chapter03/image_direct.pdf";
    /** The movie poster. */
    public static final String RESOURCE
        = "E:/study/PDF/SourceCodeiText/itext-book/book/resources/img/loa.jpg";
    
    public static void main(String[] args)
        throws IOException, DocumentException {
    	// step 1
        Document document
            = new Document(PageSize.POSTCARD, 30, 30, 30, 30);
        // step 2
        PdfWriter writer
            = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
        writer.setCompressionLevel(0);
        // step 3
        document.open();
        // step 4
        Image img = Image.getInstance(RESOURCE);
        img.setAbsolutePosition((PageSize.POSTCARD.getWidth() - img.getScaledWidth()) / 2,
                (PageSize.POSTCARD.getHeight() - img.getScaledHeight()) / 2);
        writer.getDirectContent().addImage(img);
        Paragraph p = new Paragraph("Foobar Film Festival", new Font(FontFamily.HELVETICA, 22));
        p.setAlignment(Element.ALIGN_CENTER);
        document.add(p);
        // step 5
        document.close();
    }
}

倾斜图片

iText实战--根据绝对位置添加内容_第8张图片

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;

public class ImageSkew {

    /** The resulting PDF. */
    public static final String RESULT = "D:/data/iText/inAction/chapter03/image_skew.pdf";
    /** The movie poster. */
    public static final String RESOURCE = "E:/study/PDF/SourceCodeiText/itext-book/book/resources/img/loa.jpg";

    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
    	// step 1
        Document document = new Document(PageSize.POSTCARD.rotate());
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document,
                new FileOutputStream(RESULT));
        writer.setCompressionLevel(0);
        // step 3
        document.open();
        // step 4
        Image img = Image.getInstance(RESOURCE);
        // Add the image to the upper layer
        writer.getDirectContent().addImage(img,
            img.getWidth(), 0, 0.35f * img.getHeight(),
            0.65f * img.getHeight(), 30, 30);
        // step 5
        document.close();
    }
}

内嵌图片

PdfWriter.getDirectContent().addImage(img, true)

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;

public class ImageInline {

    /** The resulting PDF. */
    public static final String RESULT
        = "D:/data/iText/inAction/chapter03/image_inline.pdf";
    /** The movie poster. */
    public static final String RESOURCE
        = "E:/study/PDF/SourceCodeiText/itext-book/book/resources/img/loa.jpg";

    /**
     * Main method.
     *
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     */
    public static void main(String[] args)
        throws IOException, DocumentException {
    	// step 1
        Document document = new Document(PageSize.POSTCARD, 30, 30, 30, 30);
        // step 2
        PdfWriter writer = PdfWriter.getInstance(document,
                new FileOutputStream(RESULT));
        writer.setCompressionLevel(0);
        // step 3
        document.open();
        // step 4
        Image img = Image.getInstance(RESOURCE);
        img.setAbsolutePosition(
            (PageSize.POSTCARD.getWidth() - img.getScaledWidth()) / 2,
            (PageSize.POSTCARD.getHeight() - img.getScaledHeight()) / 2);
        writer.getDirectContent().addImage(img, true);
        // step 5
        document.close();
    }
}

PdfTemplate 对象

PdfTemplate:XObject的别称

PdfTemplate是一个PDF内容流,它是任何图形对象的序列。PdfTemplate扩展PdfContentByte并继承所有其方法。

iText实战--根据绝对位置添加内容_第9张图片

        PdfContentByte canvas = writer.getDirectContent();
        // Create the XObject
        PdfTemplate celluloid = canvas.createTemplate(595, 84.2f);
        celluloid.rectangle(8, 8, 579, 68);
        for (float f = 8.25f; f < 581; f+= 6.5f) {
            celluloid.roundRectangle(f, 8.5f, 6, 3, 1.5f);
            celluloid.roundRectangle(f, 72.5f, 6, 3, 1.5f);
        }
        celluloid.setGrayFill(0.1f);
        celluloid.eoFill();
        // Write the XObject to the OutputStream
        writer.releaseTemplate(celluloid);
        // Add the XObject 10 times
        for (int i = 0; i < 10; i++) {
            canvas.addTemplate(celluloid, 0, i * 84.2f);
        }
        // Go to the next page
        document.newPage();
        // Add the XObject 10 times
        for (int i = 0; i < 10; i++) {
            canvas.addTemplate(celluloid, 0, i * 84.2f);
        }

你可能感兴趣的:(签章专题,Java,python,java,开发语言)