Browse Source

Fix for test/layoutengine/standard-testcases/block-container_absolute-position_fixed.xml.


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@709373 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-1_0
Adrian Cumiskey 15 years ago
parent
commit
c550e0349a

+ 128
- 0
src/java/org/apache/fop/AbstractData.java View File

@@ -0,0 +1,128 @@
package org.apache.fop;

import java.awt.Color;
import java.awt.geom.AffineTransform;
import java.io.Serializable;

/**
* A base state data holding object
*/
public abstract class AbstractData implements Cloneable, Serializable {

private static final long serialVersionUID = 5208418041189828624L;

/** The current color */
protected Color color = null;

/** The current background color */
protected Color backColor = null;

/** The current font name */
protected String fontName = null;

/** The current font size */
protected int fontSize = 0;

/** The current line width */
protected float lineWidth = 0;

/** The dash array for the current basic stroke (line type) */
protected float[] dashArray = null;

/** The current transform */
protected AffineTransform transform = null;

/**
* Returns a newly create data object
*
* @return a new data object
*/
protected abstract AbstractData instantiate();

/**
* 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;
}

/**
* Sets the current AffineTransform.
*/
public void setTransform(AffineTransform baseTransform) {
this.transform = baseTransform;
}

/**
* Resets the current AffineTransform.
*/
public void clearTransform() {
transform = new AffineTransform();
}

/**
* Returns the derived rotation from the current transform
*
* @return the derived rotation from the current transform
*/
public int getDerivedRotation() {
AffineTransform at = getTransform();
double sx = at.getScaleX();
double sy = at.getScaleY();
double shx = at.getShearX();
double shy = at.getShearY();
int rotation = 0;
if (sx == 0 && sy == 0 && shx > 0 && shy < 0) {
rotation = 270;
} else if (sx < 0 && sy < 0 && shx == 0 && shy == 0) {
rotation = 180;
} else if (sx == 0 && sy == 0 && shx < 0 && shy > 0) {
rotation = 90;
} else {
rotation = 0;
}
return rotation;
}

/** {@inheritDoc} */
public Object clone() {
AbstractData data = instantiate();
data.color = this.color;
data.backColor = this.backColor;
data.fontName = this.fontName;
data.fontSize = this.fontSize;
data.lineWidth = this.lineWidth;
data.dashArray = this.dashArray;
data.transform = new AffineTransform(this.transform);
return data;
}

/** {@inheritDoc} */
public String toString() {
return "color=" + color
+ ", backColor=" + backColor
+ ", fontName=" + fontName
+ ", fontSize=" + fontSize
+ ", lineWidth=" + lineWidth
+ ", dashArray=" + dashArray
+ ", transform=" + transform;
}

}

+ 72
- 160
src/java/org/apache/fop/AbstractState.java View File

@@ -23,8 +23,8 @@ import java.awt.Color;
import java.awt.geom.AffineTransform;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;


@@ -33,11 +33,13 @@ import java.util.Stack;
*/
public abstract class AbstractState implements Cloneable, Serializable {

private static final long serialVersionUID = 5998356138437094188L;

/** current state data */
private AbstractData currentData = null;
private AbstractData data = null;

/** the state stack */
private StateStack stateStack = null;
private StateStack stateStack = new StateStack();

/**
* Instantiates a new state data object
@@ -59,10 +61,10 @@ public abstract class AbstractState implements Cloneable, Serializable {
* @return the currently valid state
*/
public AbstractData getData() {
if (currentData == null) {
currentData = instantiateData();
if (data == null) {
data = instantiateData();
}
return currentData;
return data;
}

/**
@@ -212,7 +214,7 @@ public abstract class AbstractState implements Cloneable, Serializable {
*/
public AffineTransform getTransform() {
AffineTransform at = new AffineTransform();
for (Iterator iter = getStateStack().iterator(); iter.hasNext();) {
for (Iterator iter = stateStack.iterator(); iter.hasNext();) {
AbstractData data = (AbstractData)iter.next();
AffineTransform stackTrans = data.getTransform();
at.concatenate(stackTrans);
@@ -242,10 +244,10 @@ public abstract class AbstractState implements Cloneable, Serializable {
* @return the base transform, or null if the state stack is empty
*/
public AffineTransform getBaseTransform() {
if (getStateStack().isEmpty()) {
if (stateStack.isEmpty()) {
return null;
} else {
AbstractData baseData = (AbstractData)getStateStack().get(0);
AbstractData baseData = (AbstractData)stateStack.get(0);
return (AffineTransform) baseData.getTransform().clone();
}
}
@@ -260,12 +262,20 @@ public abstract class AbstractState implements Cloneable, Serializable {
}

/**
* Resets the current AffineTransform.
* Resets the current AffineTransform to the Base AffineTransform.
*/
public void resetTransform() {
getData().resetTransform();
getData().setTransform(getBaseTransform());
}

/**
* Clears the current AffineTransform to the Identity AffineTransform
*/
public void clearTransform() {
getData().clearTransform();
}


/**
* Push the current state onto the stack.
* This call should be used when the Q operator is used
@@ -273,7 +283,7 @@ public abstract class AbstractState implements Cloneable, Serializable {
*/
public void push() {
AbstractData copy = (AbstractData)getData().clone();
getStateStack().push(copy);
stateStack.push(copy);
}

/**
@@ -284,20 +294,62 @@ public abstract class AbstractState implements Cloneable, Serializable {
* @return the restored state, null if the stack is empty
*/
public AbstractData pop() {
if (!getStateStack().isEmpty()) {
this.currentData = (AbstractData)getStateStack().pop();
return this.currentData;
if (!stateStack.isEmpty()) {
setData((AbstractData)stateStack.pop());
return this.data;
} else {
return null;
}
}

/**
* Pushes all state data in the given list to the stack
*
* @param dataList a state data list
*/
public void pushAll(List/*<AbstractData>*/ dataList) {
Iterator it = dataList.iterator();
while (it.hasNext()) {
// save current data on stack
push();
setData((AbstractData)it.next());
}
}

/**
* Pops all state data from the stack
*
* @return a list of state data popped from the stack
*/
public List/*<AbstractData>*/ popAll() {
List/*<AbstractData>*/ dataList = new java.util.ArrayList/*<AbstractData>*/();
AbstractData data;
while (true) {
data = getData();
if (pop() == null) {
break;
}
// insert because of stack-popping
dataList.add(0, data);
}
return dataList;
}

/**
* Sets the current state data
*
* @param currentData state data
*/
protected void setData(AbstractData data) {
this.data = data;
}

/**
* Clears the state stack
*/
public void clear() {
getStateStack().clear();
currentData = null;
stateStack.clear();
setData(null);
}

/**
@@ -306,160 +358,20 @@ public abstract class AbstractState implements Cloneable, Serializable {
* @return the state stack
*/
protected Stack/*<AbstractData>*/ getStateStack() {
if (stateStack == null) {
stateStack = new StateStack();
}
return stateStack;
return this.stateStack;
}

/** {@inheritDoc} */
public Object clone() {
AbstractState state = instantiateState();
state.stateStack = new StateStack(this.stateStack);
state.currentData = (AbstractData)this.currentData.clone();
state.data = (AbstractData)this.data.clone();
return state;
}

/** {@inheritDoc} */
public String toString() {
return ", stateStack=" + stateStack
+ ", currentData=" + currentData;
}

/**
* A base state data holding object
*/
public abstract class AbstractData implements Cloneable, Serializable {

private static final long serialVersionUID = 5208418041189828624L;

/** 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 = getBaseTransform();
// transform = new AffineTransform();
}

/**
* Returns the derived rotation from the current transform
*
* @return the derived rotation from the current transform
*/
public int getDerivedRotation() {
AffineTransform at = getTransform();
double sx = at.getScaleX();
double sy = at.getScaleY();
double shx = at.getShearX();
double shy = at.getShearY();
int rotation = 0;
if (sx == 0 && sy == 0 && shx > 0 && shy < 0) {
rotation = 270;
} else if (sx < 0 && sy < 0 && shx == 0 && shy == 0) {
rotation = 180;
} else if (sx == 0 && sy == 0 && shx < 0 && shy > 0) {
rotation = 90;
} else {
rotation = 0;
}
return rotation;
}

/** {@inheritDoc} */
public Object clone() {
AbstractData data = instantiateData();
data.color = this.color;
data.backColor = this.backColor;
data.fontName = this.fontName;
data.fontSize = this.fontSize;
data.lineWidth = this.lineWidth;
data.dashArray = this.dashArray;
data.transform = new AffineTransform(this.transform);
return data;
}

/** {@inheritDoc} */
public String toString() {
return "color=" + color
+ ", backColor=" + backColor
+ ", fontName=" + fontName
+ ", fontSize=" + fontSize
+ ", lineWidth=" + lineWidth
+ ", dashArray=" + dashArray
+ ", transform=" + transform;
}
}

/**
* No copy constructor for java.util.Stack so extended and implemented one.
*/
private class StateStack extends java.util.Stack {

private static final long serialVersionUID = 4897178211223823041L;

/**
* Default constructor
*/
public StateStack() {
super();
}

/**
* Copy constructor
*
* @param c initial contents of stack
*/
public StateStack(Collection c) {
elementCount = c.size();
// 10% for growth
elementData = new Object[
(int)Math.min((elementCount * 110L) / 100, Integer.MAX_VALUE)];
c.toArray(elementData);
}
+ ", currentData=" + data;
}
}

+ 31
- 0
src/java/org/apache/fop/StateStack.java View File

@@ -0,0 +1,31 @@
package org.apache.fop;

import java.util.Collection;

/**
* No copy constructor for java.util.Stack so extended and implemented one.
*/
class StateStack extends java.util.Stack {

private static final long serialVersionUID = 4897178211223823041L;

/**
* Default constructor
*/
public StateStack() {
super();
}

/**
* Copy constructor
*
* @param c initial contents of stack
*/
public StateStack(Collection c) {
elementCount = c.size();
// 10% for growth
elementData = new Object[
(int)Math.min((elementCount * 110L) / 100, Integer.MAX_VALUE)];
c.toArray(elementData);
}
}

+ 7
- 1
src/java/org/apache/fop/afp/AFPState.java View File

@@ -21,6 +21,7 @@ package org.apache.fop.afp;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.AbstractData;
import org.apache.fop.AbstractState;

/**
@@ -483,7 +484,7 @@ public class AFPState extends org.apache.fop.AbstractState implements Cloneable
/**
* Block level state data
*/
private class AFPData extends org.apache.fop.AbstractState.AbstractData {
private class AFPData extends org.apache.fop.AbstractData {
private static final long serialVersionUID = -1789481244175275686L;

/** The current fill status */
@@ -506,6 +507,11 @@ public class AFPState extends org.apache.fop.AbstractState implements Cloneable
+ ", imageUri=" + imageUri
+ "}";
}

/** {@inheritDoc} */
protected AbstractData instantiate() {
return new AFPData();
}
}

}

+ 20
- 2
src/java/org/apache/fop/pdf/PDFState.java View File

@@ -19,12 +19,13 @@

package org.apache.fop.pdf;

import java.util.Iterator;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import java.util.Iterator;

import org.apache.fop.AbstractData;
import org.apache.fop.AbstractState;

/**
@@ -165,7 +166,19 @@ public class PDFState extends org.apache.fop.AbstractState {
return new PDFState();
}

private class PDFData extends org.apache.fop.AbstractState.AbstractData {
/**
* 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 data = getData();
AbstractData copy = (AbstractData)data.clone();
data.clearTransform();
getStateStack().add(copy);
}

private class PDFData extends org.apache.fop.AbstractData {

private static final long serialVersionUID = 3527950647293177764L;

@@ -206,6 +219,11 @@ public class PDFState extends org.apache.fop.AbstractState {
+ ", clip=" + clip
+ ", gstate=" + gstate;
}

/** {@inheritDoc} */
protected AbstractData instantiate() {
return new PDFData();
}
}

}

+ 8
- 5
src/java/org/apache/fop/render/AbstractPathOrientedRenderer.java View File

@@ -486,14 +486,14 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
CTM ctm = bv.getCTM();
int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore();

if (bv.getPositioning() == Block.ABSOLUTE
|| bv.getPositioning() == Block.FIXED) {
int positioning = bv.getPositioning();
if (positioning == Block.ABSOLUTE || positioning == 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) {
if (positioning == Block.FIXED) {
breakOutList = breakOutOfStateStack();
}

@@ -564,8 +564,11 @@ public abstract class AbstractPathOrientedRenderer extends PrintRenderer {
restoreGraphicsState();
}

if (breakOutList != null) {
restoreStateStackAfterBreakOut(breakOutList);
//For FIXED, we need to restore break out now we are done
if (positioning == Block.FIXED) {
if (breakOutList != null) {
restoreStateStackAfterBreakOut(breakOutList);
}
}

currentIPPosition = saveIP;

+ 2
- 18
src/java/org/apache/fop/render/afp/AFPRenderer.java View File

@@ -169,7 +169,6 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {

private AFPRectanglePainter rectanglePainter;


/**
* Constructor for AFPRenderer.
*/
@@ -509,28 +508,13 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
/** {@inheritDoc} */
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());
}
state.pushAll(breakOutList);
}

/** {@inheritDoc} */
protected List breakOutOfStateStack() {
log.debug("Block.FIXED --> break out");
List breakOutList = new java.util.ArrayList();
AbstractState.AbstractData data;
while (true) {
data = state.getData();
if (state.pop() == null) {
break;
}
breakOutList.add(0, data); //Insert because of stack-popping
}
return breakOutList;
return state.popAll();
}

/** {@inheritDoc} */

+ 16
- 16
src/java/org/apache/fop/render/pdf/PDFRenderer.java View File

@@ -40,17 +40,7 @@ import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.io.IOUtils;

import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.xmlgraphics.xmp.Metadata;
import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter;
import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema;

import org.apache.fop.AbstractState;
import org.apache.fop.AbstractData;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
@@ -118,6 +108,14 @@ import org.apache.fop.render.RendererContext;
import org.apache.fop.util.CharUtilities;
import org.apache.fop.util.ColorProfileUtil;
import org.apache.fop.util.ColorUtil;
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.xmlgraphics.xmp.Metadata;
import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter;
import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema;

/**
* Renderer that renders areas to PDF.
@@ -263,7 +261,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
protected Map filterMap;

/** Image handler registry */
private PDFImageHandlerRegistry imageHandlerRegistry = new PDFImageHandlerRegistry();
private final PDFImageHandlerRegistry imageHandlerRegistry = new PDFImageHandlerRegistry();

/**
* create the PDF renderer
@@ -1095,8 +1093,9 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
* @return the saved state stack to recreate later
*/
protected List breakOutOfStateStack() {
// return currentState.popAll();
List breakOutList = new java.util.ArrayList();
AbstractState.AbstractData data;
AbstractData data;
while (true) {
data = currentState.getData();
if (currentState.pop() == null) {
@@ -1117,10 +1116,11 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
*/
protected void restoreStateStackAfterBreakOut(List breakOutList) {
comment("------ restoring context after break-out...");
AbstractState.AbstractData data;
// currentState.pushAll(breakOutList);
AbstractData data;
Iterator i = breakOutList.iterator();
while (i.hasNext()) {
data = (AbstractState.AbstractData)i.next();
data = (AbstractData)i.next();
saveGraphicsState();
AffineTransform at = data.getTransform();
concatenateTransformationMatrix(at);
@@ -1609,7 +1609,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
endTextObject();
putImage(url, pos, foreignAttributes);
}
/**
* Adds a PDF XObject (a bitmap or form) to the PDF that will later be referenced.
* @param uri URL of the bitmap

Loading…
Cancel
Save