<exclude name="org/apache/fop/render/pdf/PDFRenderer.class"/>
<exclude name="org/apache/fop/render/pdf/PDFXMLHandler*"/>
<include name="org/apache/fop/render/*RendererConfigurator**"/>
+ <include name="org/apache/fop/render/*State*"/>
<include name="org/apache/fop/pdf/**"/>
</patternset>
<!-- PS transcoder -->
package org.apache.fop.pdf;
-import java.io.Serializable;
-import java.util.List;
import java.util.Iterator;
-
-import java.awt.Color;
import java.awt.Paint;
import java.awt.Shape;
-import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
* It is impossible to optimise the result without analysing the all
* the possible combinations after completing.
*/
-public class PDFState {
-
- private Data data = new Data();
-
- private List stateStack = new java.util.ArrayList();
+public class PDFState extends org.apache.fop.render.AbstractState {
/**
* PDF State for storing graphics state.
*/
public PDFState() {
-
- }
-
- /**
- * Push the current state onto the stack.
- * This call should be used when the q operator is used
- * so that the state is known when popped.
- */
- public void push() {
- Data copy;
- try {
- copy = (Data)getData().clone();
- getData().resetTransform();
- } catch (CloneNotSupportedException e) {
- throw new RuntimeException(e.getMessage());
- }
- stateStack.add(copy);
- }
-
- /**
- * @return the currently valid state
- */
- public Data getData() {
- return data;
- }
-
- /**
- * Pop the state from the stack and set current values to popped state.
- * This should be called when a Q operator is used so
- * the state is restored to the correct values.
- * @return the restored state, null if the stack is empty
- */
- public Data pop() {
- if (getStackLevel() > 0) {
- Data popped = (Data)stateStack.remove(stateStack.size() - 1);
-
- data = popped;
- return popped;
- } else {
- return null;
- }
- }
-
- /**
- * Get the current stack level.
- *
- * @return the current stack level
- */
- public int getStackLevel() {
- return stateStack.size();
- }
-
- /**
- * Restore the state to a particular level.
- * this can be used to restore to a known level without making
- * multiple pop calls.
- *
- * @param stack the level to restore to
- */
- /*
- public void restoreLevel(int stack) {
- int pos = stack;
- while (stateStack.size() > pos + 1) {
- stateStack.remove(stateStack.size() - 1);
- }
- if (stateStack.size() > pos) {
- pop();
- }
- }*/
-
- /**
- * Set the current line dash.
- * Check if setting the line dash to the given values
- * will make a change and then set the state to the new values.
- *
- * @param array the line dash array
- * @param offset the line dash start offset
- * @return true if the line dash has changed
- */
- /*
- public boolean setLineDash(int[] array, int offset) {
- return false;
- }*/
-
- /**
- * Set the current line width.
- * @param width the line width in points
- * @return true if the line width has changed
- */
- public boolean setLineWidth(float width) {
- if (getData().lineWidth != width) {
- getData().lineWidth = width;
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Set the current color.
- * Check if the new color is a change and then set the current color.
- *
- * @param col the color to set
- * @return true if the color has changed
- */
- public boolean setColor(Color col) {
- if (!col.equals(getData().color)) {
- getData().color = col;
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Set the current background color.
- * Check if the background color will change and then set the new color.
- *
- * @param col the new background color
- * @return true if the background color has changed
- */
- public boolean setBackColor(Color col) {
- if (!col.equals(getData().backcolor)) {
- getData().backcolor = col;
- return true;
- } else {
- return false;
- }
}
/**
* @return true if the new paint changes the current paint
*/
public boolean setPaint(Paint p) {
- if (getData().paint == null) {
+ Paint paint = ((PDFData)getData()).paint;
+ if (paint == null) {
if (p != null) {
- getData().paint = p;
+ ((PDFData)getData()).paint = p;
return true;
}
- } else if (!data.paint.equals(p)) {
- getData().paint = p;
+ } else if (!paint.equals(p)) {
+ ((PDFData)getData()).paint = p;
return true;
}
return false;
* @return true if the clip will change the current clip.
*/
public boolean checkClip(Shape cl) {
- if (getData().clip == null) {
+ Shape clip = ((PDFData)getData()).clip;
+ if (clip == null) {
if (cl != null) {
return true;
}
- } else if (!new Area(getData().clip).equals(new Area(cl))) {
+ } else if (!new Area(clip).equals(new Area(cl))) {
return true;
}
//TODO check for clips that are larger than the current
* @param cl the new clip in the current state
*/
public void setClip(Shape cl) {
- if (getData().clip != null) {
- Area newClip = new Area(getData().clip);
+ Shape clip = ((PDFData)getData()).clip;
+ if (clip != null) {
+ Area newClip = new Area(clip);
newClip.intersect(new Area(cl));
- getData().clip = new GeneralPath(newClip);
+ ((PDFData)getData()).clip = new GeneralPath(newClip);
} else {
- getData().clip = cl;
+ ((PDFData)getData()).clip = cl;
}
}
/**
- * Check the current transform.
- * The transform for the current state is the combination of all
- * transforms in the current state. The parameter is compared
- * against this current transform.
- *
- * @param tf the transform the check against
- * @return true if the new transform is different then the current transform
- */
- public boolean checkTransform(AffineTransform tf) {
- return !tf.equals(getData().transform);
- }
-
- /**
- * Set a new transform.
- * This transform is appended to the transform of
- * the current graphic state.
- *
- * @param tf the transform to concatonate to the current level transform
- * @deprecated This method name is misleading. Use concatenate(AffineTransform) instead!
- */
- public void setTransform(AffineTransform tf) {
- concatenate(tf);
- }
-
- /**
- * Concatenates the given AffineTransform to the current one.
- * @param tf the transform to concatenate to the current level transform
- */
- public void concatenate(AffineTransform tf) {
- getData().concatenate(tf);
- }
-
- /**
- * Get the current transform.
- * This gets the combination of all transforms in the
- * current state.
- *
- * @return the calculate combined transform for the current state
- */
- public AffineTransform getTransform() {
- AffineTransform tf;
- AffineTransform at = new AffineTransform();
- for (Iterator iter = stateStack.iterator(); iter.hasNext();) {
- Data d = (Data)iter.next();
- tf = d.transform;
- at.concatenate(tf);
- }
- at.concatenate(getData().transform);
- return at;
- }
-
- /**
- * Get a copy of the base transform for the page. Used to translate
- * IPP/BPP values into X,Y positions when positioning is "fixed".
+ * Get the current stack level.
*
- * @return the base transform, or null if the state stack is empty
+ * @return the current stack level
*/
- public AffineTransform getBaseTransform() {
- if (stateStack.size() == 0) {
- return null;
- } else {
- Data baseData = (Data) stateStack.get(0);
- return (AffineTransform) baseData.transform.clone();
- }
+ public int getStackLevel() {
+ return getStateStack().size();
}
/**
PDFGState defaultState = PDFGState.DEFAULT;
PDFGState state;
- PDFGState newstate = new PDFGState();
- newstate.addValues(defaultState);
- for (Iterator iter = stateStack.iterator(); iter.hasNext();) {
- Data d = (Data)iter.next();
+ PDFGState newState = new PDFGState();
+ newState.addValues(defaultState);
+ for (Iterator iter = getStateStack().iterator(); iter.hasNext();) {
+ PDFData d = (PDFData)iter.next();
state = d.gstate;
if (state != null) {
- newstate.addValues(state);
+ newState.addValues(state);
}
}
- if (getData().gstate != null) {
- newstate.addValues(getData().gstate);
+ if (((PDFData)getData()).gstate != null) {
+ newState.addValues(((PDFData)getData()).gstate);
}
-
- return newstate;
+ return newState;
}
- public class Data implements Cloneable, Serializable {
+ private class PDFData extends org.apache.fop.render.AbstractState.AbstractData {
- public Color color = Color.black;
- public Color backcolor = Color.black;
- public Paint paint = null;
- public Paint backPaint = null;
- public int lineCap = 0;
- public int lineJoin = 0;
- public float lineWidth = 1;
- public float miterLimit = 0;
- public boolean text = false;
- public int dashOffset = 0;
- public int[] dashArray = new int[0];
- public AffineTransform transform = new AffineTransform();
- public float fontSize = 0;
- public String fontName = "";
- public Shape clip = null;
- public PDFGState gstate = null;
-
+ private static final long serialVersionUID = 3527950647293177764L;
+
+ private Paint paint = null;
+ private Paint backPaint = null;
+ private int lineCap = 0;
+ private int lineJoin = 0;
+ private float miterLimit = 0;
+ private boolean text = false;
+ private int dashOffset = 0;
+ private Shape clip = null;
+ private PDFGState gstate = null;
/** {@inheritDoc} */
public Object clone() throws CloneNotSupportedException {
- Data obj = new Data();
- obj.color = this.color;
- obj.backcolor = this.backcolor;
+ PDFData obj = (PDFData)super.clone();
obj.paint = this.paint;
obj.backPaint = this.paint;
obj.lineCap = this.lineCap;
obj.lineJoin = this.lineJoin;
- obj.lineWidth = this.lineWidth;
obj.miterLimit = this.miterLimit;
obj.text = this.text;
obj.dashOffset = this.dashOffset;
- obj.dashArray = this.dashArray;
- obj.transform = new AffineTransform(this.transform);
- obj.fontSize = this.fontSize;
- obj.fontName = this.fontName;
obj.clip = this.clip;
obj.gstate = this.gstate;
return obj;
}
- /**
- * Get the current Transform.
- */
- public AffineTransform getTransform() {
- return transform;
- }
-
- public void resetTransform() {
- transform = new AffineTransform();
- }
-
- /**
- * Concatenate the given AffineTransform with the current thus creating
- * a new viewport. Note that all concatenation operations are logged
- * so they can be replayed if necessary (ex. for block-containers with
- * "fixed" positioning.
- * @param at Transformation to perform
- */
- public void concatenate(AffineTransform at) {
- transform.concatenate(at);
- }
-
/** {@inheritDoc} */
public String toString() {
- return super.toString() + ", " + this.transform;
+ return super.toString()
+ + ", paint=" + paint
+ + ", backPaint=" + backPaint
+ + ", lineCap=" + lineCap
+ + ", miterLimit=" + miterLimit
+ + ", text=" + text
+ + ", dashOffset=" + dashOffset
+ + ", clip=" + clip
+ + ", gstate=" + gstate;
}
}
+
+ /** {@inheritDoc} */
+ protected AbstractData instantiateData() {
+ return new PDFData();
+ }
}
--- /dev/null
+/*
+ * 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;
+
+import java.awt.Color;
+import java.awt.geom.AffineTransform;
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Stack;
+
+/**
+ * A base class which holds information about the current rendering state.
+ */
+public abstract class AbstractState {
+ private AbstractData currentData = null;
+ private Stack/*<AbstractData>*/ stateStack = null;
+
+ /**
+ * Instantiates a new state data object
+ * @return a new state data object
+ */
+ protected abstract AbstractData instantiateData();
+
+ /**
+ * @return the currently valid state
+ */
+ public AbstractData getData() {
+ if (currentData == null) {
+ currentData = instantiateData();
+ }
+ return currentData;
+ }
+
+ /**
+ * Set the current color.
+ * Check if the new color is a change and then set the current color.
+ *
+ * @param col the color to set
+ * @return true if the color has changed
+ */
+ public boolean setColor(Color col) {
+ if (!col.equals(getData().color)) {
+ getData().color = col;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the color.
+ * @return the color
+ */
+ public Color getColor() {
+ if (getData().color == null) {
+ getData().color = Color.black;
+ }
+ return getData().color;
+ }
+
+ /**
+ * Get the background color.
+ * @return the background color
+ */
+ public Color getBackColor() {
+ if (getData().backColor == null) {
+ getData().backColor = Color.white;
+ }
+ return getData().backColor;
+ }
+
+ /**
+ * Set the current background color.
+ * Check if the new background color is a change and then set the current background color.
+ *
+ * @param col the background color to set
+ * @return true if the color has changed
+ */
+ public boolean setBackColor(Color col) {
+ if (!col.equals(getData().backColor)) {
+ getData().backColor = col;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Set the current font name
+ * @param internalFontName the internal font name
+ * @return true if the font name has changed
+ */
+ public boolean setFontName(String internalFontName) {
+ if (!internalFontName.equals(getData().fontName)) {
+ getData().fontName = internalFontName;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Gets the current font name
+ * @return the current font name
+ */
+ public String getFontName() {
+ return getData().fontName;
+ }
+
+ /**
+ * Gets the current font size
+ * @return the current font size
+ */
+ public int getFontSize() {
+ return getData().fontSize;
+ }
+
+ /**
+ * Set the current font size.
+ * Check if the font size is a change and then set the current font size.
+ *
+ * @param size the font size to set
+ * @return true if the font size has changed
+ */
+ public boolean setFontSize(int size) {
+ if (size != getData().fontSize) {
+ getData().fontSize = size;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Set the current line width.
+ * @param width the line width in points
+ * @return true if the line width has changed
+ */
+ public boolean setLineWidth(float width) {
+ if (getData().lineWidth != width) {
+ getData().lineWidth = width;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Gets the current line width
+ * @return the current line width
+ */
+ public float getLineWidth() {
+ return getData().lineWidth;
+ }
+
+ /**
+ * Sets the dash array (line type) for the current basic stroke
+ * @param dash the line dash array
+ * @return true if the dash array has changed
+ */
+ public boolean setDashArray(float[] dash) {
+ if (!Arrays.equals(dash, getData().dashArray)) {
+ getData().dashArray = dash;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the current transform.
+ * This gets the combination of all transforms in the
+ * current state.
+ *
+ * @return the calculate combined transform for the current state
+ */
+ public AffineTransform getTransform() {
+ AffineTransform at = new AffineTransform();
+ for (Iterator iter = getStateStack().iterator(); iter.hasNext();) {
+ AbstractData data = (AbstractData)iter.next();
+ AffineTransform stackTrans = data.getTransform();
+ at.concatenate(stackTrans);
+ }
+ AffineTransform currentTrans = getData().getTransform();
+ at.concatenate(currentTrans);
+ return at;
+ }
+
+ /**
+ * Check the current transform.
+ * The transform for the current state is the combination of all
+ * transforms in the current state. The parameter is compared
+ * against this current transform.
+ *
+ * @param tf the transform the check against
+ * @return true if the new transform is different then the current transform
+ */
+ public boolean checkTransform(AffineTransform tf) {
+ return !tf.equals(getData().getTransform());
+ }
+
+ /**
+ * Get a copy of the base transform for the page. Used to translate
+ * IPP/BPP values into X,Y positions when positioning is "fixed".
+ *
+ * @return the base transform, or null if the state stack is empty
+ */
+ public AffineTransform getBaseTransform() {
+ if (getStateStack().isEmpty()) {
+ return null;
+ } else {
+ AbstractData baseData = (AbstractData)getStateStack().get(0);
+ return (AffineTransform) baseData.getTransform().clone();
+ }
+ }
+
+ /**
+ * Concatenates the given AffineTransform to the current one.
+ * @param tf the transform to concatenate to the current level transform
+ */
+ public void concatenate(AffineTransform tf) {
+ getData().concatenate(tf);
+ }
+
+ /**
+ * Resets the current AffineTransform.
+ */
+ public void resetTransform() {
+ getData().resetTransform();
+ }
+
+ /**
+ * Push the current state onto the stack.
+ * This call should be used when the Q operator is used
+ * so that the state is known when popped.
+ */
+ public void push() {
+ AbstractData copy;
+ try {
+ copy = (AbstractData)getData().clone();
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ getStateStack().push(copy);
+ }
+
+ /**
+ * Pop the state from the stack and set current values to popped state.
+ * This should be called when a Q operator is used so
+ * the state is restored to the correct values.
+ * @return the restored state, null if the stack is empty
+ */
+ public AbstractData pop() {
+ if (!getStateStack().isEmpty()) {
+ this.currentData = (AbstractData)getStateStack().pop();
+ return this.currentData;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Clears the state stack
+ */
+ public void clear() {
+ getStateStack().clear();
+ currentData = null;
+ }
+
+ /**
+ * @return the state stack
+ */
+ protected Stack/*<AbstractData>*/ getStateStack() {
+ if (stateStack == null) {
+ stateStack = new java.util.Stack/*<AbstractData>*/();
+ }
+ return stateStack;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "stateStack=" + stateStack
+ + ", currentData=" + currentData;
+ }
+
+ /**
+ * A base state data holding object
+ */
+ public abstract class AbstractData implements Cloneable, Serializable {
+ /** The current color */
+ private Color color = null;
+
+ /** The current background color */
+ private Color backColor = null;
+
+ /** The current font name */
+ private String fontName = null;
+
+ /** The current font size */
+ private int fontSize = 0;
+
+ /** The current line width */
+ private float lineWidth = 0;
+
+ /** The dash array for the current basic stroke (line type) */
+ private float[] dashArray = null;
+
+ /** The current transform */
+ private AffineTransform transform = null;
+
+ /**
+ * Concatenate the given AffineTransform with the current thus creating
+ * a new viewport. Note that all concatenation operations are logged
+ * so they can be replayed if necessary (ex. for block-containers with
+ * "fixed" positioning.
+ * @param at Transformation to perform
+ */
+ public void concatenate(AffineTransform at) {
+ getTransform().concatenate(at);
+ }
+
+ /**
+ * Get the current AffineTransform.
+ * @return the current transform
+ */
+ public AffineTransform getTransform() {
+ if (transform == null) {
+ transform = new AffineTransform();
+ }
+ return transform;
+ }
+
+ /**
+ * Resets the current AffineTransform.
+ */
+ public void resetTransform() {
+ transform = new AffineTransform();
+ }
+
+ /** {@inheritDoc} */
+ public Object clone() throws CloneNotSupportedException {
+ AbstractData obj = instantiateData();
+ obj.color = this.color;
+ obj.backColor = this.backColor;
+ obj.fontName = this.fontName;
+ obj.fontSize = this.fontSize;
+ obj.lineWidth = this.lineWidth;
+ obj.dashArray = this.dashArray;
+ obj.transform = new AffineTransform(this.transform);
+ return obj;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "color=" + color
+ + ", backColor=" + backColor
+ + ", fontName=" + fontName
+ + ", fontSize=" + fontSize
+ + ", lineWidth=" + lineWidth
+ + ", dashArray=" + dashArray
+ + ", transform=" + transform;
+ }
+ }
+}
public final class AFPInfo {
/** see WIDTH */
private int width;
+
/** see HEIGHT */
private int height;
+
/** see XPOS */
private int x;
+
/** see YPOS */
private int y;
+
/** see HANDLER_CONFIGURATION */
private Configuration cfg;
/** see AFP_FONT_INFO */
private FontInfo fontInfo;
+
/** See AFP_DATASTREAM */
private AFPDataStream afpDataStream;
+
/** See AFP_STATE */
private AFPState afpState;
- /** see AFP_GRAYSCALE */
- private boolean color;
- /** see AFP_RESOLUTION */
- private int resolution;
- /** see AFP_BITS_PER_PIXEL */
- private int bitsPerPixel;
/**
* Returns the width.
* @return true if supports color
*/
public boolean isColorSupported() {
- return this.color;
+ return getState().isColorImages();
}
/**
* @return the resolution
*/
protected int getResolution() {
- return resolution;
+ return getState().getResolution();
}
/**
* @return the number of bits per pixel to use
*/
protected int getBitsPerPixel() {
- return bitsPerPixel;
+ return getState().getBitsPerPixel();
}
/**
this.y = y;
}
- /**
- * Sets the current resolution
- * @param resolution the current resolution
- */
- protected void setResolution(int resolution) {
- this.resolution = resolution;
- }
-
/**
* Sets the current font info
* @param fontInfo the current font info
/**
* Sets the AFP datastream
- * @param afpDataStream the AFP datastream
- */
- public void setAFPDataStream(AFPDataStream afpDataStream) {
- this.afpDataStream = afpDataStream;
- }
-
- /**
- * Sets if we are supporing color
- * @param color true if color is supported
- */
- public void setColor(boolean color) {
- this.color = color;
- }
-
- /**
- * Sets the number of bits per pixel
- * @param bitsPerPixel the number of bits per pixel
- */
- public void setBitsPerPixel(int bitsPerPixel) {
- this.bitsPerPixel = bitsPerPixel;
+ * @param dataStream the AFP datastream
+ */
+ public void setAFPDataStream(AFPDataStream dataStream) {
+ this.afpDataStream = dataStream;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "width=" + width
+ + ",height=" + height
+ + ",x=" + x
+ + ",y=" + y
+ + ",cfg=" + cfg
+ + ",fontInfo=" + fontInfo
+ + ",afpDatastream=" + afpDataStream
+ + ",afpState=" + afpState;
}
}
\ No newline at end of file
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.RenderedImage;
import java.io.FileNotFoundException;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.xmlgraphics.ps.ImageEncodingHelper;
+import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.area.Block;
-import org.apache.fop.area.BlockViewport;
-import org.apache.fop.area.BodyRegion;
import org.apache.fop.area.CTM;
import org.apache.fop.area.LineArea;
-import org.apache.fop.area.NormalFlow;
import org.apache.fop.area.OffDocumentItem;
import org.apache.fop.area.PageViewport;
-import org.apache.fop.area.RegionReference;
-import org.apache.fop.area.RegionViewport;
import org.apache.fop.area.Trait;
import org.apache.fop.area.inline.Image;
import org.apache.fop.area.inline.Leader;
import org.apache.fop.fonts.base14.Helvetica;
import org.apache.fop.fonts.base14.TimesRoman;
import org.apache.fop.render.AbstractPathOrientedRenderer;
+import org.apache.fop.render.AbstractState;
import org.apache.fop.render.Graphics2DAdapter;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.afp.extensions.AFPElementMapping;
import org.apache.fop.render.afp.fonts.OutlineFont;
import org.apache.fop.render.afp.modca.AFPConstants;
import org.apache.fop.render.afp.modca.AFPDataStream;
-import org.apache.fop.render.afp.modca.ImageObject;
import org.apache.fop.render.afp.modca.PageObject;
/**
*/
public class AFPRenderer extends AbstractPathOrientedRenderer {
- /**
- * The default afp renderer output resolution
- */
- public static final int DPI_240_RESOLUTION = 240;
+ private static final int X = 0;
+
+ private static final int Y = 1;
+
+ private static final int X1 = 0;
- /**
- * The afp factor for calculating resolutions (e.g. 72000/240 = 300)
- */
- private static final int DPI_CONVERSION_FACTOR = 72000;
+ private static final int Y1 = 1;
+
+ private static final int X2 = 2;
+
+ private static final int Y2 = 3;
/**
* The afp data stream object responsible for generating afp data
*/
private AFPDataStream afpDataStream = null;
- /**
- * The map of afp root extensions
- */
- // UNUSED
- // private HashMap rootExtensionMap = null;
/**
* The map of page segments
*/
private Map/*<String,String>*/pageSegmentsMap = null;
- /**
- * The fonts on the current page
- */
- private Map/*<String,AFPFontAttributes<*/currentPageFontMap = null;
-
- /**
- * The current color object
- */
- private Color currentColor = null;
-
- /**
- * The page font number counter, used to determine the next font reference
- */
- private int pageFontCounter = 0;
-
- /**
- * The current font family
- */
- // UNUSED
- // private String currentFontFamily = "";
- /**
- * The current font size
- */
- private int currentFontSize = 0;
-
- /**
- * The Options to be set on the AFPRenderer
- */
- // UNUSED
- // private Map afpOptions = null;
- /**
- * The page width
- */
- private int pageWidth = 0;
-
- /**
- * The page height
- */
- private int pageHeight = 0;
-
- /**
- * The current page sequence id
- */
- // UNUSED
- // private String pageSequenceId = null;
- /**
- * The portrait rotation
- */
- private int portraitRotation = 0;
-
- /**
- * The landscape rotation
- */
- private int landscapeRotation = 270;
-
- /**
- * The line cache, avoids drawing duplicate lines in tables.
- */
- // UNUSED
- // private HashSet lineCache = null;
- /**
- * The current x position for line drawing
- */
- // UNUSED
- // private float x;
- /**
- * The current y position for line drawing
- */
- // UNUSED
- // private float y;
/**
* The map of saved incomplete pages
*/
private Map pages = null;
- /**
- * Flag to the set the output object type for images
- */
- private boolean colorImages = false;
-
- /**
- * Default value for image depth
- */
- private int bitsPerPixel = 8;
-
- /**
- * The output resolution
- */
- private int resolution = DPI_240_RESOLUTION;
-
/** drawing state */
- private AFPState currentState = null;
+ private AFPState currentState = new AFPState();
+
+ private boolean gocaEnabled = false;
/**
* Constructor for AFPRenderer.
super();
}
- /**
- * Set up the font info
- *
- * @param inFontInfo
- * font info to set up
- */
+ /** {@inheritDoc} */
public void setupFontInfo(FontInfo inFontInfo) {
this.fontInfo = inFontInfo;
int num = 1;
for (Iterator it = super.embedFontInfoList.iterator(); it.hasNext();) {
AFPFontInfo afi = (AFPFontInfo) it.next();
AFPFont bf = (AFPFont) afi.getAFPFont();
- for (Iterator it2 = afi.getFontTriplets().iterator(); it2
- .hasNext();) {
+ for (Iterator it2 = afi.getFontTriplets().iterator(); it2.hasNext();) {
FontTriplet ft = (FontTriplet) it2.next();
this.fontInfo.addFontProperties("F" + num, ft.getName(), ft
.getStyle(), ft.getWeight());
}
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void setUserAgent(FOUserAgent agent) {
super.setUserAgent(agent);
}
- private Map/*<String,AFPFontAttributes>*/getCurrentPageFonts() {
- if (currentPageFontMap == null) {
- this.currentPageFontMap = new java.util.HashMap/*<String,AFPFontAttributes>*/();
- }
- return this.currentPageFontMap;
- }
-
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void startRenderer(OutputStream outputStream) throws IOException {
- this.currentColor = new Color(255, 255, 255);
- getAFPDataStream().setPortraitRotation(portraitRotation);
- getAFPDataStream().setLandscapeRotation(landscapeRotation);
- getAFPDataStream().setOutputStream(outputStream);
+ currentState.setColor(new Color(255, 255, 255));
+ getAFPDataStream().setPortraitRotation(currentState.getPortraitRotation());
+ afpDataStream.setLandscapeRotation(currentState.getLandscapeRotation());
+ afpDataStream.setOutputStream(outputStream);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void stopRenderer() throws IOException {
getAFPDataStream().write();
afpDataStream = null;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void startPageSequence(LineArea seqTitle) {
getAFPDataStream().endPageGroup();
- getAFPDataStream().startPageGroup();
+ afpDataStream.startPageGroup();
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public boolean supportsOutOfOrder() {
// return false;
return true;
}
- /**
- * Prepare a page for rendering. This is called if the renderer supports out
- * of order rendering. The renderer should prepare the page so that a page
- * further on in the set of pages can be rendered. The body of the page
- * should not be rendered. The page will be rendered at a later time by the
- * call to render page.
- *
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void preparePage(PageViewport page) {
- // initializeRootExtensions(page);
-
- // this.currentFontFamily = "";
- this.currentFontSize = 0;
- this.pageFontCounter = 0;
- this.currentPageFontMap = null;
- // this.lineCache = new HashSet();
-
- Rectangle2D bounds = page.getViewArea();
-
- this.pageWidth = mpts2units(bounds.getWidth());
- this.pageHeight = mpts2units(bounds.getHeight());
-
- // renderPageGroupExtensions(page);
-
final int pageRotation = 0;
+ int pageWidth = currentState.getPageWidth();
+ int pageHeight = currentState.getPageHeight();
getAFPDataStream().startPage(pageWidth, pageHeight, pageRotation,
getResolution(), getResolution());
renderPageObjectExtensions(page);
+ getPages().put(page, getAFPDataStream().savePage());
+ }
+
+ private Map/*<PageViewport, PageObject>*/ getPages() {
if (this.pages == null) {
- this.pages = new java.util.HashMap();
+ this.pages = new java.util.HashMap/*<PageViewport, PageObject>*/();
}
- this.pages.put(page, getAFPDataStream().savePage());
-
+ return this.pages;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void processOffDocumentItem(OffDocumentItem odi) {
// TODO
+ log.debug("NYI processOffDocumentItem(" + odi + ")");
}
/** {@inheritDoc} */
public Graphics2DAdapter getGraphics2DAdapter() {
return new AFPGraphics2DAdapter();
}
-
- /**
- * {@inheritDoc}
- */
+
+ /** {@inheritDoc} */
public void startVParea(CTM ctm, Rectangle2D clippingRect) {
- // dummy not used
- }
-
- /**
- * {@inheritDoc}
- */
- public void endVParea() {
- // dummy not used
- }
-
- /**
- * Renders a region viewport.
- * <p>
- *
- * The region may clip the area and it establishes a position from where the
- * region is placed.
- * </p>
- *
- * @param port
- * The region viewport to be rendered
- */
- public void renderRegionViewport(RegionViewport port) {
- if (port != null) {
- Rectangle2D view = port.getViewArea();
- // The CTM will transform coordinates relative to
- // this region-reference area into page coords, so
- // set origin for the region to 0,0.
- currentBPPosition = 0;
- currentIPPosition = 0;
-
- RegionReference regionReference = port.getRegionReference();
- handleRegionTraits(port);
-
- /*
- * _afpDataStream.startOverlay(mpts2units(view.getX()) ,
- * mpts2units(view.getY()) , mpts2units(view.getWidth()) ,
- * mpts2units(view.getHeight())
- * , rotation);
- */
-
- pushViewPortPos(new ViewPortPos(view, regionReference.getCTM()));
-
- if (regionReference.getRegionClass() == FO_REGION_BODY) {
- renderBodyRegion((BodyRegion) regionReference);
- } else {
- renderRegion(regionReference);
- }
- /*
- * _afpDataStream.endOverlay();
- */
- popViewPortPos();
+ saveGraphicsState();
+ if (ctm != null) {
+ AffineTransform at = ctm.toAffineTransform();
+ concatenateTransformationMatrix(at);
+ }
+ if (clippingRect != null) {
+ clipRect((float)clippingRect.getX() / 1000f,
+ (float)clippingRect.getY() / 1000f,
+ (float)clippingRect.getWidth() / 1000f,
+ (float)clippingRect.getHeight() / 1000f);
}
}
/** {@inheritDoc} */
- protected void renderBlockViewport(BlockViewport bv, List children) {
- // clip and position viewport if necessary
-
- // save positions
- int saveIP = currentIPPosition;
- int saveBP = currentBPPosition;
-
- CTM ctm = bv.getCTM();
- int borderPaddingStart = bv.getBorderAndPaddingWidthStart();
- int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore();
- // This is the content-rect
- float width = (float) bv.getIPD() / 1000f;
- float height = (float) bv.getBPD() / 1000f;
-
- if (bv.getPositioning() == Block.ABSOLUTE
- || bv.getPositioning() == Block.FIXED) {
-
- // For FIXED, we need to break out of the current viewports to the
- // one established by the page. We save the state stack for
- // restoration
- // after the block-container has been painted. See below.
- List breakOutList = null;
- if (bv.getPositioning() == Block.FIXED) {
- breakOutList = breakOutOfStateStack();
- }
-
- AffineTransform positionTransform = new AffineTransform();
- positionTransform.translate(bv.getXOffset(), bv.getYOffset());
-
- // "left/"top" (bv.getX/YOffset()) specify the position of the
- // content rectangle
- positionTransform.translate(-borderPaddingStart,
- -borderPaddingBefore);
-
- // skipping fox:transform here
-
- // saveGraphicsState();
- // Viewport position
- // concatenateTransformationMatrix(mptToPt(positionTransform));
-
- // Background and borders
- float bpwidth = (borderPaddingStart + bv
- .getBorderAndPaddingWidthEnd()) / 1000f;
- float bpheight = (borderPaddingBefore + bv
- .getBorderAndPaddingWidthAfter()) / 1000f;
- Point2D ptSrc = new Point(0, 0);
- Point2D ptDst = positionTransform.transform(ptSrc, null);
- Rectangle2D borderRect = new Rectangle2D.Double(ptDst.getX(), ptDst
- .getY(), 1000 * (width + bpwidth),
- 1000 * (height + bpheight));
- pushViewPortPos(new ViewPortPos(borderRect, new CTM(
- positionTransform)));
- drawBackAndBorders(bv, 0, 0, width + bpwidth, height + bpheight);
-
- // Shift to content rectangle after border painting
- AffineTransform contentRectTransform = new AffineTransform();
- contentRectTransform.translate(borderPaddingStart,
- borderPaddingBefore);
- // concatenateTransformationMatrix(mptToPt(contentRectTransform));
- ptSrc = new Point(0, 0);
- ptDst = contentRectTransform.transform(ptSrc, null);
- Rectangle2D contentRect = new Rectangle2D.Double(ptDst.getX(),
- ptDst.getY(), 1000 * width, 1000 * height);
- pushViewPortPos(new ViewPortPos(contentRect, new CTM(
- contentRectTransform)));
-
- // Clipping is not supported, yet
- // Rectangle2D clippingRect = null;
- // clippingRect = new Rectangle(0, 0, bv.getIPD(), bv.getBPD());
-
- // saveGraphicsState();
- // Set up coordinate system for content rectangle
- AffineTransform contentTransform = ctm.toAffineTransform();
- // concatenateTransformationMatrix(mptToPt(contentTransform));
- contentRect = new Rectangle2D.Double(0, 0, 1000 * width,
- 1000 * height);
- pushViewPortPos(new ViewPortPos(contentRect, new CTM(
- contentTransform)));
-
- currentIPPosition = 0;
- currentBPPosition = 0;
- renderBlocks(bv, children);
-
- popViewPortPos();
- popViewPortPos();
- // restoreGraphicsState();
- popViewPortPos();
- // restoreGraphicsState();
-
- if (breakOutList != null) {
- restoreStateStackAfterBreakOut(breakOutList);
- }
-
- currentIPPosition = saveIP;
- currentBPPosition = saveBP;
- } else {
-
- currentBPPosition += bv.getSpaceBefore();
-
- // borders and background in the old coordinate system
- handleBlockTraits(bv);
-
- // Advance to start of content area
- currentIPPosition += bv.getStartIndent();
-
- CTM tempctm = new CTM(containingIPPosition, currentBPPosition);
- ctm = tempctm.multiply(ctm);
-
- // Now adjust for border/padding
- currentBPPosition += borderPaddingBefore;
-
- Rectangle2D clippingRect = null;
- clippingRect = new Rectangle(currentIPPosition, currentBPPosition,
- bv.getIPD(), bv.getBPD());
-
- // startVParea(ctm, clippingRect);
- pushViewPortPos(new ViewPortPos(clippingRect, ctm));
-
- currentIPPosition = 0;
- currentBPPosition = 0;
- renderBlocks(bv, children);
- // endVParea();
- popViewPortPos();
-
- currentIPPosition = saveIP;
- currentBPPosition = saveBP;
-
- currentBPPosition += (int) (bv.getAllocBPD());
- }
+ public void endVParea() {
+ restoreGraphicsState();
}
/** {@inheritDoc} */
- protected void renderReferenceArea(Block block) {
- //TODO Remove this method once concatenateTransformationMatrix() is implemented
-
- // save position and offset
- int saveIP = currentIPPosition;
- int saveBP = currentBPPosition;
-
- //Establish a new coordinate system
- AffineTransform at = new AffineTransform();
- at.translate(currentIPPosition, currentBPPosition);
- at.translate(block.getXOffset(), block.getYOffset());
- at.translate(0, block.getSpaceBefore());
-
- if (!at.isIdentity()) {
- Rectangle2D contentRect
- = new Rectangle2D.Double(at.getTranslateX(), at.getTranslateY(),
- block.getAllocIPD(), block.getAllocBPD());
- pushViewPortPos(new ViewPortPos(contentRect, new CTM(at)));
- }
-
- currentIPPosition = 0;
- currentBPPosition = 0;
- handleBlockTraits(block);
-
- List children = block.getChildAreas();
- if (children != null) {
- renderBlocks(block, children);
- }
-
+ protected void concatenateTransformationMatrix(AffineTransform at) {
if (!at.isIdentity()) {
- popViewPortPos();
+ currentState.concatenate(at);
}
-
- // stacked and relative blocks effect stacking
- currentIPPosition = saveIP;
- currentBPPosition = saveBP;
}
-
- /** {@inheritDoc} */
- protected void renderFlow(NormalFlow flow) {
- // save position and offset
- int saveIP = currentIPPosition;
- int saveBP = currentBPPosition;
-
- //Establish a new coordinate system
- AffineTransform at = new AffineTransform();
- at.translate(currentIPPosition, currentBPPosition);
-
- if (!at.isIdentity()) {
- Rectangle2D contentRect
- = new Rectangle2D.Double(at.getTranslateX(), at.getTranslateY(),
- flow.getAllocIPD(), flow.getAllocBPD());
- pushViewPortPos(new ViewPortPos(contentRect, new CTM(at)));
- }
- currentIPPosition = 0;
- currentBPPosition = 0;
- super.renderFlow(flow);
-
- if (!at.isIdentity()) {
- popViewPortPos();
- }
-
- // stacked and relative blocks effect stacking
- currentIPPosition = saveIP;
- currentBPPosition = saveBP;
- }
-
-
/** {@inheritDoc} */
- protected void concatenateTransformationMatrix(AffineTransform at) {
- // Not used here since AFPRenderer defines its own renderBlockViewport()
- // method.
- throw new UnsupportedOperationException("NYI");
- }
-
- /**
- * {@inheritDoc}
- */
- public void renderPage(PageViewport pageViewport) {
-
- // initializeRootExtensions(page);
-
- // this.currentFontFamily = "";
- this.currentFontSize = 0;
- this.pageFontCounter = 0;
- this.currentPageFontMap = null;
- // this.lineCache = new HashSet();
+ public void renderPage(PageViewport pageViewport) throws IOException, FOPException {
+ currentState.clear();
Rectangle2D bounds = pageViewport.getViewArea();
+
+ AffineTransform basicPageTransform = new AffineTransform();
+ int resolution = currentState.getResolution();
+ double scale = (double)1 / (AFPConstants.DPI_72_MPTS / resolution);
+ basicPageTransform.scale(scale, scale);
- this.pageWidth = mpts2units(bounds.getWidth());
- this.pageHeight = mpts2units(bounds.getHeight());
-
- if (pages != null && pages.containsKey(pageViewport)) {
+ currentState.concatenate(basicPageTransform);
+ if (getPages().containsKey(pageViewport)) {
getAFPDataStream().restorePage(
- (PageObject) pages.remove(pageViewport));
-
+ (PageObject)getPages().remove(pageViewport));
} else {
- // renderPageGroupExtensions(page);
+ int pageWidth
+ = (int)Math.round(bounds.getWidth() / (AFPConstants.DPI_72_MPTS / resolution));
+ currentState.setPageWidth(pageWidth);
+ int pageHeight
+ = (int)Math.round(bounds.getHeight() / (AFPConstants.DPI_72_MPTS / resolution));
+ currentState.setPageHeight(pageHeight);
final int pageRotation = 0;
getAFPDataStream().startPage(pageWidth, pageHeight, pageRotation,
- getResolution(), getResolution());
+ resolution, resolution);
renderPageObjectExtensions(pageViewport);
-
}
+
+ super.renderPage(pageViewport);
- pushViewPortPos(new ViewPortPos());
-
- renderPageAreas(pageViewport.getPage());
-
- if (currentPageFontMap != null) {
- Iterator iter = currentPageFontMap.values().iterator();
- while (iter.hasNext()) {
- AFPFontAttributes afpFontAttributes = (AFPFontAttributes) iter
- .next();
-
- getAFPDataStream().createFont(
- (byte) afpFontAttributes.getFontReference(),
- afpFontAttributes.getFont(),
- afpFontAttributes.getPointSize());
- }
+ AFPPageFonts pageFonts = currentState.getPageFonts();
+ if (pageFonts != null && !pageFonts.isEmpty()) {
+ getAFPDataStream().addFontsToCurrentPage(pageFonts);
}
getAFPDataStream().endPage();
-
- popViewPortPos();
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void clip() {
// TODO
+ log.debug("NYI clip()");
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void clipRect(float x, float y, float width, float height) {
// TODO
+ log.debug("NYI clipRect(x=" + x + ",y=" + y + ",width=" + width + ", height=" + height + ")");
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void moveTo(float x, float y) {
// TODO
+ log.debug("NYI moveTo(x=" + x + ",y=" + y + ")");
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void lineTo(float x, float y) {
// TODO
+ log.debug("NYI lineTo(x=" + x + ",y=" + y + ")");
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void closePath() {
// TODO
+ log.debug("NYI closePath()");
}
- /**
- * {@inheritDoc}
- */
+ private int[] mpts2units(float[] srcPts, float[] dstPts) {
+ return transformPoints(srcPts, dstPts, true);
+ }
+
+ private int[] pts2units(float[] srcPts, float[] dstPts) {
+ return transformPoints(srcPts, dstPts, false);
+ }
+
+ private int[] mpts2units(float[] srcPts) {
+ return transformPoints(srcPts, null, true);
+ }
+
+ private int[] pts2units(float[] srcPts) {
+ return transformPoints(srcPts, null, false);
+ }
+
+ /** {@inheritDoc} */
public void fillRect(float x, float y, float width, float height) {
-// getAFPDataStream().createShading(
-// pts2units(x), pts2units(y), pts2units(width), pts2units(height),
-// currentColor);
- getAFPDataStream().createLine(pts2units(x), pts2units(y),
- pts2units(x + width), pts2units(y), pts2units(height),
- currentColor);
+ float[] srcPts = new float[] {x * 1000, y * 1000};
+ float[] dstPts = new float[srcPts.length];
+ int[] coords = mpts2units(srcPts, dstPts);
+ int resolution = currentState.getResolution();
+ int x2 = Math.round(dstPts[X] + ((width * 1000) / (AFPConstants.DPI_72_MPTS / resolution)));
+ int thickness = Math.round((height * 1000) / (AFPConstants.DPI_72_MPTS / resolution));
+ getAFPDataStream().createLine(
+ coords[X],
+ coords[Y],
+ x2,
+ coords[Y],
+ thickness,
+ currentState.getColor());
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void drawBorderLine(float x1, float y1, float x2, float y2,
boolean horz, boolean startOrBefore, int style, Color col) {
- float w = x2 - x1;
- float h = y2 - y1;
- if ((w < 0) || (h < 0)) {
+ float[] srcPts = new float[] {x1 * 1000, y1 * 1000, x2 * 1000, y2 * 1000};
+ float[] dstPts = new float[srcPts.length];
+ int[] coords = mpts2units(srcPts, dstPts);
+
+ float width = dstPts[X2] - dstPts[X1];
+ float height = dstPts[Y2] - dstPts[Y1];
+ if ((width < 0) || (height < 0)) {
log.error("Negative extent received. Border won't be painted.");
return;
}
switch (style) {
case Constants.EN_DOUBLE:
if (horz) {
- float h3 = h / 3;
- float ym1 = y1;
- float ym2 = ym1 + h3 + h3;
- getAFPDataStream().createLine(pts2units(x1), pts2units(ym1),
- pts2units(x2), pts2units(ym1), pts2units(h3), col);
- getAFPDataStream().createLine(pts2units(x1), pts2units(ym2),
- pts2units(x2), pts2units(ym2), pts2units(h3), col);
+ float h3 = height / 3;
+ float ym2 = dstPts[Y1] + h3 + h3;
+ afpDataStream.createLine(
+ coords[X1],
+ coords[Y1],
+ coords[X2],
+ coords[Y1],
+ Math.round(h3),
+ col);
+ afpDataStream.createLine(
+ coords[X1],
+ Math.round(ym2),
+ coords[X2],
+ Math.round(ym2),
+ Math.round(h3),
+ col);
} else {
- float w3 = w / 3;
- float xm1 = x1;
- float xm2 = xm1 + w3 + w3;
- getAFPDataStream().createLine(pts2units(xm1), pts2units(y1),
- pts2units(xm1), pts2units(y2), pts2units(w3), col);
- getAFPDataStream().createLine(pts2units(xm2), pts2units(y1),
- pts2units(xm2), pts2units(y2), pts2units(w3), col);
+ float w3 = width / 3;
+ float xm2 = dstPts[X1] + w3 + w3;
+ afpDataStream.createLine(
+ coords[X1],
+ coords[Y1],
+ coords[X1],
+ coords[Y2],
+ Math.round(w3),
+ col);
+ afpDataStream.createLine(
+ Math.round(xm2),
+ coords[Y1],
+ Math.round(xm2),
+ coords[Y2],
+ Math.round(w3),
+ col);
}
break;
case Constants.EN_DASHED:
if (horz) {
- float w2 = 2 * h;
- while (x1 + w2 < x2) {
- getAFPDataStream().createLine(pts2units(x1), pts2units(y1),
- pts2units(x1 + w2), pts2units(y1), pts2units(h),
+ float w2 = 2 * height;
+ while (coords[X1] + w2 < coords[X2]) {
+ afpDataStream.createLine(
+ coords[X1],
+ coords[Y1],
+ coords[X1] + Math.round(w2),
+ coords[Y1],
+ Math.round(height),
col);
- x1 += 2 * w2;
+ coords[X1] += 2 * w2;
}
} else {
- float h2 = 2 * w;
- while (y1 + h2 < y2) {
- getAFPDataStream().createLine(pts2units(x1), pts2units(y1),
- pts2units(x1), pts2units(y1 + h2), pts2units(w),
+ float h2 = 2 * width;
+ while (coords[Y1] + h2 < coords[Y2]) {
+ afpDataStream.createLine(
+ coords[X1],
+ coords[Y2],
+ coords[X1],
+ coords[Y1] + Math.round(h2),
+ Math.round(width),
col);
- y1 += 2 * h2;
+ coords[Y1] += 2 * h2;
}
}
break;
case Constants.EN_DOTTED:
if (horz) {
- while (x1 + h < x2) {
- getAFPDataStream()
- .createLine(pts2units(x1), pts2units(y1),
- pts2units(x1 + h), pts2units(y1),
- pts2units(h), col);
- x1 += 2 * h;
+ while (coords[X1] + height < coords[X2]) {
+ afpDataStream.createLine(
+ coords[X1],
+ coords[Y1],
+ coords[X1] + Math.round(height),
+ coords[Y1],
+ Math.round(height),
+ col
+ );
+ coords[X1] += 2 * height;
}
} else {
- while (y1 + w < y2) {
- getAFPDataStream()
- .createLine(pts2units(x1), pts2units(y1),
- pts2units(x1), pts2units(y1 + w),
- pts2units(w), col);
- y1 += 2 * w;
+ while (y1 + width < y2) {
+ afpDataStream.createLine(
+ coords[X1],
+ coords[Y1],
+ coords[X1],
+ coords[Y1] + Math.round(width),
+ Math.round(width),
+ col);
+ coords[Y1] += 2 * width;
}
}
break;
if (horz) {
Color uppercol = lightenColor(col, -colFactor);
Color lowercol = lightenColor(col, colFactor);
- float h3 = h / 3;
- float ym1 = y1;
- getAFPDataStream().createLine(pts2units(x1), pts2units(ym1),
- pts2units(x2), pts2units(ym1), pts2units(h3), uppercol);
- getAFPDataStream().createLine(pts2units(x1),
- pts2units(ym1 + h3), pts2units(x2),
- pts2units(ym1 + h3), pts2units(h3), col);
- getAFPDataStream().createLine(pts2units(x1),
- pts2units(ym1 + h3 + h3), pts2units(x2),
- pts2units(ym1 + h3 + h3), pts2units(h3), lowercol);
+ float h3 = height / 3;
+ afpDataStream.createLine(
+ coords[X1],
+ coords[Y1],
+ coords[X2],
+ coords[Y1],
+ Math.round(h3),
+ uppercol);
+ afpDataStream.createLine(
+ coords[X1],
+ Math.round(dstPts[Y1] + h3),
+ coords[X2],
+ Math.round(dstPts[Y1] + h3),
+ Math.round(h3),
+ col);
+ afpDataStream.createLine(
+ coords[X1],
+ Math.round(dstPts[Y1] + h3 + h3),
+ coords[X2],
+ Math.round(dstPts[Y1] + h3 + h3),
+ Math.round(h3),
+ lowercol);
} else {
Color leftcol = lightenColor(col, -colFactor);
Color rightcol = lightenColor(col, colFactor);
- float w3 = w / 3;
- float xm1 = x1 + (w3 / 2);
- getAFPDataStream().createLine(pts2units(xm1), pts2units(y1),
- pts2units(xm1), pts2units(y2), pts2units(w3), leftcol);
- getAFPDataStream().createLine(pts2units(xm1 + w3),
- pts2units(y1), pts2units(xm1 + w3), pts2units(y2),
- pts2units(w3), col);
- getAFPDataStream().createLine(pts2units(xm1 + w3 + w3),
- pts2units(y1), pts2units(xm1 + w3 + w3), pts2units(y2),
- pts2units(w3), rightcol);
+ float w3 = width / 3;
+ float xm1 = dstPts[X1] + (w3 / 2);
+ afpDataStream.createLine(
+ Math.round(xm1),
+ coords[Y1],
+ Math.round(xm1),
+ coords[Y2],
+ Math.round(w3),
+ leftcol);
+ afpDataStream.createLine(
+ Math.round(xm1 + w3),
+ coords[Y1],
+ Math.round(xm1 + w3),
+ coords[Y2],
+ Math.round(w3),
+ col);
+ afpDataStream.createLine(
+ Math.round(xm1 + w3 + w3),
+ coords[Y1],
+ Math.round(xm1 + w3 + w3),
+ coords[Y2],
+ Math.round(w3),
+ rightcol);
}
break;
}
case Constants.EN_INSET:
case Constants.EN_OUTSET:
default:
- getAFPDataStream().createLine(pts2units(x1), pts2units(y1),
- pts2units(horz ? x2 : x1), pts2units(horz ? y1 : y2),
- pts2units(Math.abs(horz ? (y2 - y1) : (x2 - x1))), col);
+ afpDataStream.createLine(
+ coords[X1],
+ coords[Y1],
+ (horz ? coords[X2] : coords[X1]),
+ (horz ? coords[Y1] : coords[Y2]),
+ Math.abs(Math.round(horz ? height : width)),
+ col);
}
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected RendererContext createRendererContext(int x, int y, int width,
int height, Map foreignAttributes) {
RendererContext context;
context = super.createRendererContext(x, y, width, height,
foreignAttributes);
- context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE, Boolean
- .valueOf(!this.colorImages));
context.setProperty(AFPRendererContextConstants.AFP_FONT_INFO,
this.fontInfo);
- context.setProperty(AFPRendererContextConstants.AFP_RESOLUTION,
- new Integer(this.resolution));
- context.setProperty(AFPRendererContextConstants.AFP_BITS_PER_PIXEL,
- new Integer(this.bitsPerPixel));
context.setProperty(AFPRendererContextConstants.AFP_DATASTREAM,
getAFPDataStream());
context.setProperty(AFPRendererContextConstants.AFP_STATE, getState());
/** {@inheritDoc} */
public void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) {
uri = URISpecification.getURL(uri);
- getState().setImageUri(uri);
+ currentState.setImageUri(uri);
Rectangle posInt = new Rectangle((int) pos.getX(), (int) pos.getY(),
(int) pos.getWidth(), (int) pos.getHeight());
Point origin = new Point(currentIPPosition, currentBPPosition);
int x = origin.x + posInt.x;
int y = origin.y + posInt.y;
-
+
String name = (String)getPageSegments().get(uri);
if (name != null) {
- getAFPDataStream().createIncludePageSegment(name, mpts2units(x),
- mpts2units(y));
+ float[] srcPts = {x, y};
+ int[] coords = mpts2units(srcPts);
+ getAFPDataStream().createIncludePageSegment(name, coords[X], coords[Y]);
} else {
ImageManager manager = getUserAgent().getFactory().getImageManager();
ImageInfo info = null;
ImageRawCCITTFax ccitt = (ImageRawCCITTFax) img;
in = ccitt.createInputStream();
byte[] buf = IOUtils.toByteArray(in);
- int afpx = mpts2units(posInt.x + currentIPPosition);
- int afpy = mpts2units(posInt.y + currentBPPosition);
- int afpw = mpts2units(posInt.getWidth());
- int afph = mpts2units(posInt.getHeight());
- int afpres = getResolution();
+ float[] srcPts = new float[] {
+ posInt.x + currentIPPosition,
+ posInt.y + currentBPPosition,
+ (float)posInt.getWidth(),
+ (float)posInt.getHeight()
+ };
+ int[] coords = mpts2units(srcPts);
String mimeType = info.getMimeType();
// create image object parameters
ImageObjectInfo imageObjectInfo = new ImageObjectInfo();
+ imageObjectInfo.setBuffered(false);
imageObjectInfo.setUri(uri);
imageObjectInfo.setMimeType(mimeType);
ObjectAreaInfo objectAreaInfo = new ObjectAreaInfo();
- objectAreaInfo.setX(afpx);
- objectAreaInfo.setY(afpy);
- objectAreaInfo.setWidth(afpw);
- objectAreaInfo.setHeight(afph);
- objectAreaInfo.setWidthRes(afpres);
- objectAreaInfo.setHeightRes(afpres);
+ objectAreaInfo.setX(coords[X]);
+ objectAreaInfo.setY(coords[Y]);
+ int resolution = currentState.getResolution();
+ int w = Math.round(
+ ((float)posInt.getWidth() * 1000)
+ / (AFPConstants.DPI_72_MPTS / resolution));
+ int h = Math.round(
+ ((float)posInt.getHeight() * 1000)
+ / (AFPConstants.DPI_72_MPTS / resolution));
+ objectAreaInfo.setWidth(w);
+ objectAreaInfo.setHeight(h);
+ objectAreaInfo.setWidthRes(resolution);
+ objectAreaInfo.setHeightRes(resolution);
imageObjectInfo.setObjectAreaInfo(objectAreaInfo);
imageObjectInfo.setData(buf);
imageObjectInfo.setDataHeight(ccitt.getSize().getHeightPx());
imageObjectInfo.setDataWidth(ccitt.getSize().getWidthPx());
- imageObjectInfo.setColor(colorImages);
- imageObjectInfo.setBitsPerPixel(bitsPerPixel);
+ imageObjectInfo.setColor(currentState.isColorImages());
+ imageObjectInfo.setBitsPerPixel(currentState.getBitsPerPixel());
imageObjectInfo.setCompression(ccitt.getCompression());
imageObjectInfo.setResourceInfoFromForeignAttributes(foreignAttributes);
getAFPDataStream().createObject(imageObjectInfo);
* the x coordinate (in mpt)
* @param y
* the y coordinate (in mpt)
- * @param w
+ * @param width
* the width of the viewport (in mpt)
- * @param h
+ * @param height
* the height of the viewport (in mpt)
* @param foreignAttributes
* a mapping of foreign attributes
*/
public void drawBufferedImage(ImageInfo imageInfo, RenderedImage image,
- int imageRes, int x, int y, int w, int h, Map foreignAttributes) {
+ int imageRes, int x, int y, int width, int height, Map foreignAttributes) {
ByteArrayOutputStream baout = new ByteArrayOutputStream();
try {
// Serialize image
}
ObjectAreaInfo objectAreaInfo = new ObjectAreaInfo();
- objectAreaInfo.setX(mpts2units(x));
- objectAreaInfo.setY(mpts2units(y));
- objectAreaInfo.setWidth(mpts2units(w));
- objectAreaInfo.setHeight(mpts2units(h));
+
+ float[] srcPts = new float[] {x, y};
+ int[] coords = mpts2units(srcPts);
+ objectAreaInfo.setX(coords[X]);
+ objectAreaInfo.setY(coords[Y]);
+ int resolution = currentState.getResolution();
+ int w = Math.round(
+ (width * 1000)
+ / (AFPConstants.DPI_72_MPTS / resolution));
+ int h = Math.round(
+ (height * 1000)
+ / (AFPConstants.DPI_72_MPTS / resolution));
+ objectAreaInfo.setWidth(w);
+ objectAreaInfo.setHeight(h);
+
objectAreaInfo.setWidthRes(imageRes);
objectAreaInfo.setHeightRes(imageRes);
imageObjectInfo.setObjectAreaInfo(objectAreaInfo);
-
+
imageObjectInfo.setData(baout.toByteArray());
imageObjectInfo.setDataHeight(image.getHeight());
imageObjectInfo.setDataWidth(image.getWidth());
- imageObjectInfo.setColor(colorImages);
- imageObjectInfo.setBitsPerPixel(bitsPerPixel);
+ imageObjectInfo.setColor(currentState.isColorImages());
+ imageObjectInfo.setBitsPerPixel(currentState.getBitsPerPixel());
imageObjectInfo.setResourceInfoFromForeignAttributes(foreignAttributes);
getAFPDataStream().createObject(imageObjectInfo);
}
- /**
- * Establishes a new foreground or fill color. {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void updateColor(Color col, boolean fill) {
if (fill) {
- currentColor = col;
+ currentState.setColor(col);
}
}
/** {@inheritDoc} */
- public List breakOutOfStateStack() {
- log.debug("Block.FIXED --> break out");
- List breakOutList = new java.util.ArrayList();
- //Don't pop the last ViewPortPos (created by renderPage())
- while (this.viewPortPositions.size() > 1) {
- breakOutList.add(0, popViewPortPos());
+ public void restoreStateStackAfterBreakOut(List breakOutList) {
+ log.debug("Block.FIXED --> restoring context after break-out");
+ AbstractState.AbstractData data;
+ Iterator it = breakOutList.iterator();
+ while (it.hasNext()) {
+ data = (AbstractState.AbstractData)it.next();
+ saveGraphicsState();
+ concatenateTransformationMatrix(data.getTransform());
}
- return breakOutList;
}
/** {@inheritDoc} */
- public void restoreStateStackAfterBreakOut(List breakOutList) {
- log.debug("Block.FIXED --> restoring context after break-out");
- for (int i = 0, c = breakOutList.size(); i < c; i++) {
- ViewPortPos vps = (ViewPortPos)breakOutList.get(i);
- pushViewPortPos(vps);
+ protected List breakOutOfStateStack() {
+ log.debug("Block.FIXED --> break out");
+ List breakOutList = new java.util.ArrayList();
+ AbstractState.AbstractData data;
+ while (true) {
+ data = currentState.getData();
+ if (currentState.pop() == null) {
+ break;
+ }
+ breakOutList.add(0, data); //Insert because of stack-popping
}
+ return breakOutList;
}
- /** Saves the graphics state of the rendering engine. */
+ /** {@inheritDoc} */
public void saveGraphicsState() {
-
+ currentState.push();
}
- /** Restores the last graphics state of the rendering engine. */
+ /** {@inheritDoc} */
public void restoreGraphicsState() {
-
+ currentState.pop();
}
/** Indicates the beginning of a text object. */
public void beginTextObject() {
-
+ //TODO maybe?
+ log.debug("NYI beginTextObject()");
}
/** Indicates the end of a text object. */
public void endTextObject() {
-
+ //TODO maybe?
+ log.debug("NYI endTextObject()");
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void renderImage(Image image, Rectangle2D pos) {
drawImage(image.getURL(), pos, image.getForeignAttributes());
}
- /**
- * {@inheritDoc}
- */
- public void renderText(TextArea text) {
+ /** {@inheritDoc} */
+ public void renderText(TextArea text) {
+ log.debug(text.getText());
renderInlineAreaBackAndBorders(text);
String name = getInternalFontNameForArea(text);
- this.currentFontSize = ((Integer) text.getTrait(Trait.FONT_SIZE))
- .intValue();
- AFPFont font = (AFPFont) fontInfo.getFonts().get(name);
-
- Color col = (Color) text.getTrait(Trait.COLOR);
-
- int vsci = mpts2units(font.getWidth(' ', currentFontSize) / 1000
- + text.getTextWordSpaceAdjust()
- + text.getTextLetterSpaceAdjust());
-
- // word.getOffset() = only height of text itself
- // currentBlockIPPosition: 0 for beginning of line; nonzero
- // where previous line area failed to take up entire allocated space
- int rx = currentIPPosition + text.getBorderAndPaddingWidthStart();
- int bl = currentBPPosition + text.getOffset()
- + text.getBaselineOffset();
+ int fontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
+ currentState.setFontSize(fontSize);
+ AFPFont font = (AFPFont)fontInfo.getFonts().get(name);
// Set letterSpacing
// float ls = fs.getLetterSpacing() / this.currentFontSize;
- String worddata = text.getText();
-
// Create an AFPFontAttributes object from the current font details
- AFPFontAttributes afpFontAttributes = new AFPFontAttributes(name, font,
- currentFontSize);
+ AFPFontAttributes afpFontAttributes
+ = new AFPFontAttributes(name, font, fontSize);
- if (!getCurrentPageFonts().containsKey(afpFontAttributes.getFontKey())) {
+ AFPPageFonts pageFonts = currentState.getPageFonts();
+ if (!pageFonts.containsKey(afpFontAttributes.getFontKey())) {
// Font not found on current page, so add the new one
- this.pageFontCounter++;
- afpFontAttributes.setFontReference(pageFontCounter);
- getCurrentPageFonts().put(afpFontAttributes.getFontKey(),
- afpFontAttributes);
+ afpFontAttributes.setFontReference(currentState.incrementPageFontCount());
+ pageFonts.put(afpFontAttributes.getFontKey(), afpFontAttributes);
} else {
// Use the previously stored font attributes
- afpFontAttributes = (AFPFontAttributes) currentPageFontMap
- .get(afpFontAttributes.getFontKey());
+ afpFontAttributes = (AFPFontAttributes) pageFonts.get(afpFontAttributes.getFontKey());
}
// Try and get the encoding to use for the font
String encoding = null;
try {
- encoding = font.getCharacterSet(currentFontSize).getEncoding();
+ encoding = font.getCharacterSet(fontSize).getEncoding();
} catch (Throwable ex) {
encoding = AFPConstants.EBCIDIC_ENCODING;
log.warn("renderText():: Error getting encoding for font '"
+ encoding);
}
+ byte[] data = null;
try {
- getAFPDataStream().createText(afpFontAttributes.getFontReference(),
- mpts2units(rx), mpts2units(bl), col, vsci,
- mpts2units(text.getTextLetterSpaceAdjust()),
- worddata.getBytes(encoding));
+ String worddata = text.getText();
+ data = worddata.getBytes(encoding);
} catch (UnsupportedEncodingException usee) {
log.error("renderText:: Font " + afpFontAttributes.getFontKey()
+ " caused UnsupportedEncodingException");
+ return;
}
+ int fontReference = afpFontAttributes.getFontReference();
+
+ int x = (currentIPPosition + text.getBorderAndPaddingWidthStart());
+ int y = (currentBPPosition + text.getOffset() + text.getBaselineOffset());
+ float[] srcPts = new float[] {x, y};
+ int[] coords = mpts2units(srcPts);
+
+ Color color = (Color) text.getTrait(Trait.COLOR);
+
+ int variableSpaceCharacterIncrement = font.getWidth(' ', fontSize) / 1000
+ + text.getTextWordSpaceAdjust()
+ + text.getTextLetterSpaceAdjust();
+ int resolution = currentState.getResolution();
+ variableSpaceCharacterIncrement /= (AFPConstants.DPI_72_MPTS / resolution);
+
+ int interCharacterAdjustment = text.getTextLetterSpaceAdjust();
+ interCharacterAdjustment /= (AFPConstants.DPI_72_MPTS / resolution);
+
+ AFPTextDataInfo textDataInfo = new AFPTextDataInfo();
+ textDataInfo.setFontReference(fontReference);
+ textDataInfo.setX(coords[X]);
+ textDataInfo.setY(coords[Y]);
+ textDataInfo.setColor(color);
+ textDataInfo.setVariableSpaceCharacterIncrement(variableSpaceCharacterIncrement);
+ textDataInfo.setInterCharacterAdjustment(interCharacterAdjustment);
+ textDataInfo.setData(data);
+ getAFPDataStream().createText(textDataInfo);
+ // word.getOffset() = only height of text itself
+ // currentBlockIPPosition: 0 for beginning of line; nonzero
+ // where previous line area failed to take up entire allocated space
+
super.renderText(text);
- renderTextDecoration(font, currentFontSize, text, bl, rx);
+ renderTextDecoration(font, fontSize, text, coords[Y], coords[X]);
}
/**
super.renderLeader(area);
}
- /**
- * Sets the AFPRenderer options
- *
- * @param options
- * the <code>Map</code> containing the options
- */
- // UNUSED
- // public void setOptions(Map options) {
- //
- // this.afpOptions = options;
- //
- // }
- /**
- * Determines the orientation from the string representation, this method
- * guarantees to return a value of either 0, 90, 180 or 270.
- *
- * @return the orientation
- */
- // UNUSED
- // private int getOrientation(String orientationString) {
- //
- // int orientation = 0;
- // if (orientationString != null && orientationString.length() > 0) {
- // try {
- // orientation = Integer.parseInt(orientationString);
- // } catch (NumberFormatException nfe) {
- // log.error("Cannot use orientation of " + orientation
- // + " defaulting to zero.");
- // orientation = 0;
- // }
- // } else {
- // orientation = 0;
- // }
- // switch (orientation) {
- // case 0:
- // break;
- // case 90:
- // break;
- // case 180:
- // break;
- // case 270:
- // break;
- // default:
- // log.error("Cannot use orientation of " + orientation
- // + " defaulting to zero.");
- // orientation = 0;
- // break;
- // }
- //
- // return orientation;
- //
- // }
/**
* Sets the rotation to be used for portrait pages, valid values are 0
* (default), 90, 180, 270.
* The rotation in degrees.
*/
public void setPortraitRotation(int rotation) {
- if (rotation == 0 || rotation == 90 || rotation == 180
- || rotation == 270) {
- portraitRotation = rotation;
- } else {
- throw new IllegalArgumentException(
- "The portrait rotation must be one"
- + " of the values 0, 90, 180, 270");
-
- }
+ currentState.setPortraitRotation(rotation);
}
/**
* The rotation in degrees.
*/
public void setLandscapeRotation(int rotation) {
- if (rotation == 0 || rotation == 90 || rotation == 180
- || rotation == 270) {
- landscapeRotation = rotation;
- } else {
- throw new IllegalArgumentException(
- "The landscape rotation must be one"
- + " of the values 0, 90, 180, 270");
- }
+ currentState.setLandscapeRotation(rotation);
}
/**
}
- /**
- * Converts FOP mpt measurement to afp measurement units
- *
- * @param mpt
- * the millipoints value
- */
- private int mpts2units(int mpt) {
- return mpts2units((double) mpt);
- }
-
- /**
- * Converts FOP pt measurement to afp measurement units
- *
- * @param mpt
- * the millipoints value
- */
- private int pts2units(float mpt) {
- return mpts2units(mpt * 1000d);
- }
-
- /**
- * Converts FOP mpt measurement to afp measurement units
- *
- * @param mpt
- * the millipoints value
- * @return afp measurement unit value
- */
- private int mpts2units(double mpt) {
- return (int) Math
- .round(mpt / (DPI_CONVERSION_FACTOR / getResolution()));
- }
-
- /**
- * Converts a byte array containing 24 bit RGB image data to a grayscale
- * image.
- *
- * @param io
- * the target image object
- * @param raw
- * the buffer containing the RGB image data
- * @param width
- * the width of the image in pixels
- * @param height
- * the height of the image in pixels
- * @param bitsPerPixel
- * the number of bits to use per pixel
- */
- protected static void convertToGrayScaleImage(ImageObject io, byte[] raw,
- int width, int height, int bitsPerPixel) {
- int pixelsPerByte = 8 / bitsPerPixel;
- int bytewidth = (width / pixelsPerByte);
- if ((width % pixelsPerByte) != 0) {
- bytewidth++;
- }
- byte[] bw = new byte[height * bytewidth];
- byte ib;
- for (int y = 0; y < height; y++) {
- ib = 0;
- int i = 3 * y * width;
- for (int x = 0; x < width; x++, i += 3) {
-
- // see http://www.jguru.com/faq/view.jsp?EID=221919
- double greyVal = 0.212671d * ((int) raw[i] & 0xff) + 0.715160d
- * ((int) raw[i + 1] & 0xff) + 0.072169d
- * ((int) raw[i + 2] & 0xff);
- switch (bitsPerPixel) {
- case 1:
- if (greyVal < 128) {
- ib |= (byte) (1 << (7 - (x % 8)));
- }
- break;
- case 4:
- greyVal /= 16;
- ib |= (byte) ((byte) greyVal << ((1 - (x % 2)) * 4));
- break;
- case 8:
- ib = (byte) greyVal;
- break;
- default:
- throw new UnsupportedOperationException(
- "Unsupported bits per pixel: " + bitsPerPixel);
- }
-
- if ((x % pixelsPerByte) == (pixelsPerByte - 1)
- || ((x + 1) == width)) {
- bw[(y * bytewidth) + (x / pixelsPerByte)] = ib;
- ib = 0;
- }
- }
- }
- io.setImageIDESize((byte) bitsPerPixel);
- io.setImageData(bw);
- }
-
- private final class ViewPortPos {
- private int x = 0;
-
- private int y = 0;
-
- private int rot = 0;
-
- private ViewPortPos() {
- }
-
- private ViewPortPos(Rectangle2D view, CTM ctm) {
- ViewPortPos currentVP = (ViewPortPos) viewPortPositions
- .get(viewPortPositions.size() - 1);
- int xOrigin;
- int yOrigin;
- int width;
- int height;
- switch (currentVP.rot) {
- case 90:
- width = mpts2units(view.getHeight());
- height = mpts2units(view.getWidth());
- xOrigin = pageWidth - width - mpts2units(view.getY())
- - currentVP.y;
- yOrigin = mpts2units(view.getX()) + currentVP.x;
- break;
- case 180:
- width = mpts2units(view.getWidth());
- height = mpts2units(view.getHeight());
- xOrigin = pageWidth - width - mpts2units(view.getX())
- - currentVP.x;
- yOrigin = pageHeight - height - mpts2units(view.getY())
- - currentVP.y;
- break;
- case 270:
- width = mpts2units(view.getHeight());
- height = mpts2units(view.getWidth());
- xOrigin = mpts2units(view.getY()) + currentVP.y;
- yOrigin = pageHeight - height - mpts2units(view.getX())
- - currentVP.x;
- break;
- default:
- xOrigin = mpts2units(view.getX()) + currentVP.x;
- yOrigin = mpts2units(view.getY()) + currentVP.y;
- width = mpts2units(view.getWidth());
- height = mpts2units(view.getHeight());
- break;
- }
- this.rot = currentVP.rot;
- double[] ctmf = ctm.toArray();
- if (ctmf[0] == 0.0d && ctmf[1] == -1.0d && ctmf[2] == 1.0d
- && ctmf[3] == 0.d) {
- this.rot += 270;
- } else if (ctmf[0] == -1.0d && ctmf[1] == 0.0d && ctmf[2] == 0.0d
- && ctmf[3] == -1.0d) {
- this.rot += 180;
- } else if (ctmf[0] == 0.0d && ctmf[1] == 1.0d && ctmf[2] == -1.0d
- && ctmf[3] == 0.0d) {
- this.rot += 90;
- }
- this.rot %= 360;
- switch (this.rot) {
- /*
- * case 0: this.x = mpts2units(view.getX()) + x; this.y =
- * mpts2units(view.getY()) + y; break; case 90: this.x =
- * mpts2units(view.getY()) + y; this.y = _pageWidth -
- * mpts2units(view.getX() + view.getWidth()) - x; break; case 180:
- * this.x = _pageWidth - mpts2units(view.getX() + view.getWidth()) -
- * x; this.y = _pageHeight - mpts2units(view.getY() +
- * view.getHeight()) - y; break; case 270: this.x = _pageHeight -
- * mpts2units(view.getY() + view.getHeight()) - y; this.y =
- * mpts2units(view.getX()) + x; break;
- */
- case 0:
- this.x = xOrigin;
- this.y = yOrigin;
- break;
- case 90:
- this.x = yOrigin;
- this.y = pageWidth - width - xOrigin;
- break;
- case 180:
- this.x = pageWidth - width - xOrigin;
- this.y = pageHeight - height - yOrigin;
- break;
- case 270:
- this.x = pageHeight - height - yOrigin;
- this.y = xOrigin;
- break;
- default:
- }
- }
-
- public String toString() {
- return "x:" + x + " y:" + y + " rot:" + rot;
- }
-
- }
-
- private List viewPortPositions = new java.util.ArrayList();
-
- private void pushViewPortPos(ViewPortPos vpp) {
- viewPortPositions.add(vpp);
- getAFPDataStream().setOffsets(vpp.x, vpp.y, vpp.rot);
- }
-
- private ViewPortPos popViewPortPos() {
- ViewPortPos current = (ViewPortPos)viewPortPositions.remove(viewPortPositions.size() - 1);
- if (viewPortPositions.size() > 0) {
- ViewPortPos vpp = (ViewPortPos) viewPortPositions
- .get(viewPortPositions.size() - 1);
- getAFPDataStream().setOffsets(vpp.x, vpp.y, vpp.rot);
- }
- return current;
- }
-
/**
* Sets the number of bits used per pixel
*
* number of bits per pixel
*/
public void setBitsPerPixel(int bitsPerPixel) {
- this.bitsPerPixel = bitsPerPixel;
- switch (bitsPerPixel) {
- case 1:
- case 4:
- case 8:
- break;
- default:
- log.warn("Invalid bits_per_pixel value, must be 1, 4 or 8.");
- bitsPerPixel = 8;
- break;
- }
+ currentState.setBitsPerPixel(bitsPerPixel);
}
/**
* color image output
*/
public void setColorImages(boolean colorImages) {
- this.colorImages = colorImages;
+ currentState.setColorImages(colorImages);
}
/**
* the output resolution (dpi)
*/
public void setResolution(int resolution) {
- if (log.isDebugEnabled()) {
- log.debug("renderer-resolution set to: " + resolution + "dpi");
- }
- this.resolution = resolution;
+ ((AFPState)getState()).setResolution(resolution);
}
/**
* @return the resolution in dpi
*/
public int getResolution() {
- return this.resolution;
+ return ((AFPState)getState()).getResolution();
}
- private AFPState getState() {
+ /**
+ * @return the current AFP state
+ */
+ protected AbstractState getState() {
if (currentState == null) {
currentState = new AFPState();
}
return currentState;
}
- private boolean gocaEnabled = false;
-
/**
* @param enabled
* true if AFP GOCA is enabled for SVG support
protected boolean isGOCAEnabled() {
return this.gocaEnabled;
}
+
+ // TODO: remove this and use the superclass implementation
+ /** {@inheritDoc} */
+ protected void renderReferenceArea(Block block) {
+ // save position and offset
+ int saveIP = currentIPPosition;
+ int saveBP = currentBPPosition;
+
+ //Establish a new coordinate system
+ AffineTransform at = new AffineTransform();
+ at.translate(currentIPPosition, currentBPPosition);
+ at.translate(block.getXOffset(), block.getYOffset());
+ at.translate(0, block.getSpaceBefore());
+
+ if (!at.isIdentity()) {
+ saveGraphicsState();
+ concatenateTransformationMatrix(at);
+ }
+
+ currentIPPosition = 0;
+ currentBPPosition = 0;
+ handleBlockTraits(block);
+
+ List children = block.getChildAreas();
+ if (children != null) {
+ renderBlocks(block, children);
+ }
+
+ if (!at.isIdentity()) {
+ restoreGraphicsState();
+ }
+
+ // stacked and relative blocks effect stacking
+ currentIPPosition = saveIP;
+ currentBPPosition = saveBP;
+ }
+
+ protected int[] transformPoints(float[] srcPts, float[] dstPts) {
+ return transformPoints(srcPts, dstPts, true);
+ }
+
+ protected int[] transformPoints(float[] srcPts, float[] dstPts, boolean milli) {
+ if (dstPts == null) {
+ dstPts = new float[srcPts.length];
+ }
+ AbstractState state = (AbstractState)getState();
+ AffineTransform at = state.getData().getTransform();
+ at.transform(srcPts, 0, dstPts, 0, srcPts.length / 2);
+ int[] coords = new int[srcPts.length];
+ for (int i = 0; i < srcPts.length; i++) {
+ if (!milli) {
+ dstPts[i] *= 1000;
+ }
+ coords[i] = Math.round(dstPts[i]);
+ }
+ return coords;
+ }
}
/** The font information for the AFP renderer. */
String AFP_FONT_INFO = "afpFontInfo";
- /** The afp resolution. */
- String AFP_RESOLUTION = "afpResolution";
-
/** The afp datastream */
String AFP_DATASTREAM = "afpDataStream";
/** The afp state */
String AFP_STATE = "afpPageState";
-
- /** The afp bits per pixel */
- String AFP_BITS_PER_PIXEL = "afpBitsPerPixel";
}
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.RendererContextConstants;
+import org.apache.fop.render.afp.modca.AFPConstants;
import org.apache.fop.render.afp.modca.AFPDataStream;
import org.apache.fop.render.afp.modca.GraphicsObject;
import org.apache.fop.svg.SVGUserAgent;
afpi.setHandlerConfiguration((Configuration)context.getProperty(HANDLER_CONFIGURATION));
afpi.setFontInfo((org.apache.fop.fonts.FontInfo)context.getProperty(
AFPRendererContextConstants.AFP_FONT_INFO));
- afpi.setResolution(((Integer)context.getProperty(
- AFPRendererContextConstants.AFP_RESOLUTION)).intValue());
afpi.setState((AFPState)context.getProperty(
AFPRendererContextConstants.AFP_STATE));
afpi.setAFPDataStream((AFPDataStream)context.getProperty(
AFPRendererContextConstants.AFP_DATASTREAM));
- afpi.setColor(!((Boolean)context.getProperty(
- AFPRendererContextConstants.AFP_GRAYSCALE)).booleanValue());
- afpi.setBitsPerPixel(((Integer)context.getProperty(
- AFPRendererContextConstants.AFP_BITS_PER_PIXEL)).intValue());
return afpi;
}
-
+
/**
* Render the SVG document.
*
double h = ctx.getDocumentSize().getHeight() * 1000f;
// convert to afp inches
- double sx = ((afpInfo.getWidth() / w) * res) / 72f;
- double sy = ((afpInfo.getHeight() / h) * res) / 72f;
- double xOffset = (afpInfo.getX() * res) / 72000f;
- double yOffset = ((afpInfo.getHeight() - afpInfo.getY()) * res) / 72000f;
+ double scaleX = ((afpInfo.getWidth() / w) * res) / AFPConstants.DPI_72;
+ double scaleY = ((afpInfo.getHeight() / h) * res) / AFPConstants.DPI_72;
+ double xOffset = (afpInfo.getX() * res) / AFPConstants.DPI_72_MPTS;
+ double yOffset = ((afpInfo.getHeight() - afpInfo.getY()) * res) / AFPConstants.DPI_72_MPTS;
// Transformation matrix that establishes the local coordinate system for the SVG graphic
// in relation to the current coordinate system (note: y axis is inverted)
- AffineTransform trans = new AffineTransform(sx, 0, 0, -sy, xOffset, yOffset);
+ AffineTransform trans = new AffineTransform(scaleX, 0, 0, -scaleY, xOffset, yOffset);
graphics.setTransform(trans);
- int x = (int)Math.round((afpInfo.getX() * 25.4f) / 1000);
- int y = (int)Math.round((afpInfo.getY() * 25.4f) / 1000);
- int width = (int)Math.round((afpInfo.getWidth() * res) / 72000f);
- int height = (int)Math.round((afpInfo.getHeight() * res) / 72000f);
+ int x = (int)Math.round((afpInfo.getX() * 25.4f) / 1000f);
+ int y = (int)Math.round((afpInfo.getY() * 25.4f) / 1000f);
+ int width = (int)Math.round((afpInfo.getWidth() * res) / AFPConstants.DPI_72_MPTS);
+ int height = (int)Math.round((afpInfo.getHeight() * res) / AFPConstants.DPI_72_MPTS);
// set the data object parameters
DataObjectInfo dataObjectInfo = new DataObjectInfo();
package org.apache.fop.render.afp;
-import java.awt.Color;
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.List;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
/**
- * This keeps information about the current state when writing to pdf.
+ * This keeps information about the current state when writing to an AFP datastream.
*/
-public class AFPState {
- private Data data = new Data();
-
- private List stateStack = new java.util.ArrayList();
+public class AFPState extends org.apache.fop.render.AbstractState {
+
+ private static Log log = LogFactory.getLog("org.apache.fop.render.afp.AFPState");
/**
- * Set the current color.
- * Check if the new color is a change and then set the current color.
- *
- * @param col the color to set
- * @return true if the color has changed
+ * The portrait rotation
*/
- protected boolean setColor(Color col) {
- if (!col.equals(getData().color)) {
- getData().color = col;
- return true;
+ private int portraitRotation = 0;
+
+ /**
+ * The landscape rotation
+ */
+ private int landscapeRotation = 270;
+
+ /**
+ * Flag to the set the output object type for images
+ */
+ private boolean colorImages = false;
+
+ /**
+ * Default value for image depth
+ */
+ private int bitsPerPixel = 8;
+
+ /**
+ * The output resolution
+ */
+ private int resolution = 240; // 240 dpi
+
+ /**
+ * The current page
+ */
+ private AFPPageState pageState = new AFPPageState();
+
+ /**
+ * Sets the rotation to be used for portrait pages, valid values are 0
+ * (default), 90, 180, 270.
+ *
+ * @param rotation
+ * The rotation in degrees.
+ */
+ protected void setPortraitRotation(int rotation) {
+ if (rotation == 0 || rotation == 90 || rotation == 180
+ || rotation == 270) {
+ portraitRotation = rotation;
+ } else {
+ throw new IllegalArgumentException(
+ "The portrait rotation must be one"
+ + " of the values 0, 90, 180, 270");
+
}
- return false;
}
/**
- * Sets if the current painted shape is to be filled
- * @param fill true if the current painted shape is to be filled
- * @return true if the fill value has changed
+ * @return the rotation to be used for portrait pages
*/
- protected boolean setFill(boolean fill) {
- if (fill != getData().filled) {
- getData().filled = fill;
- return true;
- }
- return false;
+ protected int getPortraitRotation() {
+ return this.portraitRotation;
}
/**
- * Get the color.
- * @return the color
+ * Sets the rotation to be used for landscape pages, valid values are 0, 90,
+ * 180, 270 (default).
+ *
+ * @param rotation
+ * The rotation in degrees.
*/
- protected Color getColor() {
- if (getData().color == null) {
- getData().color = Color.black;
+ protected void setLandscapeRotation(int rotation) {
+ if (rotation == 0 || rotation == 90 || rotation == 180
+ || rotation == 270) {
+ landscapeRotation = rotation;
+ } else {
+ throw new IllegalArgumentException(
+ "The landscape rotation must be one"
+ + " of the values 0, 90, 180, 270");
}
- return getData().color;
}
/**
- * Set the current line width.
- * @param width the line width in points
- * @return true if the line width has changed
+ * @return the landscape rotation
*/
- protected boolean setLineWidth(float width) {
- if (getData().lineWidth != width) {
- getData().lineWidth = width;
- return true;
- }
- return false;
+ protected int getLandscapeRotation() {
+ return this.landscapeRotation;
}
/**
- * Sets the dash array (line type) for the current basic stroke
- * @param dash the line dash array
- * @return true if the dash array has changed
+ * Sets the number of bits used per pixel
+ *
+ * @param bitsPerPixel
+ * number of bits per pixel
*/
- public boolean setDashArray(float[] dash) {
- if (!Arrays.equals(dash, getData().dashArray)) {
- getData().dashArray = dash;
- return true;
+ public void setBitsPerPixel(int bitsPerPixel) {
+ this.bitsPerPixel = bitsPerPixel;
+ switch (bitsPerPixel) {
+ case 1:
+ case 4:
+ case 8:
+ break;
+ default:
+ log.warn("Invalid bits_per_pixel value, must be 1, 4 or 8.");
+ bitsPerPixel = 8;
+ break;
}
- return false;
}
/**
- * Gets the current line width
- * @return the current line width
+ * @return the number of bits per pixel
*/
- protected float getLineWidth() {
- return getData().lineWidth;
+ public int getBitsPerPixel() {
+ return this.bitsPerPixel;
}
/**
- * Get the background color.
- * @return the background color
+ * Sets whether images are color or not
+ *
+ * @param colorImages
+ * color image output
*/
- protected Color getBackColor() {
- if (getData().backColor == null) {
- getData().backColor = Color.white;
- }
- return getData().backColor;
+ public void setColorImages(boolean colorImages) {
+ this.colorImages = colorImages;
}
/**
- * Set the current background color.
- * Check if the new background color is a change and then set the current background color.
- *
- * @param col the background color to set
- * @return true if the color has changed
+ * @return true if color images are to be used
*/
- protected boolean setBackColor(Color col) {
- if (!col.equals(getData().backColor)) {
- getData().backColor = col;
- return true;
- }
- return false;
+ protected boolean isColorImages() {
+ return this.colorImages;
}
/**
- * Set the current font name
- * @param internalFontName the internal font name
- * @return true if the font name has changed
+ * Sets the output/device resolution
+ *
+ * @param resolution
+ * the output resolution (dpi)
*/
- protected boolean setFontName(String internalFontName) {
- if (!internalFontName.equals(getData().fontName)) {
- getData().fontName = internalFontName;
- return true;
+ public void setResolution(int resolution) {
+ if (log.isDebugEnabled()) {
+ log.debug("renderer-resolution set to: " + resolution + "dpi");
}
- return false;
+ this.resolution = resolution;
}
/**
- * Gets the current font name
- * @return the current font name
+ * Returns the output/device resolution.
+ *
+ * @return the resolution in dpi
*/
- protected String getFontName() {
- return getData().fontName;
+ protected int getResolution() {
+ return this.resolution;
}
-
+
+ /** {@inheritDoc} */
+ protected AbstractData instantiateData() {
+ return new AFPData();
+ }
+
/**
- * Gets the current font size
- * @return the current font size
+ * @return the state of the current page
*/
- protected int getFontSize() {
- return getData().fontSize;
+ protected AFPPageState getPageState() {
+ return this.pageState;
}
-
+
/**
- * Set the current font size.
- * Check if the font size is a change and then set the current font size.
- *
- * @param size the font size to set
- * @return true if the font size has changed
+ * Sets if the current painted shape is to be filled
+ * @param fill true if the current painted shape is to be filled
+ * @return true if the fill value has changed
*/
- protected boolean setFontSize(int size) {
- if (size != getData().fontSize) {
- getData().fontSize = size;
+ protected boolean setFill(boolean fill) {
+ if (fill != ((AFPData)getData()).filled) {
+ ((AFPData)getData()).filled = fill;
return true;
}
return false;
* @return the current page fonts
*/
protected AFPPageFonts getPageFonts() {
- if (getData().pageFonts == null) {
- getData().pageFonts = new AFPPageFonts();
- }
- return getData().pageFonts;
+ return pageState.getFonts();
}
/**
- * Sets the image uri of the current image being processed
- * @param uri the image uri of the current image being processed
- * @return true if the image uri has changed
+ * Increments and returns the page font count
+ * @return the page font count
*/
- public boolean setImageUri(String uri) {
- if (!uri.equals(getData().imageUri)) {
- getData().imageUri = uri;
- return true;
- }
- return false;
+ public int incrementPageFontCount() {
+ return pageState.incrementFontCount();
}
/**
- * Returns the image uri of the current image being processed
- * @return the image uri of the current image being processed
+ * Sets the page width
+ * @param pageWidth the page width
*/
- protected String getImageUri() {
- return getData().imageUri;
+ public void setPageWidth(int pageWidth) {
+ pageState.setWidth(pageWidth);
}
-
+
/**
- * Push the current state onto the stack.
- * This call should be used when the q operator is used
- * so that the state is known when popped.
+ * @return the page width
*/
- public void push() {
- Data copy;
- try {
- copy = (Data)getData().clone();
- } catch (CloneNotSupportedException e) {
- throw new RuntimeException(e.getMessage());
- }
- stateStack.add(copy);
+ public int getPageWidth() {
+ return pageState.getWidth();
}
/**
- * Get the current stack level.
- *
- * @return the current stack level
+ * Sets the page height
+ * @param pageHeight the page height
*/
- public int getStackLevel() {
- return stateStack.size();
+ public void setPageHeight(int pageHeight) {
+ pageState.setHeight(pageHeight);
}
/**
- * Pop the state from the stack and set current values to popped state.
- * This should be called when a Q operator is used so
- * the state is restored to the correct values.
- * @return the restored state, null if the stack is empty
+ * @return the page height
*/
- public Data pop() {
- if (getStackLevel() > 0) {
- Data popped = (Data)stateStack.remove(stateStack.size() - 1);
- data = popped;
- return popped;
- } else {
- return null;
- }
+ public int getPageHeight() {
+ return pageState.getHeight();
}
/**
- * @return the currently valid state
+ * Sets the uri of the current image
+ * @param uri the uri of the current image
*/
- public Data getData() {
- return data;
+ protected void setImageUri(String uri) {
+ ((AFPData)getData()).imageUri = uri;
}
-
- /** the state data instance */
- public class Data implements Cloneable, Serializable {
- private static final long serialVersionUID = -1789481244175275686L;
- /** The current color */
- private Color color = null;
+ /**
+ * Gets the uri of the current image
+ * @return the uri of the current image
+ */
+ public String getImageUri() {
+ return ((AFPData)getData()).imageUri;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "AFPState{portraitRotation=" + portraitRotation
+ + ", landscapeRotation=" + landscapeRotation
+ + ", colorImages=" + colorImages
+ + ", bitsPerPixel=" + bitsPerPixel
+ + ", resolution=" + resolution
+ + ", pageState=" + pageState
+ + "}";
+ }
- /** The current background color */
- private Color backColor = null;
+ /**
+ * Page level state data
+ */
+ private class AFPPageState {
+ /** The current page width */
+ private int width = 0;
- /** The current font name */
- private String fontName = null;
+ /** The current page height */
+ private int height = 0;
- /** The current font size */
- private int fontSize = 0;
+ /** The current page fonts */
+ private AFPPageFonts fonts = new AFPPageFonts();
- /** The current line width */
- private float lineWidth = 0;
+ /** The current page font count */
+ private int fontCount = 0;
- /** The dash array for the current basic stroke (line type) */
- private float[] dashArray = null;
+ /**
+ * @return the page width
+ */
+ protected int getWidth() {
+ return width;
+ }
+
+ /**
+ * Sets the page width
+ * @param width the page width
+ */
+ protected void setWidth(int width) {
+ this.width = width;
+ }
+
+ /**
+ * @return the page height
+ */
+ protected int getHeight() {
+ return height;
+ }
+
+ /**
+ * Sets the page height
+ * @param height the page height
+ */
+ protected void setHeight(int height) {
+ this.height = height;
+ }
+
+ /**
+ * @return the page fonts
+ */
+ protected AFPPageFonts getFonts() {
+ return fonts;
+ }
+
+ /**
+ * Sets the current page fonts
+ * @param fonts the current page fonts
+ */
+ protected void setFonts(AFPPageFonts fonts) {
+ this.fonts = fonts;
+ }
+
+ /**
+ * @return increment and return the current page font count
+ */
+ protected int incrementFontCount() {
+ return ++fontCount;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return "AFPPageState{width=" + width
+ + ", height=" + height
+ + ", fonts=" + fonts
+ + ", fontCount=" + fontCount
+ + "}";
+ }
+ }
+
+ /**
+ * Block level data
+ */
+ private class AFPData extends org.apache.fop.render.AbstractState.AbstractData {
+ private static final long serialVersionUID = -1789481244175275686L;
/** The current fill status */
private boolean filled = false;
- /** The fonts on the current page */
- private AFPPageFonts pageFonts = null;
-
- /** The current image uri */
private String imageUri = null;
/** {@inheritDoc} */
public Object clone() throws CloneNotSupportedException {
- Data obj = new Data();
- obj.color = this.color;
- obj.backColor = this.backColor;
- obj.fontName = this.fontName;
- obj.fontSize = this.fontSize;
- obj.lineWidth = this.lineWidth;
- obj.dashArray = this.dashArray;
+ AFPData obj = (AFPData)super.clone();
obj.filled = this.filled;
- obj.pageFonts = this.pageFonts;
obj.imageUri = this.imageUri;
return obj;
}
- /** {@inheritDoc} */
+ /** {@inheritDoc} */
public String toString() {
- return "color=" + color
- + ", backColor=" + backColor
- + ", fontName=" + fontName
- + ", fontSize=" + fontSize
- + ", lineWidth=" + lineWidth
- + ", dashArray=" + dashArray
+ return "AFPData{" + super.toString()
+ ", filled=" + filled
- + ", pageFonts=" + pageFonts
- + ", imageUri=" + imageUri;
+ + ", imageUri=" + imageUri
+ + "}";
}
}
}
\ No newline at end of file
*/
/* $Id$ */
+
package org.apache.fop.render.afp;
public class ObjectAreaInfo {
+ ", heightRes=" + heightRes
+ ", rotation=" + rotation;
}
-}
\ No newline at end of file
+}
import org.apache.commons.logging.LogFactory;
import org.apache.fop.render.afp.AFPFontAttributes;
+import org.apache.fop.render.afp.AFPTextDataInfo;
import org.apache.fop.render.afp.DataObjectInfo;
import org.apache.fop.render.afp.ObjectAreaInfo;
import org.apache.fop.render.afp.ResourceInfo;
*/
private int landscapeRotation = 270;
- /**
- * The x offset
- */
- private int xOffset = 0;
-
- /**
- * The y offset
- */
- private int yOffset = 0;
-
/**
* The rotation
*/
- private int rotation;
+ private int orientation;
/**
* The outputstream for the data stream
pageRotation, pageWidthRes, pageHeightRes);
currentPage = currentPageObject;
currentOverlay = null;
- setOffsets(0, 0, 0);
+// setOffsets(0, 0, 0);
}
/**
currentPageObject.createIncludePageOverlay(overlayName, x, y, 0);
currentPage = currentOverlay;
- setOffsets(0, 0, 0);
+// setOffsets(0, 0, 0);
}
/**
* the offset in the x direction
* @param yOff
* the offset in the y direction
- * @param rot
+ * @param orientation
* the rotation
+ * @deprecated offsets are no longer used, use setOrientation() for setting the orientation
*/
- public void setOffsets(int xOff, int yOff, int rot) {
- this.xOffset = xOff;
- this.yOffset = yOff;
- this.rotation = rot;
+ public void setOffsets(int xOff, int yOff, int orientation) {
+ setOrientation(orientation);
}
+ /**
+ * Sets the orientation to be used for element positioning
+ *
+ * @param orientation
+ * the orientation used for element positioning
+ */
+ public void setOrientation(int orientation) {
+ this.orientation = orientation;
+ }
+
/**
* Creates the given page fonts in the current page
*
* Helper method to create text on the current page, this method delegates
* to the current presentation text object in order to construct the text.
*
- * @param fontReference
- * the font reference used as the resource identifier
- * @param x
- * the x coordinate of the text
- * @param y
- * the y coordinate of the text
- * @param col
- * the text color
- * @param vsci
- * The variable space character increment.
- * @param ica
- * The inter character adjustment.
- * @param data
- * the text data to create
+ * @param textDataInfo
+ * the afp text data
*/
- public void createText(int fontReference, int x, int y, Color col,
- int vsci, int ica, byte[] data) {
- getCurrentPage().createText(fontReference, x + xOffset, y + yOffset,
- rotation, col, vsci, ica, data);
+ public void createText(AFPTextDataInfo textDataInfo) {
+ textDataInfo.setOrientation(orientation);
+ getCurrentPage().createText(textDataInfo);
}
/**
//Update placement with current state
ObjectAreaInfo areaInfo = dataObjectInfo.getObjectAreaInfo();
- areaInfo.setX(areaInfo.getX() + this.xOffset);
- areaInfo.setY(areaInfo.getY() + this.yOffset);
+ areaInfo.setX(areaInfo.getX());
+ areaInfo.setY(areaInfo.getY());
areaInfo.setRotation(this.rotation);
Registry registry = Registry.getInstance();
*/
public void createLine(int x1, int y1, int x2, int y2, int thickness,
Color col) {
- getCurrentPage().createLine(x1 + xOffset, y1 + yOffset, x2 + xOffset,
- y2 + yOffset, thickness, rotation, col);
+ getCurrentPage().createLine(x1, y1, x2, y2, thickness, orientation, col);
}
/**
* the shading color
*/
public void createShading(int x, int y, int w, int h, Color col) {
- currentPageObject.createShading(x + xOffset, y + xOffset, w, h,
- col.getRed(), col.getGreen(), col.getBlue());
+ currentPageObject.createShading(x, y, w, h, col.getRed(), col.getGreen(), col.getBlue());
}
/**
* the name of the static overlay
*/
public void createIncludePageOverlay(String name) {
- currentPageObject.createIncludePageOverlay(name, 0, 0, rotation);
+ currentPageObject.createIncludePageOverlay(name, 0, 0, orientation);
currentPageObject.getActiveEnvironmentGroup().createOverlay(name);
}
public void createIncludePageSegment(String name, int x, int y) {
int xOrigin;
int yOrigin;
- switch (rotation) {
+ switch (orientation) {
case 90:
- xOrigin = getCurrentPage().getWidth() - y - yOffset;
- yOrigin = x + xOffset;
+ xOrigin = getCurrentPage().getWidth() - y;
+ yOrigin = x;
break;
case 180:
- xOrigin = getCurrentPage().getWidth() - x - xOffset;
- yOrigin = getCurrentPage().getHeight() - y - yOffset;
+ xOrigin = getCurrentPage().getWidth() - x;
+ yOrigin = getCurrentPage().getHeight() - y;
break;
case 270:
- xOrigin = y + yOffset;
- yOrigin = getCurrentPage().getHeight() - x - xOffset;
+ xOrigin = y;
+ yOrigin = getCurrentPage().getHeight() - x;
break;
default:
- xOrigin = x + xOffset;
- yOrigin = y + yOffset;
+ xOrigin = x;
+ yOrigin = y;
break;
}
getCurrentPage().createIncludePageSegment(name, xOrigin, yOrigin);
import java.io.OutputStream;
import java.util.List;
+import org.apache.fop.render.afp.AFPTextDataInfo;
import org.apache.fop.render.afp.fonts.AFPFont;
/**
* Helper method to create text on the current page, this method delegates
* to the presentation text object in order to construct the text.
*
- * @param fontRef
- * the font number used as the resource identifier
- * @param x
- * the x coordinate of the text data
- * @param y
- * the y coordinate of the text data
- * @param textRotation
- * the rotation of the text data
- * @param col
- * the text color
- * @param vsci
- * The variable space character increment.
- * @param ica
- * The inter character adjustment.
- * @param data
- * the text data to create
+ * @param textDataInfo
+ * the afp text data
*/
- public void createText(int fontRef, int x, int y, int textRotation, Color col,
- int vsci, int ica, byte[] data) {
- getPresentationTextObject().createTextData(
- fontRef, x, y, textRotation, col, vsci, ica, data);
+ public void createText(AFPTextDataInfo textDataInfo) {
+ getPresentationTextObject().createTextData(textDataInfo);
}
/**
import java.io.IOException;
import java.io.OutputStream;
+import org.apache.fop.render.afp.AFPTextDataInfo;
import org.apache.fop.render.afp.tools.BinaryUtils;
/**
* that position them - modal control sequences that adjust the positions by
* small amounts - other functions causing text to be presented with differences
* in appearance.
- *
+ *
* The graphic characters are expected to conform to a coded font representation
* so that they can be translated from the code point in the object data to the
* character in the coded font. The units of measure for linear displacements
* are derived from the PresentationTextDescriptor or from the hierarchical
* defaults.
- *
+ *
* In addition to graphic character code points, Presentation Text data can
* contain embedded control sequences. These are strings of two or more bytes
* which signal an alternate mode of processing for the content of the current
* Presentation Text data.
- *
+ *
*/
public class PresentationTextData extends AbstractAFPObject {
* Constructor for the PresentationTextData, the boolean flag indicate
* whether the control sequence prefix should be set to indicate the start
* of a new control sequence.
- *
+ *
* @param controlInd
* The control sequence indicator.
*/
public PresentationTextData(boolean controlInd) {
- final byte[] data = {
- 0x5A, // Structured field identifier
- 0x00, // Record length byte 1
- 0x00, // Record length byte 2
- (byte) 0xD3, // PresentationTextData identifier byte 1
- (byte) 0xEE, // PresentationTextData identifier byte 2
- (byte) 0x9B, // PresentationTextData identifier byte 3
- 0x00, // Flag
- 0x00, // Reserved
- 0x00, // Reserved
+ final byte[] data = { 0x5A, // Structured field identifier
+ 0x00, // Record length byte 1
+ 0x00, // Record length byte 2
+ (byte) 0xD3, // PresentationTextData identifier byte 1
+ (byte) 0xEE, // PresentationTextData identifier byte 2
+ (byte) 0x9B, // PresentationTextData identifier byte 3
+ 0x00, // Flag
+ 0x00, // Reserved
+ 0x00, // Reserved
};
baos.write(data, 0, 9);
* The Set Coded Font Local control sequence activates a coded font and
* specifies the character attributes to be used. This is a modal control
* sequence.
- *
+ *
* @param font
* The font local identifier.
* @param afpdata
* Establishes the current presentation position on the baseline at a new
* I-axis coordinate, which is a specified number of measurement units from
* the B-axis. There is no change to the current B-axis coordinate.
- *
+ *
* @param coordinate
* The coordinate for the inline move.
* @param afpdata
* The output stream to which data should be written.
*/
- private void absoluteMoveInline(int coordinate, ByteArrayOutputStream afpdata) {
+ private void absoluteMoveInline(int coordinate,
+ ByteArrayOutputStream afpdata) {
byte[] b = BinaryUtils.convert(coordinate, 2);
afpdata.write(new byte[] { 0x04, (byte) 0xC7, b[0], b[1], }, 0, 4);
currentXCoordinate = coordinate;
* Establishes the baseline and the current presentation position at a new
* B-axis coordinate, which is a specified number of measurement units from
* the I-axis. There is no change to the current I-axis coordinate.
- *
+ *
* @param coordinate
* The coordinate for the baseline move.
* @param afpdata
* The output stream to which data should be written.
*/
- private void absoluteMoveBaseline(int coordinate, ByteArrayOutputStream afpdata) {
+ private void absoluteMoveBaseline(int coordinate,
+ ByteArrayOutputStream afpdata) {
byte[] b = BinaryUtils.convert(coordinate, 2);
afpdata.write(new byte[] { 0x04, (byte) 0xD3, b[0], b[1], }, 0, 4);
currentYCoordinate = coordinate;
/**
* The Transparent Data control sequence contains a sequence of code points
* that are presented without a scan for embedded control sequences.
- *
+ *
* @param data
* The text data to add.
* @param afpdata
if (l > 255) {
// Check that we are not exceeding the maximum length
throw new IllegalArgumentException(
- "Transparent data is longer than 253 bytes: " + data);
+ "Transparent data is longer than 253 bytes: " + data);
}
afpdata.write(new byte[] { BinaryUtils.convert(l)[0], (byte) 0xDB, },
- 0, 2);
+ 0, 2);
afpdata.write(data, 0, data.length);
}
* Draws a line of specified length and specified width in the B-direction
* from the current presentation position. The location of the current
* presentation position is unchanged.
- *
+ *
* @param length
* The length of the rule.
* @param width
* @param afpdata
* The output stream to which data should be written.
*/
- private void drawBaxisRule(int length, int width, ByteArrayOutputStream afpdata) {
+ private void drawBaxisRule(int length, int width,
+ ByteArrayOutputStream afpdata) {
afpdata.write(new byte[] { 0x07, // Length
- (byte) 0xE7, // Type
+ (byte) 0xE7, // Type
}, 0, 2);
// Rule length
byte[] data1 = BinaryUtils.shortToByteArray((short) length);
* Draws a line of specified length and specified width in the I-direction
* from the current presentation position. The location of the current
* presentation position is unchanged.
- *
+ *
* @param length
* The length of the rule.
* @param width
* @param afpdata
* The output stream to which data should be written.
*/
- private void drawIaxisRule(int length, int width, ByteArrayOutputStream afpdata) {
+ private void drawIaxisRule(int length, int width,
+ ByteArrayOutputStream afpdata) {
afpdata.write(new byte[] { 0x07, // Length
- (byte) 0xE5, // Type
+ (byte) 0xE5, // Type
}, 0, 2);
// Rule length
byte[] data1 = BinaryUtils.shortToByteArray((short) length);
/**
* Create the presentation text data for the byte array of data.
- *
- * @param fontNumber
- * The font resource identifier.
- * @param x
- * The x coordinate for the text data.
- * @param y
- * The y coordinate for the text data.
- * @param orientation
- * The orientation of the text data.
- * @param col
- * The text color.
- * @param vsci
- * The variable space character increment.
- * @param ica
- * The inter character adjustment.
- * @param data
- * The text data to be created.
+ *
+ * @param textDataInfo
+ * the afp text data
* @throws MaximumSizeExceededException
+ * thrown if the maximum number of text data is exceeded
*/
- public void createTextData(int fontNumber, int x, int y, int orientation,
- Color col, int vsci, int ica, byte[] data) throws MaximumSizeExceededException {
+ public void createTextData(AFPTextDataInfo textDataInfo)
+ throws MaximumSizeExceededException {
ByteArrayOutputStream afpdata = new ByteArrayOutputStream();
- if (currentOrientation != orientation) {
- setTextOrientation(orientation, afpdata);
- currentOrientation = orientation;
+ if (currentOrientation != textDataInfo.getOrientation()) {
+ setTextOrientation(textDataInfo.getOrientation(), afpdata);
+ currentOrientation = textDataInfo.getOrientation();
currentXCoordinate = -1;
currentYCoordinate = -1;
}
// Avoid unnecessary specification of the Y co-ordinate
- if (y != currentYCoordinate) {
- absoluteMoveBaseline(y, afpdata);
+ if (textDataInfo.getY() != currentYCoordinate) {
+ absoluteMoveBaseline(textDataInfo.getY(), afpdata);
currentXCoordinate = -1;
}
// Avoid unnecessary specification of the X co-ordinate
- if (x != currentXCoordinate) {
- absoluteMoveInline(x, afpdata);
+ if (textDataInfo.getX() != currentXCoordinate) {
+ absoluteMoveInline(textDataInfo.getX(), afpdata);
}
// Avoid unnecessary specification of the variable space increment
- if (vsci != currentVariableSpaceCharacterIncrement) {
- setVariableSpaceCharacterIncrement(vsci, afpdata);
- currentVariableSpaceCharacterIncrement = vsci;
+ if (textDataInfo.getVariableSpaceCharacterIncrement()
+ != currentVariableSpaceCharacterIncrement) {
+ setVariableSpaceCharacterIncrement(textDataInfo
+ .getVariableSpaceCharacterIncrement(), afpdata);
+ currentVariableSpaceCharacterIncrement = textDataInfo
+ .getVariableSpaceCharacterIncrement();
}
// Avoid unnecessary specification of the inter character adjustment
- if (ica != currentInterCharacterAdjustment) {
- setInterCharacterAdjustment(ica, afpdata);
- currentInterCharacterAdjustment = ica;
+ if (textDataInfo.getInterCharacterAdjustment() != currentInterCharacterAdjustment) {
+ setInterCharacterAdjustment(textDataInfo.getInterCharacterAdjustment(),
+ afpdata);
+ currentInterCharacterAdjustment = textDataInfo
+ .getInterCharacterAdjustment();
}
// Avoid unnecessary specification of the text color
- if (!col.equals(currentColor)) {
- setExtendedTextColor(col, afpdata);
- currentColor = col;
+ if (!textDataInfo.getColor().equals(currentColor)) {
+ setExtendedTextColor(textDataInfo.getColor(), afpdata);
+ currentColor = textDataInfo.getColor();
}
- setCodedFont(BinaryUtils.convert(fontNumber)[0], afpdata);
- addTransparentData(data, afpdata);
+ setCodedFont(BinaryUtils.convert(textDataInfo.getFontReference())[0],
+ afpdata);
+ addTransparentData(textDataInfo.getData(), afpdata);
currentXCoordinate = -1;
- int s = afpdata.size();
+ int dataSize = afpdata.size();
- if (baos.size() + s > MAX_SIZE) {
+ if (baos.size() + dataSize > MAX_SIZE) {
currentXCoordinate = -1;
currentYCoordinate = -1;
throw new MaximumSizeExceededException();
/**
* Drawing of lines using the starting and ending coordinates, thickness and
* colour arguments.
- *
+ *
* @param x1
* The starting X coordinate.
* @param y1
* The orientation of the text data.
* @param col
* The text color.
+ * @throws MaximumSizeExceededException
+ * thrown if the maximum number of line data has been exceeded
*/
public void createLineData(int x1, int y1, int x2, int y2, int thickness,
- int orientation, Color col) throws MaximumSizeExceededException {
+ int orientation, Color col) throws MaximumSizeExceededException {
ByteArrayOutputStream afpdata = new ByteArrayOutputStream();
/**
* The Set Text Orientation control sequence establishes the I-direction and
* B-direction for the subsequent text. This is a modal control sequence.
- *
+ *
* Semantics: This control sequence specifies the I-axis and B-axis
* orientations with respect to the Xp-axis for the current Presentation
* Text object. The orientations are rotational values expressed in degrees
* and minutes.
- *
+ *
* @param orientation
- * The text orientation (0,90, 180, 270).
+ * The text orientation (0, 90, 180, 270).
* @param afpdata
* The output stream to which data should be written.
*/
- private void setTextOrientation(int orientation, ByteArrayOutputStream afpdata) {
- afpdata.write(new byte[] { 0x06, (byte) 0xF7, }, 0, 2);
+ private void setTextOrientation(int orientation,
+ ByteArrayOutputStream afpdata) {
+ afpdata.write(new byte[] {0x06, (byte) 0xF7, }, 0, 2);
switch (orientation) {
- case 90:
- afpdata.write(0x2D);
- afpdata.write(0x00);
- afpdata.write(0x5A);
- afpdata.write(0x00);
- break;
- case 180:
- afpdata.write(0x5A);
- afpdata.write(0x00);
- afpdata.write(0x87);
- afpdata.write(0x00);
- break;
- case 270:
- afpdata.write(0x87);
- afpdata.write(0x00);
- afpdata.write(0x00);
- afpdata.write(0x00);
- break;
- default:
- afpdata.write(0x00);
- afpdata.write(0x00);
- afpdata.write(0x2D);
- afpdata.write(0x00);
- break;
+ case 90:
+ afpdata.write(0x2D);
+ afpdata.write(0x00);
+ afpdata.write(0x5A);
+ afpdata.write(0x00);
+ break;
+ case 180:
+ afpdata.write(0x5A);
+ afpdata.write(0x00);
+ afpdata.write(0x87);
+ afpdata.write(0x00);
+ break;
+ case 270:
+ afpdata.write(0x87);
+ afpdata.write(0x00);
+ afpdata.write(0x00);
+ afpdata.write(0x00);
+ break;
+ default:
+ afpdata.write(0x00);
+ afpdata.write(0x00);
+ afpdata.write(0x2D);
+ afpdata.write(0x00);
+ break;
}
}
/**
* The Set Extended Text Color control sequence specifies a color value and
- * defines the color space and encoding for that value. The specified color
- * value is applied to foreground areas of the text presentation space.
- * This is a modal control sequence.
- *
+ * defines the color space and encoding for that value. The specified color
+ * value is applied to foreground areas of the text presentation space. This
+ * is a modal control sequence.
+ *
* @param col
* The color to be set.
* @param afpdata
* The output stream to which data should be written.
*/
- private void setExtendedTextColor(Color col,
- ByteArrayOutputStream afpdata) {
-
- afpdata.write(new byte[] {
- 15 // Control sequence length
- , (byte)0x81 // Control sequence function type
- , 0x00 // Reserved; must be zero
- , 0x01 // Color space - 0x01 = RGB
- , 0x00 // Reserved; must be zero
- , 0x00 // Reserved; must be zero
- , 0x00 // Reserved; must be zero
- , 0x00 // Reserved; must be zero
- , 8 // Number of bits in component 1
- , 8 // Number of bits in component 2
- , 8 // Number of bits in component 3
- , 0 // Number of bits in component 4
- , (byte)(col.getRed()) // Red intensity
- , (byte)(col.getGreen()) // Green intensity
- , (byte)(col.getBlue()) // Blue intensity
- }, 0, 15);
-
+ private void setExtendedTextColor(Color col, ByteArrayOutputStream afpdata) {
+ byte[] colorData = new byte[] {
+ 15, // Control sequence length
+ (byte) 0x81, // Control sequence function type
+ 0x00, // Reserved; must be zero
+ 0x01, // Color space - 0x01 = RGB
+ 0x00, // Reserved; must be zero
+ 0x00, // Reserved; must be zero
+ 0x00, // Reserved; must be zero
+ 0x00, // Reserved; must be zero
+ 8, // Number of bits in component 1
+ 8, // Number of bits in component 2
+ 8, // Number of bits in component 3
+ 0, // Number of bits in component 4
+ (byte) (col.getRed()), // Red intensity
+ (byte) (col.getGreen()), // Green intensity
+ (byte) (col.getBlue()), // Blue intensity
+ };
+
+ afpdata.write(colorData, 0, colorData.length);
}
/**
- * //TODO
- * This is a modal control sequence.
- *
+ * //TODO This is a modal control sequence.
+ *
* @param incr
* The increment to be set.
* @param afpdata
* The output stream to which data should be written.
*/
- private void setVariableSpaceCharacterIncrement(int incr, ByteArrayOutputStream afpdata) {
+ private void setVariableSpaceCharacterIncrement(int incr,
+ ByteArrayOutputStream afpdata) {
byte[] b = BinaryUtils.convert(incr, 2);
afpdata.write(new byte[] {
- 4 // Control sequence length
- , (byte)0xC5 // Control sequence function type
- , b[0]
- , b[1]
- }, 0, 4);
+ 4, // Control sequence length
+ (byte) 0xC5, // Control sequence function type
+ b[0], b[1] },
+ 0, 4);
}
/**
- * //TODO
- * This is a modal control sequence.
- *
+ * //TODO This is a modal control sequence.
+ *
* @param incr
* The increment to be set.
* @param afpdata
private void setInterCharacterAdjustment(int incr, ByteArrayOutputStream afpdata) {
byte[] b = BinaryUtils.convert(Math.abs(incr), 2);
afpdata.write(new byte[] {
- 5 // Control sequence length
- , (byte)0xC3 // Control sequence function type
- , b[0]
- , b[1]
- , (byte)(incr >= 0 ? 0 : 1) // Direction
- }, 0, 5);
+ 5, // Control sequence length
+ (byte) 0xC3, // Control sequence function type
+ b[0], b[1], (byte) (incr >= 0 ? 0 : 1) // Direction
+ }, 0, 5);
}
/**
* and zero or more parameters. The control sequence can extend multiple
* presentation text data objects, but must eventually be terminated. This
* method terminates the control sequence.
- *
+ *
* @throws MaximumSizeExceededException
+ * thrown in the event that maximum size has been exceeded
*/
public void endControlSequence() throws MaximumSizeExceededException {
byte[] data = new byte[2];
import java.io.OutputStream;
import java.util.List;
+import org.apache.fop.render.afp.AFPTextDataInfo;
+
/**
* The Presentation Text object is the data object used in document processing
* environments for representing text which has been prepared for presentation.
/**
* Create the presentation text data for the byte array of data.
*
- * @param fontNum
- * The font resource identifier.
- * @param x
- * The x coordinate for the text data.
- * @param y
- * The y coordinate for the text data.
- * @param col
- * The text color.
- * @param vsci
- * The variable space character increment.
- * @param ica
- * The inter character increment.
- * @param data
- * The text data to be created.
- */
- public void createTextData(int fontNum, int x, int y, Color col,
- int vsci, int ica, byte[] data) {
- // Use a default orientation of zero
- createTextData(fontNum, x, y, 0, col, vsci, ica, data);
- }
-
- /**
- * Create the presentation text data for the byte array of data.
- *
- * @param fontRef
- * The font resource identifier.
- * @param x
- * The x coordinate for the text data.
- * @param y
- * The y coordinate for the text data.
- * @param orientation
- * The orientation of the text data.
- * @param col
- * The text color.
- * @param vsci
- * The variable space character increment.
- * @param ica
- * The inter character adjustment.
- * @param data
- * The text data to be created.
+ * @param textDataInfo
+ * The afp text data
*/
- public void createTextData(int fontRef, int x, int y, int orientation,
- Color col, int vsci, int ica, byte[] data) {
+ public void createTextData(AFPTextDataInfo textDataInfo) {
if (currentPresentationTextData == null) {
startPresentationTextData();
}
try {
- currentPresentationTextData.createTextData(fontRef, x, y,
- orientation, col, vsci, ica, data);
+ currentPresentationTextData.createTextData(textDataInfo);
} catch (MaximumSizeExceededException msee) {
endPresentationTextData();
- createTextData(fontRef, x, y, orientation, col, vsci, ica, data);
+ createTextData(textDataInfo);
}
}
import org.apache.fop.pdf.PDFXMode;
import org.apache.fop.pdf.PDFXObject;
import org.apache.fop.render.AbstractPathOrientedRenderer;
+import org.apache.fop.render.AbstractState;
import org.apache.fop.render.Graphics2DAdapter;
import org.apache.fop.render.RendererContext;
import org.apache.fop.util.CharUtilities;
*/
protected List breakOutOfStateStack() {
List breakOutList = new java.util.ArrayList();
- PDFState.Data data;
+ AbstractState.AbstractData data;
while (true) {
data = currentState.getData();
if (currentState.pop() == null) {
*/
protected void restoreStateStackAfterBreakOut(List breakOutList) {
comment("------ restoring context after break-out...");
- PDFState.Data data;
+ AbstractState.AbstractData data;
Iterator i = breakOutList.iterator();
while (i.hasNext()) {
- data = (PDFState.Data)i.next();
+ data = (AbstractState.AbstractData)i.next();
saveGraphicsState();
AffineTransform at = data.getTransform();
concatenateTransformationMatrix(at);