001: package it.stefanochizzolini.clown.samples;
002:
003: import it.stefanochizzolini.clown.documents.Document;
004: import it.stefanochizzolini.clown.documents.Page;
005: import it.stefanochizzolini.clown.documents.contents.composition.AlignmentXEnum;
006: import it.stefanochizzolini.clown.documents.contents.composition.AlignmentYEnum;
007: import it.stefanochizzolini.clown.documents.contents.composition.BlockFilter;
008: import it.stefanochizzolini.clown.documents.contents.composition.PrimitiveFilter;
009: import it.stefanochizzolini.clown.documents.contents.fonts.StandardType1Font;
010: import it.stefanochizzolini.clown.documents.contents.xObjects.XObject;
011: import it.stefanochizzolini.clown.files.File;
012: import it.stefanochizzolini.clown.tokens.FileFormatException;
013:
014: import java.awt.Dimension;
015: import java.awt.geom.Dimension2D;
016: import java.awt.geom.Point2D;
017: import java.awt.geom.Rectangle2D;
018:
019: /**
020: This sample demonstrates how to reuse a page as a form (precisely: form XObject [PDF:1.6:4.9]).
021: <h3>Remarks</h3>
022: <p>Form XObjects are a convenient way to represent contents multiple times on multiple pages as
023: templates.</p>
024: @version 0.0.5
025: @since 0.0.5
026: */
027: public class PageToFormSample implements ISample {
028: // <dynamic>
029: // <interface>
030: // <public>
031: // <ISample>
032: public void run(PDFClownSampleLoader loader) {
033: // (boilerplate user choice -- ignore it)
034: String filePath = loader
035: .getPdfFileChoice("Please select a PDF file to use as form");
036:
037: // 1. Instantiate the form source file!
038: File formFile;
039: try {
040: formFile = new File(filePath);
041: } catch (FileFormatException e) {
042: throw new RuntimeException(filePath
043: + " file has a bad file format.", e);
044: } catch (Exception e) {
045: throw new RuntimeException(
046: filePath + " file access error.", e);
047: }
048:
049: // 2. Instantiate a new PDF file!
050: /* NOTE: a File object is the low-level (syntactic) representation of a PDF file. */
051: File file = new File();
052: // Get its corresponding document!
053: /* NOTE: a Document object is the high-level (semantic) representation of a PDF file. */
054: Document document = file.getDocument();
055:
056: // 3. Convert the first page of the source file into a form inside the new document!
057: XObject form = formFile.getDocument().getPages().get(0)
058: .toXObject(document);
059:
060: // 4. Insert the contents into the new document!
061: populate(document, form);
062:
063: // (boilerplate metadata insertion -- ignore it)
064: loader.buildAccessories(document, this .getClass(),
065: "Page-to-form", "converting a page to a reusable form");
066:
067: // 5. Serialize the PDF file (again, boilerplate code -- see the PDFClownSampleLoader class source code)!
068: loader.serialize(file, this .getClass().getSimpleName(), false);
069: }
070:
071: // </ISample>
072: // </public>
073:
074: // <private>
075: /**
076: Populates a PDF file with contents.
077: */
078: private void populate(Document document, XObject form) {
079: // 1. Add a page to the document!
080: Page page = new Page(document); // Instantiates the page inside the document context.
081: document.getPages().add(page); // Puts the page in the pages collection.
082:
083: // 2. Create a content builder for the content stream!
084: PrimitiveFilter builder = new PrimitiveFilter(page);
085:
086: // 3. Inserting contents...
087: Dimension2D pageSize = page.getSize();
088: // 3.1. Showing the form on the page...
089: {
090: // Form 1.
091: builder.showXObject(form, new Point2D.Double(pageSize
092: .getWidth() / 2, pageSize.getHeight() / 2),
093: new Dimension(300, 0), AlignmentXEnum.Center,
094: AlignmentYEnum.Middle, 45);
095: // Form 2.
096: builder.showXObject(form, new Point2D.Double(0, pageSize
097: .getHeight()), new Dimension(0, 300),
098: AlignmentXEnum.Left, AlignmentYEnum.Bottom, 0);
099: // Form 3.
100: builder.showXObject(form, new Point2D.Double(pageSize
101: .getWidth(), pageSize.getHeight()), new Dimension(
102: 80, 200), AlignmentXEnum.Right,
103: AlignmentYEnum.Bottom, 0);
104: }
105: // 3.2. Showing the comments on the page...
106: {
107: BlockFilter blockFilter = new BlockFilter(builder);
108: Rectangle2D frame = new Rectangle2D.Double(18, 18, pageSize
109: .getWidth() * .5, pageSize.getHeight() * .5);
110: blockFilter.begin(frame, AlignmentXEnum.Justify,
111: AlignmentYEnum.Top);
112: StandardType1Font bodyFont = new StandardType1Font(
113: document, StandardType1Font.FamilyNameEnum.Courier,
114: true, false);
115: builder.setFont(bodyFont, 24);
116: blockFilter.showText("Page-to-form sample");
117: Dimension2D breakSize = new Dimension(0, 8);
118: blockFilter.showBreak(breakSize);
119: builder.setFont(bodyFont, 8);
120: blockFilter
121: .showText("This sample shows how to convert a page to a reusable form that can be placed multiple times on other pages scaling, rotating, anchoring and aligning it.");
122: blockFilter.showBreak(breakSize);
123: blockFilter
124: .showText("On this page you can see some of the above-mentioned transformations:");
125: breakSize.setSize(8, 8);
126: blockFilter.showBreak(breakSize);
127: blockFilter
128: .showText("1. anchored to the center of the page, rotated by 45 degrees counterclockwise, 300 point wide (preserved proportions);");
129: blockFilter.showBreak(breakSize);
130: blockFilter
131: .showText("2. anchored to the bottom-left corner of the page, 300 point high (preserved proportions);");
132: blockFilter.showBreak(breakSize);
133: blockFilter
134: .showText("3. anchored to the bottom-right of the page, 80 point wide and 200 point high (altered proportions).");
135: blockFilter.end();
136: }
137:
138: // 4. Flush the contents into the content stream!
139: builder.flush();
140: }
141: // </private>
142: // </interface>
143: // </dynamic>
144: }
|