Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPSVGHandler.java URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPSVGHandler.java?rev=711273&r1=711272&r2=711273&view=diff ============================================================================== --- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPSVGHandler.java (original) +++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPSVGHandler.java Tue Nov 4 07:30:38 2008 @@ -20,6 +20,7 @@ package org.apache.fop.render.afp; // FOP +import java.awt.Dimension; import java.awt.geom.AffineTransform; import java.awt.geom.Dimension2D; import java.io.IOException; @@ -36,14 +37,16 @@ import org.apache.fop.afp.AFPGraphics2D; import org.apache.fop.afp.AFPGraphicsObjectInfo; import org.apache.fop.afp.AFPObjectAreaInfo; +import org.apache.fop.afp.AFPPaintingState; import org.apache.fop.afp.AFPResourceInfo; +import org.apache.fop.afp.AFPResourceLevel; import org.apache.fop.afp.AFPResourceManager; -import org.apache.fop.afp.AFPState; import org.apache.fop.afp.AFPTextElementBridge; import org.apache.fop.afp.AFPTextHandler; import org.apache.fop.afp.AFPTextPainter; import org.apache.fop.afp.AFPUnitConverter; -import org.apache.fop.fo.extensions.ExtensionElementMapping; +import org.apache.fop.afp.Graphics2DImagePainterGOCA; +import org.apache.fop.fonts.FontInfo; import org.apache.fop.render.AbstractGenericSVGHandler; import org.apache.fop.render.Renderer; import org.apache.fop.render.RendererContext; @@ -51,7 +54,7 @@ import org.apache.fop.render.RendererContext.RendererContextWrapper; import org.apache.fop.svg.SVGEventProducer; import org.apache.fop.svg.SVGUserAgent; -import org.apache.xmlgraphics.util.QName; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; import org.w3c.dom.Document; /** @@ -61,9 +64,7 @@ */ public class AFPSVGHandler extends AbstractGenericSVGHandler { - /** foreign attribute reader */ - private final AFPForeignAttributeReader foreignAttributeReader - = new AFPForeignAttributeReader(); + private boolean paintAsBitmap = false; /** [EMAIL PROTECTED] */ public void handleXML(RendererContext context, @@ -88,21 +89,24 @@ afpi.setHandlerConfiguration((Configuration)context.getProperty(HANDLER_CONFIGURATION)); afpi.setFontInfo((org.apache.fop.fonts.FontInfo)context.getProperty( AFPRendererContextConstants.AFP_FONT_INFO)); - afpi.setState((AFPState)context.getProperty( - AFPRendererContextConstants.AFP_STATE)); + afpi.setPaintingState((AFPPaintingState)context.getProperty( + AFPRendererContextConstants.AFP_PAINTING_STATE)); afpi.setResourceManager(((AFPResourceManager)context.getProperty( AFPRendererContextConstants.AFP_RESOURCE_MANAGER))); Map foreignAttributes = (Map)context.getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES); if (foreignAttributes != null) { + String conversionMode = (String)foreignAttributes.get(CONVERSION_MODE); + boolean paintAsBitmap = BITMAP.equalsIgnoreCase(conversionMode); + afpi.setPaintAsBitmap(paintAsBitmap); + AFPForeignAttributeReader foreignAttributeReader = new AFPForeignAttributeReader(); AFPResourceInfo resourceInfo = foreignAttributeReader.getResourceInfo(foreignAttributes); - afpi.setResourceInfo(resourceInfo); - - QName qName = new QName(ExtensionElementMapping.URI, null, "conversion-mode"); - if ("bitmap".equalsIgnoreCase((String)foreignAttributes.get(qName))) { - afpi.setPaintAsBitmap(true); + // default to inline level if painted as GOCA + if (!resourceInfo.levelChanged() && !paintAsBitmap) { + resourceInfo.setLevel(new AFPResourceLevel(AFPResourceLevel.INLINE)); } + afpi.setResourceInfo(resourceInfo); } return afpi; } @@ -122,8 +126,10 @@ AFPInfo afpInfo = getAFPInfo(context); + this.paintAsBitmap = afpInfo.paintAsBitmap(); + // fallback paint as bitmap - if (afpInfo.paintAsBitmap()) { + if (paintAsBitmap) { try { super.renderSVGDocument(context, doc); } catch (IOException ioe) { @@ -135,8 +141,8 @@ } String uri = ((AbstractDocument)doc).getDocumentURI(); - AFPState state = afpInfo.getState(); - state.setImageUri(uri); + AFPPaintingState paintingState = afpInfo.getPaintingState(); + paintingState.setImageUri(uri); // set the data object parameters AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo(); @@ -146,7 +152,7 @@ int curry = rctx.getCurrentYPosition(); float[] srcPts = {currx, curry}; - AFPUnitConverter unitConv = state.getUnitConverter(); + AFPUnitConverter unitConv = paintingState.getUnitConverter(); int[] coords = unitConv.mpts2units(srcPts); objectAreaInfo.setX(coords[X]); objectAreaInfo.setY(coords[Y]); @@ -161,7 +167,7 @@ int height = Math.round(unitConv.mpt2units(afpInfo.getHeight())); objectAreaInfo.setHeight(height); - int rotation = state.getRotation(); + int rotation = paintingState.getRotation(); objectAreaInfo.setRotation(rotation); AFPGraphicsObjectInfo graphicsObjectInfo = new AFPGraphicsObjectInfo(); @@ -171,14 +177,22 @@ final boolean textAsShapes = false; AFPGraphics2D g2d = new AFPGraphics2D(textAsShapes); - g2d.setResourceManager(afpInfo.getResourceManager()); - g2d.setResourceInfo(afpInfo.getResourceInfo()); - g2d.setState(afpInfo.getState()); + g2d.setPaintingState(paintingState); + + AFPResourceManager resourceManager = afpInfo.getResourceManager(); + g2d.setResourceManager(resourceManager); + + AFPResourceInfo resourceInfo = afpInfo.getResourceInfo(); + g2d.setResourceInfo(resourceInfo); + graphicsObjectInfo.setResourceInfo(resourceInfo); + g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); - g2d.setFontInfo(afpInfo.getFontInfo()); + + FontInfo fontInfo = afpInfo.getFontInfo(); + g2d.setFontInfo(fontInfo); // Configure GraphicsObjectPainter with the Graphics2D implementation - AFPBatikGraphicsObjectPainter painter = new AFPBatikGraphicsObjectPainter(g2d); + GraphicsObjectPainterAFP painter = new GraphicsObjectPainterAFP(g2d); (graphicsObjectInfo).setPainter(painter); // Controls whether text painted by Batik is generated using text or path operations @@ -194,12 +208,6 @@ ctx.putBridge(tBridge); } - Map/*<QName, String>*/ foreignAttributes - = (Map/*<QName, String>*/)context.getProperty( - RendererContextConstants.FOREIGN_ATTRIBUTES); - AFPResourceInfo resourceInfo = foreignAttributeReader.getResourceInfo(foreignAttributes); - graphicsObjectInfo.setResourceInfo(resourceInfo); - // Build the SVG DOM and provide the painter with it GraphicsNode root; GVTBuilder builder = new GVTBuilder(); @@ -221,13 +229,12 @@ double hx = (afpInfo.getHeight() / h); double scaleX = unitConv.pt2units((float)wx); double scaleY = unitConv.pt2units((float)hx); - double xOffset = unitConv.mpt2units(afpInfo.getX()); double yOffset = unitConv.mpt2units(afpInfo.getHeight()); // 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(scaleX, 0, 0, -scaleY, xOffset, yOffset); + AffineTransform trans = new AffineTransform(scaleX, 0, 0, -scaleY, 0, yOffset); g2d.setTransform(trans); // Set the afp graphics 2d implementation @@ -236,8 +243,6 @@ // Set the object area info graphicsObjectInfo.setObjectAreaInfo(objectAreaInfo); - AFPResourceManager resourceManager = afpInfo.getResourceManager(); - // Create the graphics object resourceManager.createObject(graphicsObjectInfo); } @@ -253,4 +258,24 @@ context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE, Boolean.FALSE); } + /** [EMAIL PROTECTED] */ + protected Graphics2DImagePainter createPainter(BridgeContext ctx, GraphicsNode root, Dimension imageSize) { + Graphics2DImagePainter painter = null; + if (paintAsBitmap()) { + painter = super.createPainter(root, ctx, imageSize); + } else { + painter = new Graphics2DImagePainterGOCA(root, ctx, imageSize); + } + return painter; + } + + /** + * Returns true if the SVG is to be painted as a bitmap + * + * @return true if the SVG is to be painted as a bitmap + */ + private boolean paintAsBitmap() { + return paintAsBitmap; + } + }
Copied: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/GraphicsObjectPainterAFP.java (from r708875, xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPBatikGraphicsObjectPainter.java) URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/GraphicsObjectPainterAFP.java?p2=xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/GraphicsObjectPainterAFP.java&p1=xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPBatikGraphicsObjectPainter.java&r1=708875&r2=711273&rev=711273&view=diff ============================================================================== --- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/AFPBatikGraphicsObjectPainter.java (original) +++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/GraphicsObjectPainterAFP.java Tue Nov 4 07:30:38 2008 @@ -24,13 +24,20 @@ import java.awt.geom.Rectangle2D; import org.apache.batik.gvt.GraphicsNode; -import org.apache.fop.afp.AFPAbstractGraphicsObjectPainter; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.fop.afp.AFPGraphics2D; +import org.apache.fop.afp.modca.GraphicsObject; +import org.apache.xmlgraphics.java2d.Graphics2DImagePainter; /** * Paints SVG as a GOCA Graphics Object using Batik */ -public class AFPBatikGraphicsObjectPainter extends AFPAbstractGraphicsObjectPainter { +public class GraphicsObjectPainterAFP implements Graphics2DImagePainter { + /** Static logging instance */ + protected static Log log = LogFactory.getLog(GraphicsObjectPainterAFP.class); + + private final AFPGraphics2D graphics2D; /** the batik root node of the svg document */ private GraphicsNode root; @@ -40,8 +47,9 @@ * * @param graphics an AFP graphics 2D implementation */ - public AFPBatikGraphicsObjectPainter(AFPGraphics2D graphics) { - super(graphics); + public GraphicsObjectPainterAFP(AFPGraphics2D graphics) { + final boolean textAsShapes = false; + this.graphics2D = new AFPGraphics2D(textAsShapes); } /** @@ -69,4 +77,13 @@ return null; } + /** + * Sets the GOCA Graphics Object + * + * @param graphicsObject the GOCA Graphics Object + */ + public void setGraphicsObject(GraphicsObject graphicsObject) { + this.graphics2D.setGraphicsObject(graphicsObject); + } + } Propchange: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/GraphicsObjectPainterAFP.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/GraphicsObjectPainterAFP.java ------------------------------------------------------------------------------ svn:keywords = Revision Id Propchange: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/afp/GraphicsObjectPainterAFP.java ------------------------------------------------------------------------------ --- svn:mergeinfo (added) +++ svn:mergeinfo Tue Nov 4 07:30:38 2008 @@ -0,0 +1,2 @@ +/xmlgraphics/fop/branches/fop-0_95/src/java/org/apache/fop/render/afp/AFPBatikGraphicsObjectPainter.java:684572,688085,688696 +/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/AFPBatikGraphicsObjectPainter.java:693433-698670,699739,704008-704909,705529-706135,706272-706276,706319-707083,707627,707631-708012,708192-708851 Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java?rev=711273&r1=711272&r2=711273&view=diff ============================================================================== --- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java (original) +++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/java2d/Java2DSVGHandler.java Tue Nov 4 07:30:38 2008 @@ -23,22 +23,18 @@ import java.io.IOException; import java.util.Map; -import org.w3c.dom.Document; - import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.GVTBuilder; import org.apache.batik.gvt.GraphicsNode; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - -import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.render.AbstractGenericSVGHandler; import org.apache.fop.render.Renderer; import org.apache.fop.render.RendererContext; import org.apache.fop.render.RendererContextConstants; import org.apache.fop.svg.SVGEventProducer; import org.apache.fop.svg.SVGUserAgent; -import org.apache.xmlgraphics.util.QName; +import org.w3c.dom.Document; /** * Java2D XML handler for SVG (uses Apache Batik). @@ -72,9 +68,8 @@ pdfi.currentXPosition = ((Integer)context.getProperty(XPOS)).intValue(); pdfi.currentYPosition = ((Integer)context.getProperty(YPOS)).intValue(); Map foreign = (Map)context.getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES); - QName qName = new QName(ExtensionElementMapping.URI, null, "conversion-mode"); if (foreign != null - && "bitmap".equalsIgnoreCase((String)foreign.get(qName))) { + && BITMAP.equalsIgnoreCase((String)foreign.get(CONVERSION_MODE))) { pdfi.paintAsBitmap = true; } return pdfi; Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java?rev=711273&r1=711272&r2=711273&view=diff ============================================================================== --- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java (original) +++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java Tue Nov 4 07:30:38 2008 @@ -95,8 +95,8 @@ AffineTransform transform = new AffineTransform(); transform.translate(fx, fy); - pdfInfo.pdfState.concatenate(transform); - graphics.setPDFState(pdfInfo.pdfState); + pdfInfo.pdfPaintingState.concatenate(transform); + graphics.setPaintingState(pdfInfo.pdfPaintingState); graphics.setOutputStream(pdfInfo.outputStream); if (pdfInfo.paintAsBitmap) { Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFRenderer.java URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFRenderer.java?rev=711273&r1=711272&r2=711273&view=diff ============================================================================== --- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFRenderer.java (original) +++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFRenderer.java Tue Nov 4 07:30:38 2008 @@ -40,7 +40,6 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.io.IOUtils; -import org.apache.fop.AbstractData; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.MimeConstants; @@ -95,9 +94,9 @@ import org.apache.fop.pdf.PDFOutputIntent; import org.apache.fop.pdf.PDFPage; import org.apache.fop.pdf.PDFPageLabels; +import org.apache.fop.pdf.PDFPaintingState; import org.apache.fop.pdf.PDFResourceContext; import org.apache.fop.pdf.PDFResources; -import org.apache.fop.pdf.PDFState; import org.apache.fop.pdf.PDFStream; import org.apache.fop.pdf.PDFTextUtil; import org.apache.fop.pdf.PDFXMode; @@ -105,9 +104,11 @@ import org.apache.fop.render.AbstractPathOrientedRenderer; import org.apache.fop.render.Graphics2DAdapter; import org.apache.fop.render.RendererContext; +import org.apache.fop.util.AbstractPaintingState; import org.apache.fop.util.CharUtilities; import org.apache.fop.util.ColorProfileUtil; import org.apache.fop.util.ColorUtil; +import org.apache.fop.util.AbstractPaintingState.AbstractData; import org.apache.xmlgraphics.image.loader.ImageException; import org.apache.xmlgraphics.image.loader.ImageInfo; import org.apache.xmlgraphics.image.loader.ImageManager; @@ -249,8 +250,8 @@ /** Optional URI to an output profile to be used. */ protected String outputProfileURI; - /** drawing state */ - protected PDFState currentState = null; + /** Painting state */ + protected PDFPaintingState paintingState = null; /** Text generation utility holding the current font status */ protected PDFTextUtil textutil; @@ -518,7 +519,7 @@ currentStream = null; currentContext = null; currentPage = null; - currentState = null; + paintingState = null; this.textutil = null; idPositions.clear(); @@ -639,7 +640,7 @@ /** [EMAIL PROTECTED] */ protected void saveGraphicsState() { endTextObject(); - currentState.push(); + paintingState.push(); currentStream.add("q\n"); } @@ -647,7 +648,7 @@ endTextObject(); currentStream.add("Q\n"); if (popState) { - currentState.pop(); + paintingState.pop(); } } @@ -782,11 +783,11 @@ } }; - currentState = new PDFState(); + paintingState = new PDFPaintingState(); // Transform the PDF's default coordinate system (0,0 at lower left) to the PDFRenderer's AffineTransform basicPageTransform = new AffineTransform(1, 0, 0, -1, 0, pageHeight / 1000f); - currentState.concatenate(basicPageTransform); + paintingState.concatenate(basicPageTransform); currentStream.add(CTMHelper.toPDFString(basicPageTransform, false) + " cm\n"); super.renderPage(page); @@ -806,7 +807,7 @@ protected void startVParea(CTM ctm, Rectangle2D clippingRect) { saveGraphicsState(); // Set the given CTM in the graphics state - currentState.concatenate( + paintingState.concatenate( new AffineTransform(CTMHelper.toPDFArray(ctm))); if (clippingRect != null) { @@ -827,7 +828,7 @@ /** [EMAIL PROTECTED] */ protected void concatenateTransformationMatrix(AffineTransform at) { if (!at.isIdentity()) { - currentState.concatenate(at); + paintingState.concatenate(at); currentStream.add(CTMHelper.toPDFString(at, false) + " cm\n"); } } @@ -1017,7 +1018,7 @@ * @param width line width in points */ private void updateLineWidth(float width) { - if (currentState.setLineWidth(width)) { + if (paintingState.setLineWidth(width)) { //Only write if value has changed WRT the current line width currentStream.add(format(width) + " w\n"); } @@ -1095,10 +1096,10 @@ protected List breakOutOfStateStack() { // return currentState.popAll(); List breakOutList = new java.util.ArrayList(); - AbstractData data; + AbstractPaintingState.AbstractData data; while (true) { - data = currentState.getData(); - if (currentState.pop() == null) { + data = paintingState.getData(); + if (paintingState.pop() == null) { break; } if (breakOutList.size() == 0) { @@ -1260,7 +1261,7 @@ */ protected void saveAbsolutePosition(String id, int relativeIPP, int relativeBPP) { saveAbsolutePosition(id, currentPageRef, - relativeIPP, relativeBPP, currentState.getTransform()); + relativeIPP, relativeBPP, paintingState.getTransform()); } /** @@ -1284,8 +1285,8 @@ bpp += currentBPPosition; } AffineTransform tf = positioning == Block.FIXED - ? currentState.getBaseTransform() - : currentState.getTransform(); + ? paintingState.getBaseTransform() + : paintingState.getTransform(); saveAbsolutePosition(id, currentPageRef, ipp, bpp, tf); } } @@ -1348,7 +1349,7 @@ int bpp = currentBPPosition + ip.getOffset(); ipRect = new Rectangle2D.Float(ipp / 1000f, bpp / 1000f, ip.getIPD() / 1000f, ip.getBPD() / 1000f); - AffineTransform transform = currentState.getTransform(); + AffineTransform transform = paintingState.getTransform(); ipRect = transform.createTransformedShape(ipRect).getBounds2D(); factory = pdfDoc.getFactory(); @@ -1582,9 +1583,9 @@ } boolean update = false; if (fill) { - update = currentState.setBackColor(col); + update = paintingState.setBackColor(col); } else { - update = currentState.setColor(col); + update = paintingState.setColor(col); } if (update) { @@ -1725,7 +1726,7 @@ x, y, width, height, foreignAttributes); context.setProperty(PDFRendererContextConstants.PDF_DOCUMENT, pdfDoc); context.setProperty(PDFRendererContextConstants.OUTPUT_STREAM, ostream); - context.setProperty(PDFRendererContextConstants.PDF_STATE, currentState); + context.setProperty(PDFRendererContextConstants.PDF_PAINTING_STATE, paintingState); context.setProperty(PDFRendererContextConstants.PDF_PAGE, currentPage); context.setProperty(PDFRendererContextConstants.PDF_CONTEXT, currentContext == null ? currentPage : currentContext); @@ -1745,7 +1746,7 @@ public void renderLeader(Leader area) { renderInlineAreaBackAndBorders(area); - currentState.push(); + paintingState.push(); saveGraphicsState(); int style = area.getRuleStyle(); float startx = (currentIPPosition + area.getBorderAndPaddingWidthStart()) / 1000f; @@ -1803,7 +1804,7 @@ } restoreGraphicsState(); - currentState.pop(); + paintingState.pop(); beginTextObject(); super.renderLeader(area); } Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFRendererContextConstants.java URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFRendererContextConstants.java?rev=711273&r1=711272&r2=711273&view=diff ============================================================================== --- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFRendererContextConstants.java (original) +++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFRendererContextConstants.java Tue Nov 4 07:30:38 2008 @@ -29,8 +29,8 @@ /** The PDF document that this image is being drawn into. */ String PDF_DOCUMENT = "pdfDoc"; - /** The current pdf state. */ - String PDF_STATE = "pdfState"; + /** The current PDF painting state. */ + String PDF_PAINTING_STATE = "pdfPaintingState"; /** The current PDF page for page renference and as a resource context. */ String PDF_PAGE = "pdfPage"; Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java?rev=711273&r1=711272&r2=711273&view=diff ============================================================================== --- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java (original) +++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/pdf/PDFSVGHandler.java Tue Nov 4 07:30:38 2008 @@ -25,8 +25,6 @@ import java.io.OutputStream; import java.util.Map; -import org.w3c.dom.Document; - import org.apache.avalon.framework.configuration.Configuration; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.GVTBuilder; @@ -35,16 +33,12 @@ import org.apache.batik.util.SVGConstants; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - -import org.apache.xmlgraphics.util.QName; - import org.apache.fop.apps.FOUserAgent; -import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.fonts.FontInfo; import org.apache.fop.pdf.PDFDocument; import org.apache.fop.pdf.PDFPage; +import org.apache.fop.pdf.PDFPaintingState; import org.apache.fop.pdf.PDFResourceContext; -import org.apache.fop.pdf.PDFState; import org.apache.fop.pdf.PDFStream; import org.apache.fop.render.AbstractGenericSVGHandler; import org.apache.fop.render.Renderer; @@ -55,6 +49,7 @@ import org.apache.fop.svg.PDFGraphics2D; import org.apache.fop.svg.SVGEventProducer; import org.apache.fop.svg.SVGUserAgent; +import org.w3c.dom.Document; /** * PDF XML handler for SVG (uses Apache Batik). @@ -78,7 +73,7 @@ PDFInfo pdfi = new PDFInfo(); pdfi.pdfDoc = (PDFDocument)context.getProperty(PDF_DOCUMENT); pdfi.outputStream = (OutputStream)context.getProperty(OUTPUT_STREAM); - pdfi.pdfState = (PDFState)context.getProperty(PDF_STATE); + pdfi.pdfPaintingState = (PDFPaintingState)context.getProperty(PDF_PAINTING_STATE); pdfi.pdfPage = (PDFPage)context.getProperty(PDF_PAGE); pdfi.pdfContext = (PDFResourceContext)context.getProperty(PDF_CONTEXT); pdfi.currentStream = (PDFStream)context.getProperty(PDF_STREAM); @@ -91,10 +86,9 @@ pdfi.currentYPosition = ((Integer)context.getProperty(YPOS)).intValue(); pdfi.cfg = (Configuration)context.getProperty(HANDLER_CONFIGURATION); Map foreign = (Map)context.getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES); - - QName qName = new QName(ExtensionElementMapping.URI, null, "conversion-mode"); + if (foreign != null - && "bitmap".equalsIgnoreCase((String)foreign.get(qName))) { + && BITMAP.equalsIgnoreCase((String)foreign.get(CONVERSION_MODE))) { pdfi.paintAsBitmap = true; } return pdfi; @@ -109,7 +103,7 @@ /** see OUTPUT_STREAM */ public OutputStream outputStream; /** see PDF_STATE */ - public PDFState pdfState; + public PDFPaintingState pdfPaintingState; /** see PDF_PAGE */ public PDFPage pdfPage; /** see PDF_CONTEXT */ @@ -199,8 +193,8 @@ float w = (float)ctx.getDocumentSize().getWidth() * 1000f; float h = (float)ctx.getDocumentSize().getHeight() * 1000f; - float sx = pdfInfo.width / (float)w; - float sy = pdfInfo.height / (float)h; + float sx = pdfInfo.width / w; + float sy = pdfInfo.height / h; //Scaling and translation for the bounding box of the image AffineTransform scaling = new AffineTransform( @@ -249,16 +243,16 @@ pdfInfo.currentStream.add("%SVG start\n"); //Save state and update coordinate system for the SVG image - pdfInfo.pdfState.push(); - pdfInfo.pdfState.concatenate(imageTransform); + pdfInfo.pdfPaintingState.push(); + pdfInfo.pdfPaintingState.concatenate(imageTransform); //Now that we have the complete transformation matrix for the image, we can update the //transformation matrix for the AElementBridge. PDFAElementBridge aBridge = (PDFAElementBridge)ctx.getBridge( SVGDOMImplementation.SVG_NAMESPACE_URI, SVGConstants.SVG_A_TAG); - aBridge.getCurrentTransform().setTransform(pdfInfo.pdfState.getTransform()); + aBridge.getCurrentTransform().setTransform(pdfInfo.pdfPaintingState.getTransform()); - graphics.setPDFState(pdfInfo.pdfState); + graphics.setPaintingState(pdfInfo.pdfPaintingState); graphics.setOutputStream(pdfInfo.outputStream); try { root.paint(graphics); @@ -268,7 +262,7 @@ context.getUserAgent().getEventBroadcaster()); eventProducer.svgRenderingError(this, e, getDocumentURI(doc)); } - pdfInfo.pdfState.pop(); + pdfInfo.pdfPaintingState.pop(); renderer.restoreGraphicsState(); pdfInfo.currentStream.add("%SVG end\n"); } Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java?rev=711273&r1=711272&r2=711273&view=diff ============================================================================== --- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java (original) +++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java Tue Nov 4 07:30:38 2008 @@ -19,30 +19,30 @@ package org.apache.fop.svg; -import org.apache.fop.Version; -import org.apache.fop.pdf.PDFDocument; -import org.apache.fop.pdf.PDFFilterList; -import org.apache.fop.pdf.PDFPage; -import org.apache.fop.pdf.PDFStream; -import org.apache.fop.pdf.PDFState; -import org.apache.fop.pdf.PDFNumber; -import org.apache.fop.pdf.PDFResources; -import org.apache.fop.pdf.PDFColor; -import org.apache.fop.pdf.PDFAnnotList; -import org.apache.fop.fonts.FontInfo; -import org.apache.fop.fonts.FontSetup; - -import java.awt.Graphics; -import java.awt.Font; import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; import java.awt.Shape; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; import java.io.StringWriter; +import org.apache.fop.Version; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.fonts.FontSetup; +import org.apache.fop.pdf.PDFAnnotList; +import org.apache.fop.pdf.PDFColor; +import org.apache.fop.pdf.PDFDocument; +import org.apache.fop.pdf.PDFFilterList; +import org.apache.fop.pdf.PDFNumber; +import org.apache.fop.pdf.PDFPage; +import org.apache.fop.pdf.PDFPaintingState; +import org.apache.fop.pdf.PDFResources; +import org.apache.fop.pdf.PDFStream; + /** * This class is a wrapper for the <tt>PDFGraphics2D</tt> that * is used to create a full document around the pdf rendering from @@ -52,7 +52,7 @@ */ public class PDFDocumentGraphics2D extends PDFGraphics2D { - private PDFContext pdfContext; + private final PDFContext pdfContext; private int width; private int height; @@ -296,7 +296,7 @@ throw new IllegalStateException("Close page first before starting another"); } //Start page - graphicsState = new PDFState(); + paintingState = new PDFPaintingState(); if (this.initialTransform == null) { //Save initial transformation matrix this.initialTransform = getTransform(); @@ -322,7 +322,7 @@ pageRef = page.referencePDF(); AffineTransform at = new AffineTransform(1.0, 0.0, 0.0, -1.0, - 0.0, (double)height); + 0.0, height); currentStream.write("1 0 0 -1 0 " + height + " cm\n"); if (svgWidth != 0) { double scaleX = width / svgWidth; @@ -340,7 +340,7 @@ scale(1 / s, 1 / s); } // Remember the transform we installed. - graphicsState.concatenate(at); + paintingState.concatenate(at); pdfContext.increasePageCount(); } Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/PDFGraphics2D.java URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/PDFGraphics2D.java?rev=711273&r1=711272&r2=711273&view=diff ============================================================================== --- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/PDFGraphics2D.java (original) +++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/svg/PDFGraphics2D.java Tue Nov 4 07:30:38 2008 @@ -59,15 +59,6 @@ import org.apache.batik.ext.awt.RenderingHintsKeyExt; import org.apache.batik.gvt.GraphicsNode; import org.apache.batik.gvt.PatternPaint; - -import org.apache.xmlgraphics.image.loader.ImageInfo; -import org.apache.xmlgraphics.image.loader.ImageSize; -import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; -import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; -import org.apache.xmlgraphics.image.loader.impl.ImageRendered; -import org.apache.xmlgraphics.java2d.AbstractGraphics2D; -import org.apache.xmlgraphics.java2d.GraphicContext; - import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontSetup; @@ -83,16 +74,23 @@ import org.apache.fop.pdf.PDFImageXObject; import org.apache.fop.pdf.PDFLink; import org.apache.fop.pdf.PDFNumber; +import org.apache.fop.pdf.PDFPaintingState; import org.apache.fop.pdf.PDFPattern; import org.apache.fop.pdf.PDFResourceContext; import org.apache.fop.pdf.PDFResources; -import org.apache.fop.pdf.PDFState; import org.apache.fop.pdf.PDFText; import org.apache.fop.pdf.PDFXObject; import org.apache.fop.render.pdf.ImageRawCCITTFaxAdapter; import org.apache.fop.render.pdf.ImageRawJPEGAdapter; import org.apache.fop.render.pdf.ImageRenderedAdapter; import org.apache.fop.util.ColorExt; +import org.apache.xmlgraphics.image.loader.ImageInfo; +import org.apache.xmlgraphics.image.loader.ImageSize; +import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax; +import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; +import org.apache.xmlgraphics.image.loader.impl.ImageRendered; +import org.apache.xmlgraphics.java2d.AbstractGraphics2D; +import org.apache.xmlgraphics.java2d.GraphicContext; /** * PDF Graphics 2D. @@ -129,9 +127,9 @@ protected String pageRef; /** - * the current state of the pdf graphics + * The PDF painting state */ - protected PDFState graphicsState; + protected PDFPaintingState paintingState; /** * The PDF graphics state level that this svg is being drawn into. @@ -200,7 +198,7 @@ currentFontSize = size; fontInfo = fi; pageRef = pref; - graphicsState = new PDFState(); + paintingState = new PDFPaintingState(); } /** @@ -226,7 +224,7 @@ this.currentFontSize = g.currentFontSize; this.fontInfo = g.fontInfo; this.pageRef = g.pageRef; - this.graphicsState = g.graphicsState; + this.paintingState = g.paintingState; this.currentStream = g.currentStream; this.nativeCount = g.nativeCount; this.outputStream = g.outputStream; @@ -266,9 +264,9 @@ * * @param state the PDF state */ - public void setPDFState(PDFState state) { - graphicsState = state; - baseLevel = graphicsState.getStackLevel(); + public void setPaintingState(PDFPaintingState state) { + paintingState = state; + baseLevel = paintingState.getStackLevel(); } /** @@ -369,7 +367,7 @@ * @return the transformation matrix that established the basic user space for this document */ protected AffineTransform getBaseTransform() { - AffineTransform at = new AffineTransform(graphicsState.getTransform()); + AffineTransform at = new AffineTransform(paintingState.getTransform()); return at; } @@ -518,10 +516,13 @@ g.setBackground(new Color(1, 1, 1, 0)); g.setPaint(new Color(1, 1, 1, 0)); g.fillRect(0, 0, width, height); - g.clip(new Rectangle(0, 0, buf.getWidth(), buf.getHeight())); + + int imageWidth = buf.getWidth(); + int imageHeight = buf.getHeight(); + g.clip(new Rectangle(0, 0, imageWidth, imageHeight)); g.setComposite(gc.getComposite()); - if (!g.drawImage(img, 0, 0, buf.getWidth(), buf.getHeight(), observer)) { + if (!g.drawImage(img, 0, 0, imageWidth, imageHeight, observer)) { return false; } g.dispose(); @@ -602,13 +603,13 @@ trans.getMatrix(tranvals); Shape imclip = getClip(); - boolean newClip = graphicsState.checkClip(imclip); - boolean newTransform = graphicsState.checkTransform(trans) + boolean newClip = paintingState.checkClip(imclip); + boolean newTransform = paintingState.checkTransform(trans) && !trans.isIdentity(); if (newClip || newTransform) { currentStream.write("q\n"); - graphicsState.push(); + paintingState.push(); if (newTransform) { concatMatrix(tranvals); } @@ -625,7 +626,7 @@ applyColor(c, true); Paint paint = getPaint(); - if (graphicsState.setPaint(paint)) { + if (paintingState.setPaint(paint)) { if (!applyPaint(paint, false)) { // Stroke the shape and use it to 'clip' // the paint contents. @@ -634,7 +635,7 @@ if (newClip || newTransform) { currentStream.write("Q\n"); - graphicsState.pop(); + paintingState.pop(); } return; } @@ -646,7 +647,7 @@ doDrawing(false, true, false); if (newClip || newTransform) { currentStream.write("Q\n"); - graphicsState.pop(); + paintingState.pop(); } } @@ -1380,7 +1381,7 @@ if (!useMultiByte) { if (ch > 127) { currentStream.write("\\"); - currentStream.write(Integer.toOctalString((int)ch)); + currentStream.write(Integer.toOctalString(ch)); } else { switch (ch) { case '(': @@ -1397,8 +1398,8 @@ } if (kerningAvailable && (i + 1) < l) { - addKerning(currentStream, (new Integer((int)ch)), - (new Integer((int)fontState.mapChar(s.charAt(i + 1)))), + addKerning(currentStream, (new Integer(ch)), + (new Integer(fontState.mapChar(s.charAt(i + 1)))), kerning, startText, endText); } @@ -1426,7 +1427,7 @@ vals.put(PDFGState.GSTATE_ALPHA_STROKE, new Float(strokeAlpha / 255f)); } PDFGState gstate = pdfDoc.getFactory().makeGState( - vals, graphicsState.getGState()); + vals, paintingState.getGState()); resourceContext.addGState(gstate); currentStream.write("/" + gstate.getName() + " gs\n"); } @@ -1438,7 +1439,7 @@ */ protected void updateCurrentFont(Font font) { String name = font.getFontName(); - float size = (float)font.getFontSize() / 1000f; + float size = font.getFontSize() / 1000f; //Only update if necessary if ((!name.equals(this.currentFontName)) @@ -1617,13 +1618,13 @@ trans.getMatrix(tranvals); Shape imclip = getClip(); - boolean newClip = graphicsState.checkClip(imclip); - boolean newTransform = graphicsState.checkTransform(trans) + boolean newClip = paintingState.checkClip(imclip); + boolean newTransform = paintingState.checkTransform(trans) && !trans.isIdentity(); if (newClip || newTransform) { currentStream.write("q\n"); - graphicsState.push(); + paintingState.push(); if (newTransform) { concatMatrix(tranvals); } @@ -1640,14 +1641,14 @@ applyColor(c, false); Paint paint = getPaint(); - if (graphicsState.setPaint(paint)) { + if (paintingState.setPaint(paint)) { if (!applyPaint(paint, true)) { // Use the shape to 'clip' the paint contents. applyUnknownPaint(paint, s); if (newClip || newTransform) { currentStream.write("Q\n"); - graphicsState.pop(); + paintingState.pop(); } return; } @@ -1660,7 +1661,7 @@ iter.getWindingRule() == PathIterator.WIND_EVEN_ODD); if (newClip || newTransform) { currentStream.write("Q\n"); - graphicsState.pop(); + paintingState.pop(); } } Copied: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/util/AbstractPaintingState.java (from r709373, xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/AbstractState.java) URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/util/AbstractPaintingState.java?p2=xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/util/AbstractPaintingState.java&p1=xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/AbstractState.java&r1=709373&r2=711273&rev=711273&view=diff ============================================================================== --- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/AbstractState.java (original) +++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/util/AbstractPaintingState.java Tue Nov 4 07:30:38 2008 @@ -17,12 +17,13 @@ /* $Id$ */ -package org.apache.fop; +package org.apache.fop.util; 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; @@ -31,7 +32,7 @@ /** * A base class which holds information about the current rendering state. */ -public abstract class AbstractState implements Cloneable, Serializable { +public abstract class AbstractPaintingState implements Cloneable, Serializable { private static final long serialVersionUID = 5998356138437094188L; @@ -39,7 +40,7 @@ private AbstractData data = null; /** the state stack */ - private StateStack stateStack = new StateStack(); + private StateStack/*<AbstractData>*/ stateStack = new StateStack/*<AbstractData>*/(); /** * Instantiates a new state data object @@ -53,7 +54,7 @@ * * @return a new state object */ - protected abstract AbstractState instantiateState(); + protected abstract AbstractPaintingState instantiate(); /** * Returns the currently valid state @@ -277,7 +278,7 @@ /** - * Push the current state onto the stack. + * Push the current painting state onto the stack. * This call should be used when the Q operator is used * so that the state is known when popped. */ @@ -287,7 +288,7 @@ } /** - * Pop the state from the stack and set current values to popped state. + * Pop the painting 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. * @@ -303,7 +304,7 @@ } /** - * Pushes all state data in the given list to the stack + * Pushes all painting state data in the given list to the stack * * @param dataList a state data list */ @@ -317,7 +318,7 @@ } /** - * Pops all state data from the stack + * Pops all painting state data from the stack * * @return a list of state data popped from the stack */ @@ -363,7 +364,7 @@ /** [EMAIL PROTECTED] */ public Object clone() { - AbstractState state = instantiateState(); + AbstractPaintingState state = instantiate(); state.stateStack = new StateStack(this.stateStack); state.data = (AbstractData)this.data.clone(); return state; @@ -374,4 +375,156 @@ return ", stateStack=" + stateStack + ", currentData=" + data; } + + + /** + * A stack implementation which holds state objects + */ + public 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); + } + } + + + /** + * A base painting 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; + } + + /** [EMAIL PROTECTED] */ + 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; + } + + /** [EMAIL PROTECTED] */ + public String toString() { + return "color=" + color + + ", backColor=" + backColor + + ", fontName=" + fontName + + ", fontSize=" + fontSize + + ", lineWidth=" + lineWidth + + ", dashArray=" + dashArray + + ", transform=" + transform; + } + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
