From 49dd6d899bc06a5554dfec23e8c1363f08638ffa Mon Sep 17 00:00:00 2001 From: Jeremias Maerki Date: Tue, 30 May 2006 15:53:12 +0000 Subject: [PATCH] Changed the way the graphics state handling is done to make a cleaner "break out" for fixed block-containers possible. Fixed block-containers are now working correctly. The Java2D renderer as well as its descendants are now basically on the same feature level as PDF and PS. All area tree elements get rendered correctly. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@410308 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/render/awt/AWTRenderer.java | 4 +- .../java2d/Java2DGraphics2DAdapter.java | 5 +- .../render/java2d/Java2DGraphicsState.java | 150 +++++++----------- .../fop/render/java2d/Java2DRenderer.java | 79 ++++----- .../fop/render/java2d/Java2DSVGHandler.java | 2 - .../fop/render/java2d/RendererState.java | 135 ---------------- 6 files changed, 105 insertions(+), 270 deletions(-) delete mode 100644 src/java/org/apache/fop/render/java2d/RendererState.java diff --git a/src/java/org/apache/fop/render/awt/AWTRenderer.java b/src/java/org/apache/fop/render/awt/AWTRenderer.java index 9e079b7b9..f04158b83 100644 --- a/src/java/org/apache/fop/render/awt/AWTRenderer.java +++ b/src/java/org/apache/fop/render/awt/AWTRenderer.java @@ -260,7 +260,7 @@ public class AWTRenderer extends Java2DRenderer implements Pageable { float width, float height) { // saves the graphics state in a stack - state.push(); + saveGraphicsState(); Color col = new Color(0.7f, 0.7f, 0.7f); state.updateColor(col); @@ -269,7 +269,7 @@ public class AWTRenderer extends Java2DRenderer implements Pageable { new Rectangle2D.Float(startx, starty, width, height)); // restores the last graphics state from the stack - state.pop(); + restoreGraphicsState(); } } diff --git a/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java b/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java index dda6d7005..2f89632fe 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java +++ b/src/java/org/apache/fop/render/java2d/Java2DGraphics2DAdapter.java @@ -61,7 +61,8 @@ public class Java2DGraphics2DAdapter implements Graphics2DAdapter { float sx = fwidth / (float)imw; float sy = fheight / (float)imh; - state.push(); + Java2DRenderer renderer = (Java2DRenderer)context.getRenderer(); + renderer.saveGraphicsState(); state.getGraph().setColor(Color.black); state.getGraph().setBackground(Color.black); @@ -79,7 +80,7 @@ public class Java2DGraphics2DAdapter implements Graphics2DAdapter { Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh); painter.paint(state.getGraph(), area); - state.pop(); + renderer.restoreGraphicsState(); } diff --git a/src/java/org/apache/fop/render/java2d/Java2DGraphicsState.java b/src/java/org/apache/fop/render/java2d/Java2DGraphicsState.java index 1be08aa9c..aa3acdb23 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DGraphicsState.java +++ b/src/java/org/apache/fop/render/java2d/Java2DGraphicsState.java @@ -26,7 +26,6 @@ import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Area; import java.awt.geom.GeneralPath; -import java.util.List; import org.apache.fop.fo.Constants; import org.apache.fop.fonts.FontInfo; @@ -37,7 +36,7 @@ import org.apache.fop.fonts.FontInfo; *

* The graphics context is updated with the updateXXX() methods. */ -public class Java2DGraphicsState implements Constants, RendererState { +public class Java2DGraphicsState { /** Holds the datas of the current state */ private Graphics2D currentGraphics; @@ -48,8 +47,6 @@ public class Java2DGraphicsState implements Constants, RendererState { private int currentStrokeStyle; - private List stateStack = new java.util.ArrayList(); - /** Font configuration, passed from AWTRenderer */ private FontInfo fontInfo; @@ -70,6 +67,19 @@ public class Java2DGraphicsState implements Constants, RendererState { currentGraphics.setTransform(at); } + /** + * Copy constructor. + * @param org the instance to copy + */ + public Java2DGraphicsState(Java2DGraphicsState org) { + this.currentGraphics = (Graphics2D)org.currentGraphics.create(); + this.fontInfo = org.fontInfo; + this.initialTransform = org.initialTransform; + this.currentStroke = org.currentStroke; + this.currentStrokeStyle = org.currentStrokeStyle; + this.currentStrokeWidth = org.currentStrokeWidth; + } + /** * @return the currently valid state */ @@ -77,43 +87,13 @@ public class Java2DGraphicsState implements Constants, RendererState { return currentGraphics; } - /** @see org.apache.fop.render.java2d.RendererState#push() */ - public void push() { - Graphics2D tmpGraphics = (Graphics2D) currentGraphics.create(); - stateStack.add(tmpGraphics); - } - - /** @see org.apache.fop.render.java2d.RendererState#pop() */ - public Graphics2D pop() { - if (getStackLevel() > 0) { - Graphics2D popped = (Graphics2D) stateStack.remove(stateStack - .size() - 1); - - currentGraphics.dispose(); - currentGraphics = popped; - return popped; - } else { - return null; - } - } - - /** @see org.apache.fop.render.java2d.RendererState#getStackLevel() */ - public int getStackLevel() { - return stateStack.size(); + /** Frees resources allocated by the current Graphics2D instance. */ + public void dispose() { + this.currentGraphics.dispose(); + this.currentGraphics = null; + } - /** - * 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 background color. Check if the background color will * change and then set the new color. @@ -138,10 +118,14 @@ public class Java2DGraphicsState implements Constants, RendererState { } /** - * @see org.apache.fop.render.java2d.RendererState#updateFont(java.lang.String, - * int, java.lang.StringBuffer) + * Set the current font name. Check if the font name will change and then + * set the new name. + * + * @param name the new font name + * @param size the font size + * @return true if the new Font changes the current Font */ - public boolean updateFont(String name, int size, StringBuffer pdf) { + public boolean updateFont(String name, int size) { FontMetricsMapper mapper = (FontMetricsMapper)fontInfo.getMetricsFor(name); boolean updateName = (!mapper.getFontName().equals( @@ -159,15 +143,18 @@ public class Java2DGraphicsState implements Constants, RendererState { } } - /** - * @return the current java.awt.Font - */ + /** @return the current java.awt.Font */ public java.awt.Font getFont() { return currentGraphics.getFont(); } /** - * @see org.apache.fop.render.java2d.RendererState#updateStroke(float, int) + * Sets the current Stroke. The line width should be set with + * updateLineWidth() before calling this method + * + * @param width the line width + * @param style the constant for the style of the line as an int + * @return true if the new Stroke changes the current Stroke */ public boolean updateStroke(float width, int style) { @@ -179,7 +166,7 @@ public class Java2DGraphicsState implements Constants, RendererState { update = true; switch (style) { - case EN_DOTTED: + case Constants.EN_DOTTED: currentStroke = new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL, 0f, new float[] {0, 2 * width}, width); @@ -190,7 +177,7 @@ public class Java2DGraphicsState implements Constants, RendererState { break; - case EN_DASHED: + case Constants.EN_DASHED: currentStroke = new BasicStroke(width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0f, new float[] {8f, 2f}, 0f); @@ -221,7 +208,13 @@ public class Java2DGraphicsState implements Constants, RendererState { return (BasicStroke) currentGraphics.getStroke(); } - /** @see org.apache.fop.render.java2d.RendererState#updatePaint(java.awt.Paint) */ + /** + * Set the current paint. This checks if the paint will change and then sets + * the current paint. + * + * @param p the new paint + * @return true if the new paint changes the current paint + */ public boolean updatePaint(Paint p) { if (getGraph().getPaint() == null) { if (p != null) { @@ -235,22 +228,12 @@ public class Java2DGraphicsState implements Constants, RendererState { return false; } - /** @see org.apache.fop.render.java2d.RendererState#checkClip(java.awt.Shape) */ - // TODO implement and test - public boolean checkClip(Shape cl) { - if (getGraph().getClip() == null) { - if (cl != null) { - return true; - } - } else if (cl.equals(getGraph().getClip())) { - return true; - } - // TODO check for clips that are larger than the current - return false; - } - /** - * @see org.apache.fop.render.java2d.RendererState#updateClip(java.awt.Shape) + * Set the current clip. This either sets a new clip or sets the clip to the + * intersect of the old clip and the new clip. + * + * @param cl the new clip in the current state + * @return true if the clip shape needed to be updated */ public boolean updateClip(Shape cl) { if (getGraph().getClip() != null) { @@ -264,40 +247,23 @@ public class Java2DGraphicsState implements Constants, RendererState { } /** - * @see org.apache.fop.render.java2d.RendererState#checkTransform(java.awt.geom.AffineTransform) - */ - public boolean checkTransform(AffineTransform tf) { - return !tf.equals(getGraph().getTransform()); - } - - /** - * @see org.apache.fop.render.java2d.RendererState#setTransform(java.awt.geom.AffineTransform) - */ - public void setTransform(AffineTransform tf) { - //apply initial transformation - getGraph().setTransform(initialTransform); - getGraph().transform(tf); - } - - /** - * @see org.apache.fop.render.java2d.RendererState#transform(java.awt.geom.AffineTransform) + * Composes an AffineTransform object with the Transform in this Graphics2D + * according to the rule last-specified-first-applied. + * @see java.awt.Graphics2D#transform(AffineTransform tf). + * + * @param tf the transform to concatonate to the current level transform */ public void transform(AffineTransform tf) { getGraph().transform(tf); } /** - * @see org.apache.fop.render.java2d.RendererState#getTransform() + * 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(getCurrentGraphics().transform); - * - * return at; - */ return getGraph().getTransform(); } @@ -305,8 +271,8 @@ public class Java2DGraphicsState implements Constants, RendererState { public String toString() { String s = "AWTGraphicsState " + currentGraphics.toString() + ", Stroke (width: " + currentStrokeWidth + " style: " - + currentStrokeStyle + "), " + getTransform() - + ", StackLevel: " + getStackLevel(); + + currentStrokeStyle + "), " + getTransform(); return s; } + } diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java index 2d771d75d..3405c3ae4 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java +++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java @@ -48,6 +48,7 @@ import java.io.OutputStream; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Stack; import org.w3c.dom.Document; @@ -127,6 +128,8 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem /** The current state, holds a Graphics2D and its context */ protected Java2DGraphicsState state; + + private Stack stateStack = new Stack(); /** true if the renderer has finished rendering all the pages */ private boolean renderingDone; @@ -317,13 +320,17 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem graphics.drawLine(1, pageHeight + 3, pageWidth + 3, pageHeight + 3); state = new Java2DGraphicsState(graphics, this.fontInfo, at); + try { + // reset the current Positions + currentBPPosition = 0; + currentIPPosition = 0; + + // this toggles the rendering of all areas + renderPageAreas(pageViewport.getPage()); + } finally { + state = null; + } - // reset the current Positions - currentBPPosition = 0; - currentIPPosition = 0; - - // this toggles the rendering of all areas - renderPageAreas(pageViewport.getPage()); return currentPageImage; } finally { this.currentPageViewport = null; @@ -361,12 +368,14 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem /** Saves the graphics state of the rendering engine. */ protected void saveGraphicsState() { // push (and save) the current graphics state - state.push(); + stateStack.push(state); + state = new Java2DGraphicsState(state); } /** Restores the last graphics state of the rendering engine. */ protected void restoreGraphicsState() { - state.pop(); + state.dispose(); + state = (Java2DGraphicsState)stateStack.pop(); } /** @@ -395,42 +404,36 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem restoreGraphicsState(); } - /** - * @see org.apache.fop.render.AbstractPathOrientedRenderer#restoreStateStackAfterBreakOut( - * java.util.List) - */ - protected void restoreStateStackAfterBreakOut(List breakOutList) { - log.debug( - "Block.FIXED --> restoring context after break-out"); - Graphics2D graph; - Iterator i = breakOutList.iterator(); - while (i.hasNext()) { - graph = (Graphics2D) i.next(); - log.debug("Restoring: " + graph); - state.push(); - } - } - /** * @see org.apache.fop.render.AbstractPathOrientedRenderer#breakOutOfStateStack() */ protected List breakOutOfStateStack() { - List breakOutList; log.debug("Block.FIXED --> break out"); + List breakOutList; breakOutList = new java.util.ArrayList(); - Graphics2D graph; - while (true) { - graph = state.getGraph(); - if (state.pop() == null) { - break; - } - breakOutList.add(0, graph); // Insert because of - // stack-popping - log.debug("Adding to break out list: " + graph); + while (!stateStack.isEmpty()) { + breakOutList.add(0, state); + //We only pop, we don't dispose, because we can use the instances again later + state = (Java2DGraphicsState)stateStack.pop(); } return breakOutList; } + /** + * @see org.apache.fop.render.AbstractPathOrientedRenderer#restoreStateStackAfterBreakOut( + * java.util.List) + */ + protected void restoreStateStackAfterBreakOut(List breakOutList) { + log.debug("Block.FIXED --> restoring context after break-out"); + + Iterator i = breakOutList.iterator(); + while (i.hasNext()) { + Java2DGraphicsState s = (Java2DGraphicsState)i.next(); + stateStack.push(state); + state = s; + } + } + /** * @see org.apache.fop.render.AbstractPathOrientedRenderer#updateColor( * org.apache.fop.datatypes.ColorType, boolean) @@ -675,7 +678,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem int saveIP = currentIPPosition; Font font = getFontFromArea(text); - state.updateFont(font.getFontName(), font.getFontSize(), null); + state.updateFont(font.getFontName(), font.getFontSize()); saveGraphicsState(); AffineTransform at = new AffineTransform(); at.translate(rx / 1000f, bl / 1000f); @@ -951,8 +954,10 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem return NO_SUCH_PAGE; } + if (state != null) { + throw new IllegalStateException("state must be null"); + } Graphics2D graphics = (Graphics2D) g; - Java2DGraphicsState oldState = state; try { PageViewport viewport = getPageViewport(pageIndex); AffineTransform at = graphics.getTransform(); @@ -968,7 +973,7 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem log.error(e); return NO_SUCH_PAGE; } finally { - state = oldState; + state = null; } } diff --git a/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java b/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java index c7fc7e9d3..ec351ae9b 100644 --- a/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java +++ b/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java @@ -22,11 +22,9 @@ import java.awt.geom.AffineTransform; import org.w3c.dom.Document; -import org.apache.fop.apps.MimeConstants; import org.apache.fop.render.Renderer; import org.apache.fop.render.XMLHandler; import org.apache.fop.render.RendererContext; -import org.apache.fop.render.pdf.PDFRenderer; import org.apache.fop.svg.SVGUserAgent; // Commons-Logging diff --git a/src/java/org/apache/fop/render/java2d/RendererState.java b/src/java/org/apache/fop/render/java2d/RendererState.java deleted file mode 100644 index bd04118fc..000000000 --- a/src/java/org/apache/fop/render/java2d/RendererState.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2005-2006 The Apache Software Foundation. - * - * Licensed 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.java2d; - -import java.awt.Graphics2D; -import java.awt.Paint; -import java.awt.Shape; -import java.awt.geom.AffineTransform; - - -/** - * An interface for the classes which hold the state of the current graphics context. - */ -public interface RendererState { - - /** - * Push the current state onto the stack. - */ - public abstract void push(); - - /** - * Pop the state from the stack and restore the graphics context. - * @return the restored state, null if the stack is empty. - */ - public abstract Graphics2D pop(); - - /** - * Get the current stack level. - * - * @return the current stack level - */ - public abstract int getStackLevel(); - - /** - * Set the current font name. Check if the font name will change and then - * set the new name. - * - * @param name the new font name - * @param size - * @param pdf - * @return true if the new Font changes the current Font - */ - public abstract boolean updateFont(String name, int size, StringBuffer pdf); - - /** - * Sets the current Stroke. The line width should be set with - * updateLineWidth() before calling this method - * - * @param style the constant for the style of the line as an int - * @return true if the new Stroke changes the current Stroke - */ - public abstract boolean updateStroke(float width, int style); - - /** - * Set the current paint. This checks if the paint will change and then sets - * the current paint. - * - * @param p the new paint - * @return true if the new paint changes the current paint - */ - public abstract boolean updatePaint(Paint p); - - /** - * Check if the clip will change the current state. A clip is assumed to be - * used in a situation where it will add to any clip in the current or - * parent states. A clip cannot be cleared, this can only be achieved by - * going to a parent level with the correct clip. If the clip is different - * then it may start a new state so that it can return to the previous clip. - * - * @param cl the clip shape to check - * @return true if the clip will change the current clip. - */ - // TODO test - public abstract boolean checkClip(Shape cl); - - /** - * Set the current clip. This either sets a new clip or sets the clip to the - * intersect of the old clip and the new clip. - * - * @param cl the new clip in the current state - */ - public abstract boolean updateClip(Shape 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 to check against - * @return true if the new transform is different from the current transform - */ - public abstract boolean checkTransform(AffineTransform tf); - - /** - * Overwrites the Transform in the Graphics2D context. Use transform() if you - * wish to compose with the current Affinetransform instead. - * @see java.awt.Graphics2D#setTransform(AffineTransform tf). - * @param tf the transform to concatonate to the current level transform - */ - public abstract void setTransform(AffineTransform tf); - - /** - * Composes an AffineTransform object with the Transform in this Graphics2D - * according to the rule last-specified-first-applied. - * @see java.awt.Graphics2D#transform(AffineTransform tf). - * - * @param tf the transform to concatonate to the current level transform - */ - public abstract void transform(AffineTransform 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 abstract AffineTransform getTransform(); - -} -- 2.39.5