123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- /* $Id$ */
-
- package org.apache.fop.render.pdf;
-
- import java.awt.Color;
- import java.awt.geom.AffineTransform;
- import java.io.IOException;
- import java.io.OutputStream;
-
- import org.apache.fop.pdf.PDFColor;
- import org.apache.fop.pdf.PDFDocument;
- import org.apache.fop.pdf.PDFFilterList;
- import org.apache.fop.pdf.PDFNumber;
- import org.apache.fop.pdf.PDFResourceContext;
- import org.apache.fop.pdf.PDFState;
- import org.apache.fop.pdf.PDFStream;
- import org.apache.fop.pdf.PDFTextUtil;
- import org.apache.fop.pdf.PDFXObject;
-
- /**
- * Generator class encapsulating all object references and state necessary to generate a
- * PDF content stream.
- */
- public class PDFContentGenerator {
-
- /** Controls whether comments are written to the PDF stream. */
- protected static final boolean WRITE_COMMENTS = true;
-
- private PDFDocument document;
- private OutputStream outputStream;
- private PDFResourceContext resourceContext;
-
- /** the current stream to add PDF commands to */
- private PDFStream currentStream;
-
- /** drawing state */
- protected PDFState currentState = null;
- /** Text generation utility holding the current font status */
- protected PDFTextUtil textutil;
-
-
- /**
- * Main constructor. Creates a new PDF stream and additional helper classes for text painting
- * and state management.
- * @param document the PDF document
- * @param out the output stream the PDF document is generated to
- * @param resourceContext the resource context
- */
- public PDFContentGenerator(PDFDocument document, OutputStream out,
- PDFResourceContext resourceContext) {
- this.document = document;
- this.outputStream = out;
- this.resourceContext = resourceContext;
- this.currentStream = document.getFactory()
- .makeStream(PDFFilterList.CONTENT_FILTER, false);
- this.textutil = new PDFTextUtil() {
- protected void write(String code) {
- currentStream.add(code);
- }
- };
-
- this.currentState = new PDFState();
- }
-
- /**
- * Returns the applicable resource context for the generator.
- * @return the resource context
- */
- public PDFDocument getDocument() {
- return this.document;
- }
-
- /**
- * Returns the output stream the PDF document is written to.
- * @return the output stream
- */
- public OutputStream getOutputStream() {
- return this.outputStream;
- }
-
- /**
- * Returns the applicable resource context for the generator.
- * @return the resource context
- */
- public PDFResourceContext getResourceContext() {
- return this.resourceContext;
- }
-
- /**
- * Returns the {@code PDFStream} associated with this instance.
- * @return the PDF stream
- */
- public PDFStream getStream() {
- return this.currentStream;
- }
-
- /**
- * Returns the {@code PDFState} associated with this instance.
- * @return the PDF state
- */
- public PDFState getState() {
- return this.currentState;
- }
-
- /**
- * Returns the {@code PDFTextUtil} associated with this instance.
- * @return the text utility
- */
- public PDFTextUtil getTextUtil() {
- return this.textutil;
- }
-
- /**
- * Flushes all queued PDF objects ready to be written to the output stream.
- * @throws IOException if an error occurs while flushing the PDF objects
- */
- public void flushPDFDoc() throws IOException {
- this.document.output(this.outputStream);
- }
-
- /**
- * Writes out a comment.
- * @param text text for the comment
- */
- protected void comment(String text) {
- if (WRITE_COMMENTS) {
- currentStream.add("% " + text + "\n");
- }
- }
-
- /** {@inheritDoc} */
- protected void saveGraphicsState() {
- endTextObject();
- currentState.push();
- currentStream.add("q\n");
- }
-
- /**
- * Restored the graphics state valid before the previous {@code #saveGraphicsState()}.
- * @param popState true if the state should also be popped, false if only the PDF command
- * should be issued
- */
- protected void restoreGraphicsState(boolean popState) {
- endTextObject();
- currentStream.add("Q\n");
- if (popState) {
- currentState.pop();
- }
- }
-
- /** {@inheritDoc} */
- protected void restoreGraphicsState() {
- restoreGraphicsState(true);
- }
-
- /** Indicates the beginning of a text object. */
- protected void beginTextObject() {
- if (!textutil.isInTextObject()) {
- textutil.beginTextObject();
- }
- }
-
- /** Indicates the end of a text object. */
- protected void endTextObject() {
- if (textutil.isInTextObject()) {
- textutil.endTextObject();
- }
- }
-
- /**
- * Converts a transformation matrix from millipoints to points.
- * @param transform the transformation matrix (in millipoints)
- * @return the converted transformation matrix (in points)
- */
- public AffineTransform toPoints(AffineTransform transform) {
- final double[] matrix = new double[6];
- transform.getMatrix(matrix);
- //Convert from millipoints to points
- matrix[4] /= 1000;
- matrix[5] /= 1000;
- return new AffineTransform(matrix);
- }
-
- /**
- * Concatenates the given transformation matrix with the current one.
- * @param transform the transformation matrix (in points)
- */
- public void concatenate(AffineTransform transform) {
- if (!transform.isIdentity()) {
- currentState.concatenate(transform);
- currentStream.add(CTMHelper.toPDFString(transform, false) + " cm\n");
- }
- }
-
- /**
- * Adds content to the stream.
- * @param content the PDF content
- */
- public void add(String content) {
- currentStream.add(content);
- }
-
- /**
- * Formats a float value (normally coordinates in points) as Strings.
- * @param value the value
- * @return the formatted value
- */
- public static final String format(float value) {
- return PDFNumber.doubleOut(value);
- }
-
- /**
- * Sets the current line width in points.
- * @param width line width in points
- */
- public void updateLineWidth(float width) {
- if (currentState.setLineWidth(width)) {
- //Only write if value has changed WRT the current line width
- currentStream.add(format(width) + " w\n");
- }
- }
-
- /**
- * Establishes a new foreground or fill color. In contrast to updateColor
- * this method does not check the PDFState for optimization possibilities.
- * @param col the color to apply
- * @param fill true to set the fill color, false for the foreground color
- * @param pdf StringBuffer to write the PDF code to
- *//*
- public void setColor(Color col, boolean fill, StringBuffer pdf) {
- assert pdf != null;
- }*/
-
- /**
- * Establishes a new foreground or fill color.
- * @param col the color to apply
- * @param fill true to set the fill color, false for the foreground color
- * @param stream the PDFStream to write the PDF code to
- */
- public void setColor(Color col, boolean fill, PDFStream stream) {
- assert stream != null;
- PDFColor color = new PDFColor(this.document, col);
- stream.add(color.getColorSpaceOut(fill));
- }
-
- /**
- * Establishes a new foreground or fill color.
- * @param col the color to apply
- * @param fill true to set the fill color, false for the foreground color
- */
- public void setColor(Color col, boolean fill) {
- setColor(col, fill, getStream());
- }
-
- /**
- * Establishes a new foreground or fill color. In contrast to updateColor
- * this method does not check the PDFState for optimization possibilities.
- * @param col the color to apply
- * @param fill true to set the fill color, false for the foreground color
- * @param pdf StringBuffer to write the PDF code to, if null, the code is
- * written to the current stream.
- */
- protected void setColor(Color col, boolean fill, StringBuffer pdf) {
- if (pdf != null) {
- PDFColor color = new PDFColor(this.document, col);
- pdf.append(color.getColorSpaceOut(fill));
- } else {
- setColor(col, fill, this.currentStream);
- }
- }
-
- /**
- * Establishes a new foreground or fill color.
- * @param col the color to apply (null skips this operation)
- * @param fill true to set the fill color, false for the foreground color
- * @param pdf StringBuffer to write the PDF code to, if null, the code is
- * written to the current stream.
- */
- public void updateColor(Color col, boolean fill, StringBuffer pdf) {
- if (col == null) {
- return;
- }
- boolean update = false;
- if (fill) {
- update = getState().setBackColor(col);
- } else {
- update = getState().setColor(col);
- }
-
- if (update) {
- setColor(col, fill, pdf);
- }
- }
-
- /**
- * Places a previously registered image at a certain place on the page.
- * @param x X coordinate
- * @param y Y coordinate
- * @param w width for image
- * @param h height for image
- * @param xobj the image XObject
- */
- public void placeImage(float x, float y, float w, float h, PDFXObject xobj) {
- saveGraphicsState();
- add(format(w) + " 0 0 "
- + format(-h) + " "
- + format(x) + " "
- + format(y + h)
- + " cm\n" + xobj.getName() + " Do\n");
- restoreGraphicsState();
- }
-
-
- }
|