Bugfix: NPE after PDFDocumentGraphics2D.create() due to missing font setup and other missing initializations. Bugfix: Properly handle state in PDFGraphics2D.drawString(). Added an example class demonstrating the use of PDFDocumentGraphics2D. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1183620 13f79535-47bb-0310-9956-ffa450edef68tags/fop-1_1rc1old
@@ -0,0 +1,180 @@ | |||
/* | |||
* 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 embedding; | |||
import java.awt.Color; | |||
import java.awt.Dimension; | |||
import java.awt.Font; | |||
import java.awt.Graphics2D; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.io.StringReader; | |||
import javax.swing.JEditorPane; | |||
import org.apache.avalon.framework.configuration.Configuration; | |||
import org.apache.avalon.framework.configuration.ConfigurationException; | |||
import org.apache.avalon.framework.configuration.DefaultConfiguration; | |||
import org.apache.commons.io.IOUtils; | |||
import org.apache.xmlgraphics.util.UnitConv; | |||
import org.apache.fop.svg.PDFDocumentGraphics2D; | |||
import org.apache.fop.svg.PDFDocumentGraphics2DConfigurator; | |||
/** | |||
* This example class demonstrates the use of {@link PDFDocumentGraphics2D} that can be | |||
* used to create a PDF file from Java2D graphics (using the {@link Graphics2D} API). | |||
*/ | |||
public class ExampleJava2D2PDF { | |||
private Configuration createAutoFontsConfiguration() { | |||
//Create a default configuration using auto-detection of fonts. | |||
//This can be a bit slow but covers most use cases. | |||
DefaultConfiguration c = new DefaultConfiguration("cfg"); | |||
DefaultConfiguration fonts = new DefaultConfiguration("fonts"); | |||
c.addChild(fonts); | |||
DefaultConfiguration autodetect = new DefaultConfiguration("auto-detect"); | |||
fonts.addChild(autodetect); | |||
return c; | |||
/* You can also load the configuration from a file: | |||
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder(); | |||
return cfgBuilder.buildFromFile(configFile); | |||
*/ | |||
} | |||
private void configure(PDFDocumentGraphics2D g2d, Configuration cfg) | |||
throws ConfigurationException { | |||
PDFDocumentGraphics2DConfigurator configurator = new PDFDocumentGraphics2DConfigurator(); | |||
configurator.configure(g2d, cfg); | |||
} | |||
/** | |||
* Creates a PDF file. The contents are painted using a Graphics2D implementation that | |||
* generates an PDF file. | |||
* @param outputFile the target file | |||
* @throws IOException In case of an I/O error | |||
* @throws ConfigurationException if an error occurs configuring the PDF output | |||
*/ | |||
public void generatePDF(File outputFile) throws IOException, ConfigurationException { | |||
OutputStream out = new java.io.FileOutputStream(outputFile); | |||
out = new java.io.BufferedOutputStream(out); | |||
try { | |||
//Instantiate the PDFDocumentGraphics2D instance | |||
PDFDocumentGraphics2D g2d = new PDFDocumentGraphics2D(false); | |||
g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); | |||
//Configure the G2D with the necessary fonts | |||
configure(g2d, createAutoFontsConfiguration()); | |||
//Set up the document size | |||
Dimension pageSize = new Dimension( | |||
(int)Math.ceil(UnitConv.mm2pt(210)), | |||
(int)Math.ceil(UnitConv.mm2pt(297))); //page size A4 (in pt) | |||
g2d.setupDocument(out, pageSize.width, pageSize.height); | |||
g2d.translate(144, 72); //Establish some page borders | |||
//A few rectangles rotated and with different color | |||
Graphics2D copy = (Graphics2D)g2d.create(); | |||
int c = 12; | |||
for (int i = 0; i < c; i++) { | |||
float f = ((i + 1) / (float)c); | |||
Color col = new Color(0.0f, 1 - f, 0.0f); | |||
copy.setColor(col); | |||
copy.fillRect(70, 90, 50, 50); | |||
copy.rotate(-2 * Math.PI / c, 70, 90); | |||
} | |||
copy.dispose(); | |||
//Some text | |||
g2d.rotate(-0.25); | |||
g2d.setColor(Color.RED); | |||
g2d.setFont(new Font("sans-serif", Font.PLAIN, 36)); | |||
g2d.drawString("Hello world!", 140, 140); | |||
g2d.setColor(Color.RED.darker()); | |||
g2d.setFont(new Font("serif", Font.PLAIN, 36)); | |||
g2d.drawString("Hello world!", 140, 180); | |||
g2d.nextPage(); | |||
//Demonstrate painting rich text | |||
String someHTML = "<html><body style=\"font-family:Verdana\">" | |||
+ "<p>Welcome to <b>page 2!</b></p>" | |||
+ "<h2>PDFDocumentGraphics2D Demonstration</h2>" | |||
+ "<p>We can <i>easily</i> paint some HTML here!</p>" | |||
+ "<p style=\"color:green;\">" | |||
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin accumsan" | |||
+ " condimentum ullamcorper. Sed varius quam id arcu fermentum luctus. Praesent" | |||
+ " nisi ligula, cursus sed vestibulum vel, sodales sed lectus.</p>" | |||
+ "</body></html>"; | |||
JEditorPane htmlComp = new JEditorPane(); | |||
htmlComp.setContentType("text/html"); | |||
htmlComp.read(new StringReader(someHTML), null); | |||
htmlComp.setSize(new Dimension(pageSize.width - 72, pageSize.height - 72)); | |||
//htmlComp.setBackground(Color.ORANGE); | |||
htmlComp.validate(); | |||
htmlComp.printAll(g2d); | |||
//Cleanup | |||
g2d.finish(); | |||
} finally { | |||
IOUtils.closeQuietly(out); | |||
} | |||
} | |||
/** | |||
* Main method. | |||
* @param args command-line arguments | |||
*/ | |||
public static void main(String[] args) { | |||
try { | |||
System.out.println("FOP " + ExampleJava2D2PDF.class.getSimpleName() + "\n"); | |||
System.out.println("Preparing..."); | |||
//Setup directories | |||
File baseDir = new File("."); | |||
File outDir = new File(baseDir, "out"); | |||
if (!outDir.isDirectory()) { | |||
if (!outDir.mkdirs()) { | |||
throw new IOException("Could not create output directory: " + outDir); | |||
} | |||
} | |||
//Setup output file | |||
File pdffile = new File(outDir, "ResultJava2D2PDF.pdf"); | |||
System.out.println("Output: PDF (" + pdffile + ")"); | |||
System.out.println(); | |||
System.out.println("Generating..."); | |||
ExampleJava2D2PDF app = new ExampleJava2D2PDF(); | |||
app.generatePDF(pdffile); | |||
System.out.println("Success!"); | |||
} catch (Throwable t) { | |||
t.printStackTrace(System.err); | |||
System.exit(-1); | |||
} | |||
} | |||
} |
@@ -276,6 +276,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { | |||
} | |||
/** {@inheritDoc} */ | |||
@Override | |||
protected void preparePainting() { | |||
if (pdfContext.isPagePending()) { | |||
return; | |||
@@ -391,7 +392,9 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { | |||
* @return a new graphics context that is a copy of | |||
* this graphics context. | |||
*/ | |||
@Override | |||
public Graphics create() { | |||
preparePainting(); | |||
return new PDFDocumentGraphics2D(this); | |||
} | |||
@@ -403,6 +406,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D { | |||
* @param x the x position | |||
* @param y the y position | |||
*/ | |||
@Override | |||
public void drawString(String s, float x, float y) { | |||
if (super.textAsShapes) { | |||
Font font = super.getFont(); |
@@ -751,10 +751,14 @@ public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHand | |||
} | |||
boolean doWrite = false; | |||
if (fill && paintingState.setBackColor(col)) { | |||
doWrite = true; | |||
} else if (paintingState.setColor(col)) { | |||
doWrite = true; | |||
if (fill) { | |||
if (paintingState.setBackColor(col)) { | |||
doWrite = true; | |||
} | |||
} else { | |||
if (paintingState.setColor(col)) { | |||
doWrite = true; | |||
} | |||
} | |||
if (doWrite) { | |||
StringBuffer sb = new StringBuffer(); | |||
@@ -1327,7 +1331,7 @@ public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHand | |||
} | |||
updateCurrentFont(fontState); | |||
currentStream.write("q\n"); | |||
saveGraphicsState(); | |||
Color c = getColor(); | |||
applyColor(c, true); | |||
@@ -1402,7 +1406,7 @@ public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHand | |||
currentStream.write("] TJ\n"); | |||
currentStream.write("ET\n"); | |||
currentStream.write("Q\n"); | |||
restoreGraphicsState(); | |||
} | |||
/** |
@@ -60,6 +60,9 @@ | |||
documents. Example: the fix of marks layering will be such a case when it's done. | |||
--> | |||
<release version="FOP Trunk" date="TBD"> | |||
<action context="Renderers" dev="JM" type="add"> | |||
Various bugfixes to make PDFDocumentGraphics2D operational again. | |||
</action> | |||
<action context="Code" dev="PH" type="add" fixes-bug="51962" due-to="Mehdi Houshmand"> | |||
Bugfix for when the last simple-page-master referenced in a page-sequence-master is not | |||
chosen when force-page-count=odd. |
@@ -25,6 +25,7 @@ import org.junit.runners.Suite.SuiteClasses; | |||
import org.apache.fop.events.BasicEventTestCase; | |||
import org.apache.fop.pdf.FileIDGeneratorTestCase; | |||
import org.apache.fop.pdf.PDFDocumentGraphics2DTestCase; | |||
import org.apache.fop.pdf.PDFEncryptionJCETestCase; | |||
import org.apache.fop.pdf.PDFFactoryTestCase; | |||
import org.apache.fop.pdf.PDFObjectTestCase; | |||
@@ -51,7 +52,8 @@ import org.apache.fop.util.XMLResourceBundleTestCase; | |||
FileIDGeneratorTestCase.class, | |||
PDFFactoryTestCase.class, | |||
PDFEncryptionJCETestCase.class, | |||
BitmapImageUtilTestCase.class | |||
BitmapImageUtilTestCase.class, | |||
PDFDocumentGraphics2DTestCase.class | |||
}) | |||
public class UtilityCodeTestSuite { | |||
} |
@@ -0,0 +1,93 @@ | |||
/* | |||
* 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.pdf; | |||
import java.awt.Color; | |||
import java.awt.Dimension; | |||
import java.awt.Font; | |||
import java.awt.Graphics2D; | |||
import junit.framework.Assert; | |||
import org.junit.Test; | |||
import org.apache.commons.io.output.ByteArrayOutputStream; | |||
import org.apache.xmlgraphics.util.UnitConv; | |||
import org.apache.fop.svg.PDFDocumentGraphics2D; | |||
/** | |||
* Tests for {@link PDFDocumentGraphics2D}. | |||
*/ | |||
public class PDFDocumentGraphics2DTestCase { | |||
/** | |||
* Does a smoke test on PDFDocumentGraphics2D making sure that nobody accidentally broke | |||
* anything serious. It does not check the correctness of the produced PDF. | |||
* @throws Exception if an error occurs | |||
*/ | |||
@Test | |||
public void smokeTest() throws Exception { | |||
ByteArrayOutputStream baout = new ByteArrayOutputStream(); | |||
PDFDocumentGraphics2D g2d = new PDFDocumentGraphics2D(false); | |||
g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext()); | |||
//Set up the document size | |||
Dimension pageSize = new Dimension( | |||
(int)Math.ceil(UnitConv.mm2pt(210)), | |||
(int)Math.ceil(UnitConv.mm2pt(297))); //page size A4 (in pt) | |||
g2d.setupDocument(baout, pageSize.width, pageSize.height); | |||
//A few rectangles rotated and with different color | |||
Graphics2D copy = (Graphics2D)g2d.create(); | |||
int c = 12; | |||
for (int i = 0; i < c; i++) { | |||
float f = ((i + 1) / (float)c); | |||
Color col = new Color(0.0f, 1 - f, 0.0f); | |||
copy.setColor(col); | |||
copy.fillRect(70, 90, 50, 50); | |||
copy.rotate(-2 * Math.PI / c, 70, 90); | |||
} | |||
copy.dispose(); | |||
//Some text | |||
g2d.rotate(-0.25); | |||
g2d.setColor(Color.RED); | |||
g2d.setFont(new Font("sans-serif", Font.PLAIN, 36)); | |||
g2d.drawString("Hello world!", 140, 140); | |||
g2d.setColor(Color.RED.darker()); | |||
g2d.setFont(new Font("serif", Font.PLAIN, 36)); | |||
g2d.drawString("Hello world!", 140, 180); | |||
g2d.nextPage(); //Move to next page | |||
g2d.setFont(new Font("sans-serif", Font.PLAIN, 36)); | |||
g2d.drawString("Welcome to page 2!", 140, 140); | |||
//Cleanup | |||
g2d.finish(); | |||
String pdfString = baout.toString("ISO-8859-1"); | |||
Assert.assertEquals("%%EOF not found", | |||
pdfString.substring(pdfString.length() - 6), "%%EOF\n"); | |||
} | |||
} |