Browse Source

* PDFImageHandler interface split into ImageHandler and PDFImageHandler.

* Deleted AFPDataObjectInfoProvider and AFPImage*Factory implementations, and abstracted AbstractImageHandlerRegistry from PDFImageHandlerRegistry, creating AFPImageHandlerRegistry and AFPImageHandler so there is a common reuse of image handling implementation between AFP and PDF now.
* RendererContext instantiation is now overridable in PrintRenderer.
* Created AFPRendererContext that is able to provide AFPInfo.
* toString() added to RendererContext for ease of use.
* Removed GraphicsObjectPainterAFP.
* Added package.html for AFP (sub)packages.
* Abstracted AbstractFOPBridgeContext from PDFBridgeContext and provided AFPBridgeContext implementation.
* Abstracted AbstractFOPTextElementBridge from PDFTextElementBridge and provided AFPTextElementBridge implementation.
* Abstracted AbstractFOPImageElementBridge from PDFImageElementBridge and provided AFPImageElementBridge implementation.
* Provided inline image support/handling in AFPGraphics2D for SVG.
* Created NativeImageHandler interface.
* Fix for path iterator filled line drawing in AFPGraphics2D adding coordinate drawing implementations GraphicsLineRelative and GraphicsFilletRelative (Thanks for the patch Jeremias).
* Improved configuration.xml documentation for images mode/native setting in AFP renderer configuration.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@713747 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-1_0
Adrian Cumiskey 15 years ago
parent
commit
f637010908
73 changed files with 2335 additions and 1562 deletions
  1. 2
    1
      src/documentation/content/xdocs/trunk/configuration.xml
  2. 5
    0
      src/java/META-INF/services/org.apache.fop.render.afp.AFPImageHandler
  3. 114
    79
      src/java/org/apache/fop/afp/AFPGraphics2D.java
  4. 5
    1
      src/java/org/apache/fop/afp/AFPGraphicsObjectInfo.java
  5. 7
    6
      src/java/org/apache/fop/afp/AFPPaintingState.java
  6. 0
    5
      src/java/org/apache/fop/afp/AFPResourceManager.java
  7. 5
    2
      src/java/org/apache/fop/afp/AFPStreamer.java
  8. 1
    1
      src/java/org/apache/fop/afp/Graphics2DImagePainterGOCA.java
  9. 14
    13
      src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java
  10. 1
    5
      src/java/org/apache/fop/afp/fonts/AFPPageFonts.java
  11. 23
    0
      src/java/org/apache/fop/afp/fonts/package.html
  12. 0
    1
      src/java/org/apache/fop/afp/goca/AbstractGraphicsCoord.java
  13. 42
    0
      src/java/org/apache/fop/afp/goca/GraphicsFilletRelative.java
  14. 1
    2
      src/java/org/apache/fop/afp/goca/GraphicsLine.java
  15. 42
    0
      src/java/org/apache/fop/afp/goca/GraphicsLineRelative.java
  16. 23
    0
      src/java/org/apache/fop/afp/goca/package.html
  17. 23
    0
      src/java/org/apache/fop/afp/ioca/package.html
  18. 33
    2
      src/java/org/apache/fop/afp/modca/GraphicsObject.java
  19. 23
    0
      src/java/org/apache/fop/afp/modca/package.html
  20. 23
    0
      src/java/org/apache/fop/afp/modca/triplets/package.html
  21. 23
    0
      src/java/org/apache/fop/afp/package.html
  22. 105
    0
      src/java/org/apache/fop/afp/svg/AFPBridgeContext.java
  23. 37
    0
      src/java/org/apache/fop/afp/svg/AFPImageElementBridge.java
  24. 42
    0
      src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java
  25. 6
    13
      src/java/org/apache/fop/afp/svg/AFPTextHandler.java
  26. 20
    5
      src/java/org/apache/fop/afp/svg/AFPTextPainter.java
  27. 2
    2
      src/java/org/apache/fop/fonts/FontInfo.java
  28. 17
    0
      src/java/org/apache/fop/fonts/package.html
  29. 17
    0
      src/java/org/apache/fop/pdf/package.html
  30. 28
    14
      src/java/org/apache/fop/render/AbstractGenericSVGHandler.java
  31. 13
    2
      src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java
  32. 211
    0
      src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java
  33. 46
    0
      src/java/org/apache/fop/render/ImageHandler.java
  34. 10
    4
      src/java/org/apache/fop/render/PrintRenderer.java
  35. 29
    7
      src/java/org/apache/fop/render/RendererContext.java
  36. 0
    93
      src/java/org/apache/fop/render/afp/AFPAbstractImageFactory.java
  37. 0
    87
      src/java/org/apache/fop/render/afp/AFPDataObjectInfoProvider.java
  38. 3
    1
      src/java/org/apache/fop/render/afp/AFPForeignAttributeReader.java
  39. 37
    66
      src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java
  40. 0
    135
      src/java/org/apache/fop/render/afp/AFPImageGraphics2DFactory.java
  41. 19
    26
      src/java/org/apache/fop/render/afp/AFPImageHandler.java
  42. 128
    0
      src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java
  43. 39
    20
      src/java/org/apache/fop/render/afp/AFPImageHandlerRawCCITTFax.java
  44. 42
    14
      src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java
  45. 42
    0
      src/java/org/apache/fop/render/afp/AFPImageHandlerRegistry.java
  46. 40
    16
      src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java
  47. 82
    0
      src/java/org/apache/fop/render/afp/AFPImageHandlerXML.java
  48. 22
    8
      src/java/org/apache/fop/render/afp/AFPInfo.java
  49. 63
    65
      src/java/org/apache/fop/render/afp/AFPRenderer.java
  50. 18
    16
      src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
  51. 83
    0
      src/java/org/apache/fop/render/afp/AFPRendererContext.java
  52. 3
    22
      src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java
  53. 93
    137
      src/java/org/apache/fop/render/afp/AFPSVGHandler.java
  54. 0
    89
      src/java/org/apache/fop/render/afp/GraphicsObjectPainterAFP.java
  55. 23
    0
      src/java/org/apache/fop/render/afp/package.html
  56. 3
    24
      src/java/org/apache/fop/render/pdf/PDFImageHandler.java
  57. 8
    5
      src/java/org/apache/fop/render/pdf/PDFImageHandlerGraphics2D.java
  58. 9
    6
      src/java/org/apache/fop/render/pdf/PDFImageHandlerRawCCITTFax.java
  59. 9
    6
      src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java
  60. 5
    158
      src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java
  61. 10
    6
      src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java
  62. 9
    7
      src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java
  63. 2
    1
      src/java/org/apache/fop/render/pdf/PDFRenderer.java
  64. 19
    25
      src/java/org/apache/fop/render/ps/PSTextPainter.java
  65. 139
    0
      src/java/org/apache/fop/svg/AbstractFOPBridgeContext.java
  66. 284
    0
      src/java/org/apache/fop/svg/AbstractFOPImageElementBridge.java
  67. 21
    18
      src/java/org/apache/fop/svg/AbstractFOPTextElementBridge.java
  68. 40
    0
      src/java/org/apache/fop/svg/NativeImageHandler.java
  69. 30
    74
      src/java/org/apache/fop/svg/PDFBridgeContext.java
  70. 4
    3
      src/java/org/apache/fop/svg/PDFGraphics2D.java
  71. 5
    228
      src/java/org/apache/fop/svg/PDFImageElementBridge.java
  72. 5
    37
      src/java/org/apache/fop/svg/PDFTextElementBridge.java
  73. 3
    4
      src/java/org/apache/fop/svg/PDFTextPainter.java

+ 2
- 1
src/documentation/content/xdocs/trunk/configuration.xml View File

@@ -383,7 +383,8 @@
<resource-group-file>resources.afp</resource-group-file>
</renderer>]]></source>
<p>
The default value for the "images mode" setting is "b+w" (black and white). When the setting is "color" a "bits-per-pixel" setting can be provided. When the setting "native" is set to true, images (TIFF, JPEG and Encapsulated Postscript) will be placed in the datastream in their native form using a MO:DCA Object Container.
The default value for the images "mode" setting is "b+w" (black and white). When the images "mode" setting is "b+w" a "bits-per-pixel" setting can be provided to aid the grayscale conversion process. With this setting all images referenced in your source document are converted to an IOCA FS45 grayscale bitmap image form.
When the setting is "color" all images are converted to an IOCA FS45 color bitmap image form. When "native" setting is "true", all images encountered (TIFF, GIF, JPEG and Encapsulated Postscript etc.) will be embedded directly in the datastream in their native form using a MO:DCA Object Container.
</p>
<p>
The default value for the "renderer-resolution" is 240 dpi.

+ 5
- 0
src/java/META-INF/services/org.apache.fop.render.afp.AFPImageHandler View File

@@ -0,0 +1,5 @@
org.apache.fop.render.afp.AFPImageHandlerRenderedImage
org.apache.fop.render.afp.AFPImageHandlerRawCCITTFax
org.apache.fop.render.afp.AFPImageHandlerRawStream
org.apache.fop.render.afp.AFPImageHandlerGraphics2D
org.apache.fop.render.afp.AFPImageHandlerXML

+ 114
- 79
src/java/org/apache/fop/afp/AFPGraphics2D.java View File

@@ -48,6 +48,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.fop.afp.goca.GraphicsSetLineType;
import org.apache.fop.afp.modca.GraphicsObject;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.svg.NativeImageHandler;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
@@ -65,7 +66,7 @@ import org.apache.xmlgraphics.util.MimeConstants;
*
* @see org.apache.xmlgraphics.java2d.AbstractGraphics2D
*/
public class AFPGraphics2D extends AbstractGraphics2D {
public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHandler {

private static final Log log = LogFactory.getLog(AFPGraphics2D.class);

@@ -109,10 +110,19 @@ public class AFPGraphics2D extends AbstractGraphics2D {
* @param textAsShapes
* if true, all text is turned into shapes in the convertion. No
* text is output.
*
* @param paintingState painting state
* @param resourceManager resource manager
* @param resourceInfo resource info
* @param fontInfo font info
*/
public AFPGraphics2D(boolean textAsShapes) {
public AFPGraphics2D(boolean textAsShapes, AFPPaintingState paintingState,
AFPResourceManager resourceManager, AFPResourceInfo resourceInfo,
FontInfo fontInfo) {
super(textAsShapes);
this.paintingState = paintingState;
this.resourceManager = resourceManager;
this.resourceInfo = resourceInfo;
this.fontInfo = fontInfo;
}

/**
@@ -123,12 +133,14 @@ public class AFPGraphics2D extends AbstractGraphics2D {
*/
public AFPGraphics2D(AFPGraphics2D g2d) {
super(g2d);
this.paintingState = g2d.paintingState;
this.resourceManager = g2d.resourceManager;
this.resourceInfo = g2d.resourceInfo;
this.fontInfo = g2d.fontInfo;

this.graphicsObj = g2d.graphicsObj;
this.fallbackTextHandler = g2d.fallbackTextHandler;
this.customTextHandler = g2d.customTextHandler;
this.resourceManager = g2d.resourceManager;
this.resourceInfo = g2d.resourceInfo;
this.paintingState = g2d.paintingState;
}

/**
@@ -282,16 +294,13 @@ public class AFPGraphics2D extends AbstractGraphics2D {
mhr
);
} else {
// graphics segment opening coordinates (x,y)
// current position coordinates (x,y)
for (int[] openingCoords = new int[2], currCoords = new int[2];
!iter.isDone(); iter.next()) {
// round the coordinate values and combine with current position
// coordinates
int type = iter.currentSegment(dstPts);
if (type == PathIterator.SEG_MOVETO) {
openingCoords[X] = currCoords[X] = (int)Math.round(dstPts[X]);
openingCoords[Y] = currCoords[Y] = (int)Math.round(dstPts[Y]);
graphicsObj.setCurrentPosition(openingCoords);
} else {
int numCoords;
if (type == PathIterator.SEG_LINETO) {
@@ -303,32 +312,22 @@ public class AFPGraphics2D extends AbstractGraphics2D {
} else {
// close of the graphics segment
if (type == PathIterator.SEG_CLOSE) {
coords = new int[] {
coords[coords.length - 2], //prev X
coords[coords.length - 1], //prev Y
openingCoords[X],
openingCoords[Y]
};
graphicsObj.addLine(coords);
graphicsObj.addLine(openingCoords, true);
} else {
log.debug("Unrecognised path iterator type: "
+ type);
}
continue;
}
// combine current position coordinates with new graphics
// segment coordinates
coords = new int[numCoords + 2];
coords[X] = currCoords[X];
coords[Y] = currCoords[Y];
coords = new int[numCoords];
for (int i = 0; i < numCoords; i++) {
coords[i + 2] = (int) Math.round(dstPts[i]);
coords[i] = (int) Math.round(dstPts[i]);
}
if (type == PathIterator.SEG_LINETO) {
graphicsObj.addLine(coords);
graphicsObj.addLine(coords, true);
} else if (type == PathIterator.SEG_QUADTO
|| type == PathIterator.SEG_CUBICTO) {
graphicsObj.addFillet(coords);
graphicsObj.addFillet(coords, true);
}
// update current position coordinates
currCoords[X] = coords[coords.length - 2];
@@ -408,7 +407,7 @@ public class AFPGraphics2D extends AbstractGraphics2D {
BufferedImage.TYPE_INT_ARGB);
}

private AFPImageObjectInfo getImageObjectInfo(
private AFPImageObjectInfo createImageObjectInfo(
RenderedImage img, int x, int y, int width, int height) throws IOException {
ImageInfo imageInfo = new ImageInfo(null, "image/unknown");
ImageSize size = new ImageSize(img.getWidth(), img.getHeight(), 72);
@@ -422,7 +421,8 @@ public class AFPGraphics2D extends AbstractGraphics2D {

imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45);

imageObjectInfo.setBitsPerPixel(paintingState.getBitsPerPixel());
int bitsPerPixel = paintingState.getBitsPerPixel();
imageObjectInfo.setBitsPerPixel(bitsPerPixel);

imageObjectInfo.setResourceInfo(resourceInfo);

@@ -442,7 +442,6 @@ public class AFPGraphics2D extends AbstractGraphics2D {
// convert to grayscale
if (!colorImages) {
boas.reset();
int bitsPerPixel = paintingState.getBitsPerPixel();
imageObjectInfo.setBitsPerPixel(bitsPerPixel);
ImageEncodingHelper.encodeRGBAsGrayScale(
imageData, dataWidth, dataHeight, bitsPerPixel, boas);
@@ -456,21 +455,10 @@ public class AFPGraphics2D extends AbstractGraphics2D {

// create object area info
AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo();

AffineTransform at = gc.getTransform();
float[] srcPts = new float[] {x, y};
float[] dstPts = new float[srcPts.length];
at.transform(srcPts, 0, dstPts, 0, 1);
objectAreaInfo.setX(Math.round(dstPts[X]));
objectAreaInfo.setY(Math.round(dstPts[Y]));

AFPUnitConverter unitConv = paintingState.getUnitConverter();

int w = Math.round(unitConv.pt2units(width));
objectAreaInfo.setWidth(w);

int h = Math.round(unitConv.pt2units(height));
objectAreaInfo.setHeight(h);
objectAreaInfo.setX(x);
objectAreaInfo.setY(y);
objectAreaInfo.setWidth(width);
objectAreaInfo.setHeight(height);

int resolution = paintingState.getResolution();
objectAreaInfo.setWidthRes(resolution);
@@ -481,37 +469,62 @@ public class AFPGraphics2D extends AbstractGraphics2D {
return imageObjectInfo;
}

/** {@inheritDoc} */
public boolean drawImage(Image img, int x, int y, int width, int height,
ImageObserver observer) {

// draw with AWT Graphics2D
Dimension size = new Dimension(width, height);
BufferedImage bufferedImage = buildBufferedImage(size);
/**
* Draws an AWT image into a BufferedImage using an AWT Graphics2D implementation
*
* @param img the AWT image
* @param bufferedImage the AWT buffered image
* @param width the image width
* @param height the image height
* @param observer the image observer
* @return true if the image was drawn
*/
private boolean drawBufferedImage(Image img, BufferedImage bufferedImage,
int width, int height, ImageObserver observer) {

java.awt.Graphics2D g2d = bufferedImage.createGraphics();
g2d.setComposite(AlphaComposite.SrcOver);
try {
g2d.setComposite(AlphaComposite.SrcOver);

Color color = new Color(1, 1, 1, 0);
g2d.setBackground(color);
g2d.setPaint(color);

g2d.fillRect(0, 0, width, height);

Color color = new Color(1, 1, 1, 0);
g2d.setBackground(color);
g2d.setPaint(color);
int imageWidth = bufferedImage.getWidth();
int imageHeight = bufferedImage.getHeight();
Rectangle clipRect = new Rectangle(0, 0, imageWidth, imageHeight);
g2d.clip(clipRect);

g2d.fillRect(0, 0, width, height);
g2d.setComposite(gc.getComposite());

int imageWidth = bufferedImage.getWidth();
int imageHeight = bufferedImage.getHeight();
Rectangle clipRect = new Rectangle(0, 0, imageWidth, imageHeight);
g2d.clip(clipRect);
return g2d.drawImage(img, 0, 0, imageWidth, imageHeight, observer);
} finally {
g2d.dispose(); //drawn so dispose immediately to free system resource
}
}

g2d.setComposite(gc.getComposite());
/** {@inheritDoc} */
public boolean drawImage(Image img, int x, int y, int width, int height,
ImageObserver observer) {

boolean drawn = g2d.drawImage(img, 0, 0, imageWidth, imageHeight, observer);
g2d.dispose(); //drawn so dispose immediately to free system resource
// draw with AWT Graphics2D
Dimension imageSize = new Dimension(width, height);
BufferedImage bufferedImage = buildBufferedImage(imageSize);

boolean drawn = drawBufferedImage(img, bufferedImage, width, height, observer);
if (drawn) {
AffineTransform at = gc.getTransform();
float[] srcPts = new float[] {x, y};
float[] dstPts = new float[srcPts.length];
at.transform(srcPts, 0, dstPts, 0, 1);
x = Math.round(dstPts[X]);
y = Math.round(dstPts[Y]);
try {
// get image object info
AFPImageObjectInfo imageObjectInfo = getImageObjectInfo(bufferedImage, x, y, width, height);
AFPImageObjectInfo imageObjectInfo
= createImageObjectInfo(bufferedImage, x, y, width, height);

// create image resource
resourceManager.createObject(imageObjectInfo);
@@ -523,25 +536,24 @@ public class AFPGraphics2D extends AbstractGraphics2D {
return false;
}

/** {@inheritDoc} */
public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
log.debug("drawRenderableImage() NYI: img=" + img + ", xform=" + xform);
}

/** {@inheritDoc} */
public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
log.debug("drawRenderedImage() NYI: img=" + img + ", xform=" + xform);
}

/** {@inheritDoc} */
public FontMetrics getFontMetrics(Font f) {
log.debug("getFontMetrics() NYI: f=" + f);
return null;
}
int width = img.getWidth();
int height = img.getHeight();

/** {@inheritDoc} */
public void setXORMode(Color col) {
log.debug("setXORMode() NYI: col=" + col);
AffineTransform at = paintingState.getData().getTransform();
AffineTransform gat = gc.getTransform();
int x = (int)Math.round(at.getTranslateX() + gat.getTranslateX());
int y = (int)Math.round(at.getTranslateY());
try {
// get image object info
AFPImageObjectInfo imageObjectInfo
= createImageObjectInfo(img, x, y, width, height);
// create image resource
resourceManager.createObject(imageObjectInfo);
} catch (IOException ioe) {
handleIOException(ioe);
}
}

/**
@@ -609,4 +621,27 @@ public class AFPGraphics2D extends AbstractGraphics2D {
public FontInfo getFontInfo() {
return this.fontInfo;
}

/** {@inheritDoc} */
public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
log.debug("drawRenderableImage() NYI: img=" + img + ", xform=" + xform);
}

/** {@inheritDoc} */
public FontMetrics getFontMetrics(Font f) {
log.debug("getFontMetrics() NYI: f=" + f);
return null;
}

/** {@inheritDoc} */
public void setXORMode(Color col) {
log.debug("setXORMode() NYI: col=" + col);
}

/** {@inheritDoc} */
public void addNativeImage(org.apache.xmlgraphics.image.loader.Image image,
float x, float y, float width, float height) {
log.debug("NYI: addNativeImage() "+ "image=" + image
+ ",x=" + x + ",y=" + y + ",width=" + width + ",height=" + height);
}
}

+ 5
- 1
src/java/org/apache/fop/afp/AFPGraphicsObjectInfo.java View File

@@ -19,6 +19,7 @@

package org.apache.fop.afp;

import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;

import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
@@ -62,7 +63,10 @@ public class AFPGraphicsObjectInfo extends AFPDataObjectInfo {
* @return the graphics area
*/
public Rectangle2D getArea() {
return this.area;
AFPObjectAreaInfo objectAreaInfo = getObjectAreaInfo();
int width = objectAreaInfo.getWidth();
int height = objectAreaInfo.getHeight();
return new Rectangle(width, height);
}

/**

+ 7
- 6
src/java/org/apache/fop/afp/AFPPaintingState.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.afp.fonts.AFPPageFonts;
import org.apache.fop.util.AbstractPaintingState;

/**
@@ -42,7 +43,7 @@ public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState
private boolean colorImages = false;

/** images are supported in this AFP environment */
private boolean nativeImages = false;
private boolean nativeImagesSupported = false;

/** default value for image depth */
private int bitsPerPixel = 8;
@@ -165,10 +166,10 @@ public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState
/**
* Sets whether images are natively supported or not in the AFP environment
*
* @param nativeImages true if images are natively supported in this AFP environment
* @param nativeImagesSupported true if images are natively supported in this AFP environment
*/
public void setNativeImages(boolean nativeImages) {
this.nativeImages = nativeImages;
public void setNativeImagesSupported(boolean nativeImagesSupported) {
this.nativeImagesSupported = nativeImagesSupported;
}

/**
@@ -176,8 +177,8 @@ public class AFPPaintingState extends org.apache.fop.util.AbstractPaintingState
*
* @return true if images are supported natively in this AFP environment
*/
public boolean isNativeImages() {
return this.nativeImages;
public boolean isNativeImagesSupported() {
return this.nativeImagesSupported;
}

/**

+ 0
- 5
src/java/org/apache/fop/afp/AFPResourceManager.java View File

@@ -23,8 +23,6 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.afp.modca.AbstractDataObject;
import org.apache.fop.afp.modca.AbstractNamedAFPObject;
import org.apache.fop.afp.modca.DataStream;
@@ -36,9 +34,6 @@ import org.apache.fop.afp.modca.ResourceGroup;
* Manages the creation and storage of document resources
*/
public class AFPResourceManager {
/** Static logging instance */
private static final Log log = LogFactory.getLog(AFPResourceManager.class);

/** The AFP datastream (document tree) */
private DataStream dataStream;


+ 5
- 2
src/java/org/apache/fop/afp/AFPStreamer.java View File

@@ -44,7 +44,7 @@ public class AFPStreamer implements Streamable {

private static final String AFPDATASTREAM_TEMP_FILE_PREFIX = "AFPDataStream_";

private static final int BUFFER_SIZE = 4096;
private static final int BUFFER_SIZE = 4096; // 4k writing buffer

private static final String DEFAULT_EXTERNAL_RESOURCE_FILENAME = "resources.afp";

@@ -159,8 +159,8 @@ public class AFPStreamer implements Streamable {
*
* @throws IOException if an an I/O exception of some sort has occurred
*/
public void close() throws IOException {
// write out any external resource groups
public void close() throws IOException {
Iterator it = pathResourceGroupMap.entrySet().iterator();
while (it.hasNext()) {
StreamedResourceGroup resourceGroup = (StreamedResourceGroup)it.next();
@@ -192,6 +192,7 @@ public class AFPStreamer implements Streamable {

/** {@inheritDoc} */
public void writeToStream(OutputStream os) throws IOException {
// long start = System.currentTimeMillis();
int len = (int)documentFile.length();
int numChunks = len / BUFFER_SIZE;
int remainingChunkSize = len % BUFFER_SIZE;
@@ -212,5 +213,7 @@ public class AFPStreamer implements Streamable {
os.write(buffer, 0, remainingChunkSize);
}
os.flush();
// long end = System.currentTimeMillis();
// log.debug("writing time " + (end - start) + "ms");
}
}

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

@@ -51,7 +51,7 @@ public class Graphics2DImagePainterGOCA extends Graphics2DImagePainterImpl {
/** {@inheritdoc} */
public void prepare(Graphics2D g2d, Rectangle2D area) {
double tx = area.getX();
double ty = area.getHeight() - area.getY();
double ty = area.getHeight() + area.getY();
if (tx != 0 || ty != 0) {
g2d.translate(tx, ty);
}

+ 14
- 13
src/java/org/apache/fop/afp/fonts/AFPFontAttributes.java View File

@@ -23,32 +23,24 @@ package org.apache.fop.afp.fonts;
* This class encapsulates the font attributes that need to be included
* in the AFP data stream. This class does not assist in converting the
* font attributes to AFP code pages and character set values.
*
*/
public class AFPFontAttributes {

/**
* The font reference
*/
/** the font reference */
private int fontReference;

/**
* The font key
*/
/** the font key */
private final String fontKey;

/**
* The font
*/
/** the font */
private final AFPFont font;

/**
* The point size
*/
/** the point size */
private final int pointSize;

/**
* Constructor for the AFPFontAttributes
*
* @param fontKey the font key
* @param font the font
* @param pointSize the point size
@@ -60,6 +52,8 @@ public class AFPFontAttributes {
}

/**
* Return the font
*
* @return the font
*/
public AFPFont getFont() {
@@ -67,6 +61,8 @@ public class AFPFontAttributes {
}

/**
* Return the FontKey attribute
*
* @return the FontKey attribute
*/
public String getFontKey() {
@@ -74,6 +70,8 @@ public class AFPFontAttributes {
}

/**
* Return the point size attribute
*
* @return the point size attribute
*/
public int getPointSize() {
@@ -81,6 +79,8 @@ public class AFPFontAttributes {
}

/**
* Return the FontReference attribute
*
* @return the FontReference attribute
*/
public int getFontReference() {
@@ -89,6 +89,7 @@ public class AFPFontAttributes {

/**
* Sets the FontReference attribute
*
* @param fontReference the FontReference to set
*/
public void setFontReference(int fontReference) {

src/java/org/apache/fop/afp/AFPPageFonts.java → src/java/org/apache/fop/afp/fonts/AFPPageFonts.java View File

@@ -17,11 +17,7 @@

/* $Id$ */

package org.apache.fop.afp;

import org.apache.fop.afp.fonts.AFPFont;
import org.apache.fop.afp.fonts.AFPFontAttributes;

package org.apache.fop.afp.fonts;

/**
* Holds the current page fonts

+ 23
- 0
src/java/org/apache/fop/afp/fonts/package.html View File

@@ -0,0 +1,23 @@
<!--
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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
<HTML>
<TITLE>org.apache.fop.afp.goca Package</TITLE>
<BODY>
<P>Contains a collection of AFP Graphics Object Content Architecture (GOCA) structured objects.</P>
</BODY>
</HTML>

+ 0
- 1
src/java/org/apache/fop/afp/goca/AbstractGraphicsCoord.java View File

@@ -73,7 +73,6 @@ public abstract class AbstractGraphicsCoord extends AbstractPreparedAFPObject {
* Returns the length of this order code (typically this is the same as the coordinate length)
*
* @return the length of this order code
*
*/
protected int getLength() {
return this.coords.length * 2;

+ 42
- 0
src/java/org/apache/fop/afp/goca/GraphicsFilletRelative.java View File

@@ -0,0 +1,42 @@
/*
* 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.afp.goca;

/**
* A GOCA graphics curved tangential line to a specified set of
* straight lines drawn from the given position or current position
*/
public final class GraphicsFilletRelative extends AbstractGraphicsCoord {

/**
* Constructor
*
* @param coords the x/y coordinates for this object
*/
public GraphicsFilletRelative(int[] coords) {
super(coords);
}

/** {@inheritDoc} */
protected byte getOrderCode() {
return (byte)0x85;
}

}

+ 1
- 2
src/java/org/apache/fop/afp/goca/GraphicsLine.java View File

@@ -19,10 +19,9 @@

package org.apache.fop.afp.goca;


/**
* A GOCA graphics straight line drawn from the
* given position or current position.
* given position
*/
public class GraphicsLine extends AbstractGraphicsCoord {


+ 42
- 0
src/java/org/apache/fop/afp/goca/GraphicsLineRelative.java View File

@@ -0,0 +1,42 @@
/*
* 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.afp.goca;

/**
* A GOCA graphics straight line drawn from the
* relative from the current position.
*/
public class GraphicsLineRelative extends AbstractGraphicsCoord {

/**
* Constructor
*
* @param coords the x/y coordinates for this object
*/
public GraphicsLineRelative(int[] coords) {
super(coords);
}

/** {@inheritDoc} */
protected byte getOrderCode() {
return (byte)0x81;
}

}

+ 23
- 0
src/java/org/apache/fop/afp/goca/package.html View File

@@ -0,0 +1,23 @@
<!--
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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
<HTML>
<TITLE>org.apache.fop.afp.fonts Package</TITLE>
<BODY>
<P>Contains a collection of AFP font related classes.</P>
</BODY>
</HTML>

+ 23
- 0
src/java/org/apache/fop/afp/ioca/package.html View File

@@ -0,0 +1,23 @@
<!--
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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
<HTML>
<TITLE>org.apache.fop.afp.ioca Package</TITLE>
<BODY>
<P>Contains a collection of AFP Image Object Content Architecture (IOCA) structured objects.</P>
</BODY>
</HTML>

+ 33
- 2
src/java/org/apache/fop/afp/modca/GraphicsObject.java View File

@@ -30,8 +30,10 @@ import org.apache.fop.afp.Factory;
import org.apache.fop.afp.goca.GraphicsBox;
import org.apache.fop.afp.goca.GraphicsData;
import org.apache.fop.afp.goca.GraphicsFillet;
import org.apache.fop.afp.goca.GraphicsFilletRelative;
import org.apache.fop.afp.goca.GraphicsFullArc;
import org.apache.fop.afp.goca.GraphicsLine;
import org.apache.fop.afp.goca.GraphicsLineRelative;
import org.apache.fop.afp.goca.GraphicsSetArcParameters;
import org.apache.fop.afp.goca.GraphicsSetCharacterSet;
import org.apache.fop.afp.goca.GraphicsSetCurrentPosition;
@@ -181,7 +183,21 @@ public class GraphicsObject extends AbstractDataObject {
* @param coords the x/y coordinates (can be a series)
*/
public void addLine(int[] coords) {
addObject(new GraphicsLine(coords));
addLine(coords, false);
}

/**
* Adds a line at the given x/y coordinates
*
* @param coords the x/y coordinates (can be a series)
* @param relative relative true for a line at current position (relative to)
*/
public void addLine(int[] coords, boolean relative) {
if (relative) {
addObject(new GraphicsLineRelative(coords));
} else {
addObject(new GraphicsLine(coords));
}
}

/**
@@ -199,7 +215,21 @@ public class GraphicsObject extends AbstractDataObject {
* @param coords the x/y coordinates
*/
public void addFillet(int[] coords) {
addObject(new GraphicsFillet(coords));
addFillet(coords, false);
}

/**
* Adds a fillet (curve) at the given coordinates
*
* @param coords the x/y coordinates
* @param relative relative true for a fillet at current position (relative to)
*/
public void addFillet(int[] coords, boolean relative) {
if (relative) {
addObject(new GraphicsFilletRelative(coords));
} else {
addObject(new GraphicsFillet(coords));
}
}

/**
@@ -300,4 +330,5 @@ public class GraphicsObject extends AbstractDataObject {
copySF(data, Type.END, Category.GRAPHICS);
os.write(data);
}

}

+ 23
- 0
src/java/org/apache/fop/afp/modca/package.html View File

@@ -0,0 +1,23 @@
<!--
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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
<HTML>
<TITLE>org.apache.fop.afp.modca Package</TITLE>
<BODY>
<P>Contains a collection of AFP Mixed Object Document Content Architecture (MO:DCA) structured objects.</P>
</BODY>
</HTML>

+ 23
- 0
src/java/org/apache/fop/afp/modca/triplets/package.html View File

@@ -0,0 +1,23 @@
<!--
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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
<HTML>
<TITLE>org.apache.fop.afp.modca.triplets Package</TITLE>
<BODY>
<P>Contains a collection of AFP Mixed Object Document Content Architecture (MO:DCA) triplet classes.</P>
</BODY>
</HTML>

+ 23
- 0
src/java/org/apache/fop/afp/package.html View File

@@ -0,0 +1,23 @@
<!--
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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
<HTML>
<TITLE>org.apache.fop.afp Package</TITLE>
<BODY>
<P>Contains an AFP library.</P>
</BODY>
</HTML>

+ 105
- 0
src/java/org/apache/fop/afp/svg/AFPBridgeContext.java View File

@@ -0,0 +1,105 @@
/*
* 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.afp.svg;

import java.awt.geom.AffineTransform;

import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.DocumentLoader;
import org.apache.batik.bridge.UserAgent;
import org.apache.batik.gvt.TextPainter;
import org.apache.fop.afp.AFPGraphics2D;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.svg.AbstractFOPBridgeContext;
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;

public class AFPBridgeContext extends AbstractFOPBridgeContext {

private final AFPGraphics2D g2d;

/**
* Constructs a new bridge context.
*
* @param userAgent the user agent
* @param fontInfo the font list for the text painter, may be null
* in which case text is painted as shapes
* @param imageManager an image manager
* @param imageSessionContext an image session context
* @param linkTransform AffineTransform to properly place links,
* may be null
* @param g2d an AFPGraphics 2D implementation
*/
public AFPBridgeContext(UserAgent userAgent, FontInfo fontInfo,
ImageManager imageManager, ImageSessionContext imageSessionContext,
AffineTransform linkTransform, AFPGraphics2D g2d) {
super(userAgent, fontInfo, imageManager, imageSessionContext, linkTransform);
this.g2d = g2d;
}

/**
* Constructs a new bridge context.
* @param userAgent the user agent
* @param loader the Document Loader to use for referenced documents.
* @param fontInfo the font list for the text painter, may be null
* in which case text is painted as shapes
* @param linkTransform AffineTransform to properly place links,
* may be null
* @param imageManager an image manager
* @param imageSessionContext an image session context
* @param linkTransform AffineTransform to properly place links,
* may be null
* @param an AFPGraphics 2D implementation
*/
public AFPBridgeContext(UserAgent userAgent, DocumentLoader documentLoader,
FontInfo fontInfo, ImageManager imageManager,
ImageSessionContext imageSessionContext,
AffineTransform linkTransform, AFPGraphics2D g2d) {
super(userAgent, documentLoader, fontInfo, imageManager, imageSessionContext, linkTransform);
this.g2d = g2d;
}

/** {@inheritDoc} */
public void registerSVGBridges() {
super.registerSVGBridges();

if (fontInfo != null) {
AFPTextHandler textHandler = new AFPTextHandler(g2d);
g2d.setCustomTextHandler(textHandler);

TextPainter textPainter = new AFPTextPainter(textHandler);
setTextPainter(textPainter);

putBridge(new AFPTextElementBridge(textPainter));
}

putBridge(new AFPImageElementBridge());
}

/** {@inheritDoc} */
public BridgeContext createBridgeContext() {
return new AFPBridgeContext(getUserAgent(), getDocumentLoader(),
fontInfo,
getImageManager(),
getImageSessionContext(),
linkTransform, g2d);
}

}

+ 37
- 0
src/java/org/apache/fop/afp/svg/AFPImageElementBridge.java View File

@@ -0,0 +1,37 @@
/*
* 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.afp.svg;

import org.apache.fop.svg.AbstractFOPImageElementBridge;
import org.apache.xmlgraphics.image.loader.ImageFlavor;

public class AFPImageElementBridge extends AbstractFOPImageElementBridge {

private final ImageFlavor[] supportedFlavors = new ImageFlavor[]
{ImageFlavor.RAW_JPEG,
ImageFlavor.RAW_CCITTFAX,
ImageFlavor.GRAPHICS2D,
ImageFlavor.XML_DOM};

/** {@inheritDoc} */
protected ImageFlavor[] getSupportedFlavours() {
return supportedFlavors;
}
}

+ 42
- 0
src/java/org/apache/fop/afp/svg/AFPTextElementBridge.java View File

@@ -0,0 +1,42 @@
/*
* 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.afp.svg;

import org.apache.batik.gvt.TextPainter;
import org.apache.fop.svg.AbstractFOPTextElementBridge;

/**
* Bridge class for the &lt;text> element.
* This bridge will use the direct text painter if the text
* for the element is simple.
*/
public class AFPTextElementBridge extends AbstractFOPTextElementBridge {

/**
* Constructs a new bridge for the &lt;text> element.
*
* @param textPainter the text painter to use
*/
public AFPTextElementBridge(TextPainter textPainter) {
super(textPainter);
}

}


src/java/org/apache/fop/afp/AFPTextHandler.java → src/java/org/apache/fop/afp/svg/AFPTextHandler.java View File

@@ -17,16 +17,18 @@

/* $Id$ */

package org.apache.fop.afp;
package org.apache.fop.afp.svg;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.afp.AFPGraphics2D;
import org.apache.fop.afp.AFPPaintingState;
import org.apache.fop.afp.fonts.AFPFont;
import org.apache.fop.afp.fonts.AFPFontAttributes;
import org.apache.fop.afp.fonts.AFPPageFonts;
import org.apache.fop.afp.modca.GraphicsObject;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
@@ -41,9 +43,6 @@ public class AFPTextHandler implements TextHandler {
/** logging instance */
private static Log log = LogFactory.getLog(AFPTextHandler.class);

private static final int X = 0;
private static final int Y = 1;

private AFPGraphics2D g2d = null;

/** Overriding FontState */
@@ -113,7 +112,7 @@ public class AFPTextHandler implements TextHandler {
fontReference = registerPageFont(internalFontName, fontSize);
} else {
java.awt.Font awtFont = g2d.getFont();
AffineTransform fontTransform = awtFont.getTransform();
// AffineTransform fontTransform = awtFont.getTransform();
FontInfo fontInfo = getFontInfo();
Font fopFont = fontInfo.getFontInstanceForAWTFont(awtFont);
String internalFontName = fopFont.getFontName();
@@ -122,14 +121,8 @@ public class AFPTextHandler implements TextHandler {
}
graphicsObj.setCharacterSet(fontReference);

// calculate x, y plotting coordinates from graphics context
AffineTransform at = g2d.getTransform();
float[] srcPts = new float[] { x, y };
float[] dstPts = new float[srcPts.length];
at.transform(srcPts, 0, dstPts, 0, 1);

// add the character string
graphicsObj.addString(str, Math.round(dstPts[X]), Math.round(dstPts[Y]));
graphicsObj.addString(str, Math.round(x), Math.round(y));
}

/**

src/java/org/apache/fop/afp/AFPTextPainter.java → src/java/org/apache/fop/afp/svg/AFPTextPainter.java View File

@@ -17,13 +17,14 @@

/* $Id$ */

package org.apache.fop.afp;
package org.apache.fop.afp.svg;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.font.TextAttribute;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
@@ -42,6 +43,7 @@ import org.apache.batik.gvt.text.Mark;
import org.apache.batik.gvt.text.TextPaintInfo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.afp.AFPGraphics2D;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
@@ -80,6 +82,7 @@ public class AFPTextPainter implements TextPainter {
/**
* Paints the specified attributed character iterator using the
* specified Graphics2D and context and font context.
*
* @param node the TextNode to paint
* @param g2d the Graphics2D to use
*/
@@ -87,10 +90,10 @@ public class AFPTextPainter implements TextPainter {
Point2D loc = node.getLocation();
log.debug("painting text node " + node);
if (hasUnsupportedAttributes(node)) {
log.debug("hasunsuportedattributes");
log.debug("hasUnsuportedAttributes");
PROXY_PAINTER.paint(node, g2d);
} else {
log.debug("allattributessupported");
log.debug("allAttributesSupported");
paintTextRuns(node.getTextRuns(), g2d, loc);
}
}
@@ -221,7 +224,8 @@ public class AFPTextPainter implements TextPainter {
aci.first();

updateLocationFromACI(aci, loc);
loc = g2d.getTransform().transform(loc, null);
AffineTransform at = g2d.getTransform();
loc = at.transform(loc, null);

// font
Font font = makeFont(aci);
@@ -240,6 +244,7 @@ public class AFPTextPainter implements TextPainter {
}
g2d.setPaint(foreground);

// text
String txt = getText(aci);
float advance = getStringWidth(txt, font);
float tx = 0;
@@ -258,9 +263,11 @@ public class AFPTextPainter implements TextPainter {
}

// draw string
double x = loc.getX();
double y = loc.getY();
try {
try {
nativeTextHandler.drawString(txt, (float)(loc.getX() + tx), (float)(loc.getY()));
nativeTextHandler.drawString(txt, (float)x + tx, (float)y);
} catch (IOException ioe) {
if (g2d instanceof AFPGraphics2D) {
((AFPGraphics2D)g2d).handleIOException(ioe);
@@ -424,6 +431,7 @@ public class AFPTextPainter implements TextPainter {
* Get the geometry bounds.
* This uses the StrokingTextPainter to get the bounds
* since in theory it should be the same.
*
* @param node the text node
* @return the bounds of the text
*/
@@ -436,6 +444,7 @@ public class AFPTextPainter implements TextPainter {
/**
* Get the mark.
* This does nothing since the output is AFP and not interactive.
*
* @param node the text node
* @param pos the position
* @param all select all
@@ -448,6 +457,7 @@ public class AFPTextPainter implements TextPainter {
/**
* Select at.
* This does nothing since the output is AFP and not interactive.
*
* @param x the x position
* @param y the y position
* @param node the text node
@@ -460,6 +470,7 @@ public class AFPTextPainter implements TextPainter {
/**
* Select to.
* This does nothing since the output is AFP and not interactive.
*
* @param x the x position
* @param y the y position
* @param beginMark the start mark
@@ -472,6 +483,7 @@ public class AFPTextPainter implements TextPainter {
/**
* Selec first.
* This does nothing since the output is AFP and not interactive.
*
* @param node the text node
* @return null
*/
@@ -482,6 +494,7 @@ public class AFPTextPainter implements TextPainter {
/**
* Select last.
* This does nothing since the output is AFP and not interactive.
*
* @param node the text node
* @return null
*/
@@ -492,6 +505,7 @@ public class AFPTextPainter implements TextPainter {
/**
* Get selected.
* This does nothing since the output is AFP and not interactive.
*
* @param start the start mark
* @param finish the finish mark
* @return null
@@ -503,6 +517,7 @@ public class AFPTextPainter implements TextPainter {
/**
* Get the highlighted shape.
* This does nothing since the output is AFP and not interactive.
*
* @param beginMark the start mark
* @param endMark the end mark
* @return null

+ 2
- 2
src/java/org/apache/fop/fonts/FontInfo.java View File

@@ -389,8 +389,8 @@ public class FontInfo {
}
matchedTriplet = fontLookup(awtFontFamily, awtFontStyle, awtFontWeight);
}
float awtFontSize = awtFont.getSize2D();
return getFontInstance(matchedTriplet, (int)(awtFontSize * 1000 + 0.5));
int fontSize = Math.round(awtFont.getSize2D() * 1000);
return getFontInstance(matchedTriplet, fontSize);
}

/**

+ 17
- 0
src/java/org/apache/fop/fonts/package.html View File

@@ -1,3 +1,20 @@
<!--
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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
<HTML>
<TITLE>org.apache.fop.fonts Package</TITLE>
<BODY>

+ 17
- 0
src/java/org/apache/fop/pdf/package.html View File

@@ -1,3 +1,20 @@
<!--
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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
<HTML>
<TITLE>org.apache.fop.pdf Package</TITLE>
<BODY>

+ 28
- 14
src/java/org/apache/fop/render/AbstractGenericSVGHandler.java View File

@@ -29,10 +29,12 @@ import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.dom.AbstractDocument;
import org.apache.batik.dom.svg.SVGDOMImplementation;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.events.EventBroadcaster;
import org.apache.fop.fo.extensions.ExtensionElementMapping;
import org.apache.fop.image.loader.batik.Graphics2DImagePainterImpl;
import org.apache.fop.render.RendererContext.RendererContextWrapper;
import org.apache.fop.render.afp.AFPGraphics2DAdapter;
import org.apache.fop.svg.SVGEventProducer;
import org.apache.fop.svg.SVGUserAgent;
import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
@@ -71,7 +73,7 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC
* @param imageSize the image size
* @return a new graphics 2D image painter implementation
*/
protected Graphics2DImagePainter createPainter(
protected Graphics2DImagePainter createGraphics2DImagePainter(
GraphicsNode root, BridgeContext ctx, Dimension imageSize) {
return new Graphics2DImagePainterImpl(root, ctx, imageSize);
}
@@ -85,14 +87,14 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC
* @return a built GVT root tree
*/
protected GraphicsNode buildGraphicsNode(
RendererContext rendererContext, BridgeContext ctx, Document doc) {
FOUserAgent userAgent, BridgeContext ctx, Document doc) {
GVTBuilder builder = new GVTBuilder();
final GraphicsNode root;
try {
root = builder.build(ctx, doc);
} catch (Exception e) {
EventBroadcaster eventBroadcaster
= rendererContext.getUserAgent().getEventBroadcaster();
= userAgent.getEventBroadcaster();
SVGEventProducer eventProducer = SVGEventProducer.Provider.get(eventBroadcaster);
final String uri = getDocumentURI(doc);
eventProducer.svgNotBuilt(this, e, uri);
@@ -101,6 +103,18 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC
return root;
}

/**
* Returns the image size
* @param wrappedContext renderer context wrapper
*
* @return the image size
*/
protected Dimension getImageSize(RendererContextWrapper wrappedContext) {
final int width = wrappedContext.getWidth();
final int height = wrappedContext.getHeight();
return new Dimension(width, height);
}

/**
* Render the SVG document.
*
@@ -113,23 +127,21 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC
updateRendererContext(rendererContext);

//Prepare
SVGUserAgent svgUserAgent = new SVGUserAgent(
rendererContext.getUserAgent(), new AffineTransform());
FOUserAgent userAgent = rendererContext.getUserAgent();
SVGUserAgent svgUserAgent = new SVGUserAgent(userAgent, new AffineTransform());

//Create Batik BridgeContext
final BridgeContext bridgeContext = new BridgeContext(svgUserAgent);

//Build the GVT tree
final GraphicsNode root = buildGraphicsNode(rendererContext, bridgeContext, doc);

final GraphicsNode root = buildGraphicsNode(userAgent, bridgeContext, doc);

// Create Graphics2DImagePainter
final RendererContextWrapper wrappedContext = RendererContext.wrapRendererContext(
rendererContext);

//Get Image Size
final int width = wrappedContext.getWidth();
final int height = wrappedContext.getHeight();
Dimension imageSize = new Dimension(width, height);

//Create the painter
final Graphics2DImagePainter painter = createPainter(root, bridgeContext, imageSize);
Dimension imageSize = getImageSize(wrappedContext);
final Graphics2DImagePainter painter = createGraphics2DImagePainter(root, bridgeContext, imageSize);

//Let the painter paint the SVG on the Graphics2D instance
Graphics2DAdapter g2dAdapter = rendererContext.getRenderer().getGraphics2DAdapter();
@@ -137,6 +149,8 @@ public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererC
//Paint the image
final int x = wrappedContext.getCurrentXPosition();
final int y = wrappedContext.getCurrentYPosition();
final int width = wrappedContext.getWidth();
final int height = wrappedContext.getHeight();
g2dAdapter.paintImage(painter, rendererContext, x, y, width, height);
}


+ 13
- 2
src/java/org/apache/fop/render/AbstractGraphics2DAdapter.java View File

@@ -54,8 +54,8 @@ public abstract class AbstractGraphics2DAdapter implements Graphics2DAdapter {
protected BufferedImage paintToBufferedImage(
org.apache.xmlgraphics.java2d.Graphics2DImagePainter painter,
RendererContextWrapper context, int resolution, boolean gray, boolean withAlpha) {
int bmw = (int)Math.ceil(UnitConv.mpt2px(context.getWidth(), resolution));
int bmh = (int)Math.ceil(UnitConv.mpt2px(context.getHeight(), resolution));
int bmw = mpt2px(context.getWidth(), resolution);
int bmh = mpt2px(context.getHeight(), resolution);
BufferedImage bi;
if (gray) {
if (withAlpha) {
@@ -102,6 +102,17 @@ public abstract class AbstractGraphics2DAdapter implements Graphics2DAdapter {
return bi;
}

/**
* Converts millipoints to pixels
*
* @param unit the unit to convert in mpts
* @param resolution the target resolution
* @return the converted unit in pixels
*/
protected int mpt2px(int unit, int resolution) {
return (int)Math.ceil(UnitConv.mpt2px(unit, resolution));
}

private static BufferedImage createGrayBufferedImageWithAlpha(int width, int height) {
BufferedImage bi;
boolean alphaPremultiplied = true;

+ 211
- 0
src/java/org/apache/fop/render/AbstractImageHandlerRegistry.java View File

@@ -0,0 +1,211 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render;

import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.util.Service;

/**
* This class holds references to various image handlers used by the renderers. It also
* supports automatic discovery of additional handlers available through
* the class path.
*/
public abstract class AbstractImageHandlerRegistry {

/** the logger */
private static Log log = LogFactory.getLog(AbstractImageHandlerRegistry.class);

private static final Comparator HANDLER_COMPARATOR = new Comparator() {
public int compare(Object o1, Object o2) {
ImageHandler h1 = (ImageHandler)o1;
ImageHandler h2 = (ImageHandler)o2;
return h1.getPriority() - h2.getPriority();
}
};

/** Map containing image handlers for various MIME types */
private final Map/*<Class, ImageHandler>*/ handlers
= new java.util.HashMap/*<Class, ImageHandler>*/();

/** List containing the same handlers as above but ordered by priority */
private final List/*<ImageHandler>*/ handlerList
= new java.util.LinkedList/*<ImageHandler>*/();

/** Sorted Set of registered handlers */
private ImageFlavor[] supportedFlavors = new ImageFlavor[0];

private int handlerRegistrations;
private int lastSync;

/**
* Default constructor.
*/
public AbstractImageHandlerRegistry() {
discoverHandlers();
}

/**
* Add an ImageHandler. The handler itself is inspected to find out what it supports.
* @param classname the fully qualified class name
*/
public void addHandler(String classname) {
try {
ImageHandler handlerInstance
= (ImageHandler)Class.forName(classname).newInstance();
addHandler(handlerInstance);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Could not find "
+ classname);
} catch (InstantiationException e) {
throw new IllegalArgumentException("Could not instantiate "
+ classname);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Could not access "
+ classname);
} catch (ClassCastException e) {
throw new IllegalArgumentException(classname
+ " is not an "
+ getHandlerClass().getName());
}
}

/**
* Add an image handler. The handler itself is inspected to find out what it supports.
* @param handler the ImageHandler instance
*/
public synchronized void addHandler(ImageHandler handler) {
Class[] imageClasses = handler.getSupportedImageClasses();
for (int i = 0; i < imageClasses.length; i++) {
this.handlers.put(imageClasses[i], handler);
}

//Sorted insert
ListIterator iter = this.handlerList.listIterator();
while (iter.hasNext()) {
ImageHandler h = (ImageHandler)iter.next();
if (getHandlerComparator().compare(handler, h) < 0) {
iter.previous();
break;
}
}
iter.add(handler);
this.handlerRegistrations++;
}

/**
* Returns an ImageHandler which handles an specific image type given the MIME type
* of the image.
* @param img the Image to be handled
* @return the ImageHandler responsible for handling the image or null if none is available
*/
public ImageHandler getHandler(Image img) {
return getHandler(img.getClass());
}

/**
* Returns an ImageHandler which handles an specific image type given the MIME type
* of the image.
* @param imageClass the Image subclass for which to get a handler
* @return the ImageHandler responsible for handling the image or null if none is available
*/
public synchronized ImageHandler getHandler(Class imageClass) {
ImageHandler handler = null;
Class cl = imageClass;
while (cl != null) {
handler = (ImageHandler)handlers.get(cl);
if (handler != null) {
break;
}
cl = cl.getSuperclass();
}
return handler;
}

/**
* Returns the ordered array of supported image flavors.
* @return the array of image flavors
*/
public synchronized ImageFlavor[] getSupportedFlavors() {
if (this.lastSync != this.handlerRegistrations) {
//Extract all ImageFlavors into a single array
List flavors = new java.util.ArrayList();
Iterator iter = this.handlerList.iterator();
while (iter.hasNext()) {
ImageFlavor[] f = ((ImageHandler)iter.next()).getSupportedImageFlavors();
for (int i = 0; i < f.length; i++) {
flavors.add(f[i]);
}
}
this.supportedFlavors = (ImageFlavor[])flavors.toArray(new ImageFlavor[flavors.size()]);
this.lastSync = this.handlerRegistrations;
}
return this.supportedFlavors;
}

/**
* Discovers ImageHandler implementations through the classpath and dynamically
* registers them.
*/
private void discoverHandlers() {
// add mappings from available services
Class imageHandlerClass = getHandlerClass();
Iterator providers = Service.providers(imageHandlerClass);
if (providers != null) {
while (providers.hasNext()) {
ImageHandler handler = (ImageHandler)providers.next();
try {
if (log.isDebugEnabled()) {
log.debug("Dynamically adding ImageHandler: "
+ handler.getClass().getName());
}
addHandler(handler);
} catch (IllegalArgumentException e) {
log.error("Error while adding ImageHandler", e);
}

}
}
}

/**
* Returns the ImageHandler comparator
*
* @return the ImageHandler comparator
*/
public Comparator getHandlerComparator() {
return HANDLER_COMPARATOR;
}

/**
* Returns the ImageHandler implementing class
*
* @return the ImageHandler implementing class
*/
public abstract Class getHandlerClass();
}

+ 46
- 0
src/java/org/apache/fop/render/ImageHandler.java View File

@@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render;

import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;

public interface ImageHandler {

/**
* Returns the priority for this image handler. A lower value means higher priority. This
* information is used to build the ordered/prioritized list of supported ImageFlavors for
* the PDF renderer. The built-in handlers use priorities between 100 and 999.
* @return a positive integer (>0) indicating the priority
*/
int getPriority();

/**
* Returns the {@link ImageFlavor}s supported by this instance
* @return the supported image flavors
*/
ImageFlavor[] getSupportedImageFlavors();

/**
* Returns the {@link Image} subclasses supported by this instance.
* @return the Image types
*/
Class[] getSupportedImageClasses();
}

+ 10
- 4
src/java/org/apache/fop/render/PrintRenderer.java View File

@@ -24,8 +24,6 @@ import java.awt.geom.Rectangle2D;
import java.util.List;
import java.util.Map;

import org.w3c.dom.Document;

import org.apache.fop.area.Area;
import org.apache.fop.area.Trait;
import org.apache.fop.fonts.CustomFontCollection;
@@ -36,6 +34,7 @@ import org.apache.fop.fonts.FontManager;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.base14.Base14FontCollection;
import org.w3c.dom.Document;

/** Abstract base class of "Print" type renderers. */
public abstract class PrintRenderer extends AbstractRenderer {
@@ -111,6 +110,14 @@ public abstract class PrintRenderer extends AbstractRenderer {
return fontInfo.getFontInstance(triplet, size);
}

/**
* Instantiates a RendererContext for an image
* @return a newly created RendererContext.
*/
protected RendererContext instantiateRendererContext() {
return new RendererContext(this, getMimeType());
}

/**
* Creates a RendererContext for an image.
* @param x the x coordinate (in millipoints)
@@ -122,8 +129,7 @@ public abstract class PrintRenderer extends AbstractRenderer {
*/
protected RendererContext createRendererContext(int x, int y, int width, int height,
Map foreignAttributes) {
RendererContext context;
context = new RendererContext(this, getMimeType());
RendererContext context = instantiateRendererContext();
context.setUserAgent(userAgent);

context.setProperty(RendererContextConstants.WIDTH,

+ 29
- 7
src/java/org/apache/fop/render/RendererContext.java View File

@@ -20,10 +20,12 @@
package org.apache.fop.render;

//Java
import java.util.Iterator;
import java.util.Map;

//FOP
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fo.extensions.ExtensionElementMapping;
import org.apache.xmlgraphics.util.QName;

/**
* The Render Context for external handlers. This provides a rendering context
@@ -31,21 +33,28 @@ import org.apache.fop.apps.FOUserAgent;
* render target.
*/
public class RendererContext {
/** conversion-mode extension attribute */
protected static final QName CONVERSION_MODE = new QName(
ExtensionElementMapping.URI, null, "conversion-mode");

/** "bitmap" value for the "conversion-mode" extension attribute. */
protected static final String BITMAP = "bitmap";

private final String mime;
private final AbstractRenderer renderer;
private FOUserAgent userAgent;
private final Map props = new java.util.HashMap();

private final Map/*<String,Object>*/ props = new java.util.HashMap/*<String,Object>*/();

/**
* Contructor for this class. It takes a MIME type as parameter.
* Constructor for this class. It takes a MIME type as parameter.
*
* @param renderer The current renderer
* @param m The MIME type of the output that's generated.
* @param renderer the current renderer
* @param mime the MIME type of the output that's generated.
*/
public RendererContext(AbstractRenderer renderer, String m) {
public RendererContext(AbstractRenderer renderer, String mime) {
this.renderer = renderer;
this.mime = m;
this.mime = mime;
}

/**
@@ -113,6 +122,19 @@ public class RendererContext {
return wrapper;
}

/** {@inheritDoc} **/
public String toString() {
StringBuffer stringBuffer = new StringBuffer("RendererContext{\n");
Iterator it = props.keySet().iterator();
while (it.hasNext()) {
String key = (String)it.next();
Object value = props.get(key);
stringBuffer.append("\t" + key + "=" + value + "\n");
}
stringBuffer.append("}");
return stringBuffer.toString();
}

/**
* Base class for a wrapper around RendererContext to access its properties in a type-safe,
* renderer-specific way.

+ 0
- 93
src/java/org/apache/fop/render/afp/AFPAbstractImageFactory.java View File

@@ -1,93 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.afp;

import java.io.IOException;

import org.apache.fop.afp.AFPDataObjectInfo;
import org.apache.fop.afp.AFPForeignAttributeReader;
import org.apache.fop.afp.AFPObjectAreaInfo;
import org.apache.fop.afp.AFPPaintingState;
import org.apache.fop.afp.AFPResourceInfo;
import org.apache.fop.afp.AFPUnitConverter;


/**
* Abstract image configurator
*/
public abstract class AFPAbstractImageFactory {
private static final int X = 0;
private static final int Y = 1;

/** the AFP state */
protected final AFPPaintingState state;

/** foreign attribute reader */
private final AFPForeignAttributeReader foreignAttributeReader
= new AFPForeignAttributeReader();

/**
* Main constructor
*
* @param state the AFP painting state
*/
public AFPAbstractImageFactory(AFPPaintingState state) {
this.state = state;
}

/**
* Configures the data object info
*
* @param afpImageInfo the afp image info
* @return the data object info
* @throws IOException thrown if an I/O exception of some sort has occurred.
*/
public AFPDataObjectInfo create(AFPRendererImageInfo afpImageInfo) throws IOException {
AFPDataObjectInfo dataObjectInfo = createDataObjectInfo();

// set resource information
AFPResourceInfo resourceInfo
= foreignAttributeReader.getResourceInfo(afpImageInfo.foreignAttributes);
resourceInfo.setUri(afpImageInfo.uri);
dataObjectInfo.setResourceInfo(resourceInfo);

// set object area
AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo();
float srcX = afpImageInfo.origin.x + (float)afpImageInfo.pos.getX();
float srcY = afpImageInfo.origin.y + (float)afpImageInfo.pos.getY();
AFPUnitConverter unitConv = state.getUnitConverter();
int[] coords = unitConv.mpts2units(new float[] {srcX, srcY});
objectAreaInfo.setX(coords[X]);
objectAreaInfo.setY(coords[Y]);
int width = Math.round(unitConv.mpt2units((float)afpImageInfo.pos.getWidth()));
objectAreaInfo.setWidth(width);
int height = Math.round(unitConv.mpt2units((float)afpImageInfo.pos.getHeight()));
objectAreaInfo.setHeight(height);
dataObjectInfo.setObjectAreaInfo(objectAreaInfo);
return dataObjectInfo;
}

/**
* Creates the data object information object
*
* @return the data object information object
*/
protected abstract AFPDataObjectInfo createDataObjectInfo();
}

+ 0
- 87
src/java/org/apache/fop/render/afp/AFPDataObjectInfoProvider.java View File

@@ -1,87 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.afp;

import java.util.Iterator;
import java.util.Map;

import org.apache.fop.afp.AFPPaintingState;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;
import org.apache.xmlgraphics.image.loader.impl.ImageRendered;

/**
* AFP data object info factory provider
*/
public class AFPDataObjectInfoProvider {

private final Map/*<AbstractImage,AFPDataObjectInfoFactory>*/ factoryMap
= new java.util.HashMap/*<AbstractImage,AFPDataObjectInfoFactory>*/();

private final AFPPaintingState state;

/**
* Main constructor
*
* @param state the AFP painting state
*/
public AFPDataObjectInfoProvider(AFPPaintingState state) {
this.state = state;
init();
}

/**
* Initialises the configurators
*/
private void init() {
factoryMap.put(
ImageRendered.class, new AFPImageRenderedFactory(state));
factoryMap.put(
ImageRawCCITTFax.class, new AFPRawCCITTFaxFactory(state));
factoryMap.put(
ImageRawStream.class, new AFPImageRawStreamFactory(state));
factoryMap.put(
ImageGraphics2D.class, new AFPImageGraphics2DFactory(state));
};

/**
* Returns the configurator for a given image
*
* @param img the image
* @return the image configurator for the image
*/
public AFPDataObjectInfoFactory getFactory(Image img) {
Class clazz = img.getClass();
AFPDataObjectInfoFactory configurator = (AFPDataObjectInfoFactory)factoryMap.get(clazz);
// not directly matched so try to map ancestor
if (configurator == null) {
Iterator it = factoryMap.keySet().iterator();
while (it.hasNext()) {
Class imageClass = (Class)it.next();
if (imageClass.isInstance(img)) {
return (AFPDataObjectInfoFactory)factoryMap.get(imageClass);
}
}
}
return configurator;
}
}

src/java/org/apache/fop/afp/AFPForeignAttributeReader.java → src/java/org/apache/fop/render/afp/AFPForeignAttributeReader.java View File

@@ -17,13 +17,15 @@

/* $Id$ */

package org.apache.fop.afp;
package org.apache.fop.render.afp;

import java.io.File;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.afp.AFPResourceInfo;
import org.apache.fop.afp.AFPResourceLevel;
import org.apache.fop.render.afp.extensions.AFPElementMapping;
import org.apache.xmlgraphics.util.QName;


+ 37
- 66
src/java/org/apache/fop/render/afp/AFPGraphics2DAdapter.java View File

@@ -28,7 +28,6 @@ import java.io.IOException;
import org.apache.fop.afp.AFPGraphics2D;
import org.apache.fop.afp.AFPGraphicsObjectInfo;
import org.apache.fop.afp.AFPPaintingState;
import org.apache.fop.afp.AFPResourceInfo;
import org.apache.fop.afp.AFPResourceManager;
import org.apache.fop.render.AbstractGraphics2DAdapter;
import org.apache.fop.render.RendererContext;
@@ -40,95 +39,67 @@ import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
*/
public class AFPGraphics2DAdapter extends AbstractGraphics2DAdapter {

private final AFPRenderer renderer;

private final AFPGraphics2D g2d;
private final AFPPaintingState paintingState;

/**
* Main constructor
*
* @param renderer the afp renderer
*/
public AFPGraphics2DAdapter(AFPRenderer renderer) {
this.renderer = renderer;

final boolean textAsShapes = false;
this.g2d = new AFPGraphics2D(textAsShapes);
}

/**
* Returns the AFP graphics 2D implementation
*
* @return the AFP graphics 2D implementation
* @param paintingState the AFP painting state
*/
public AFPGraphics2D getGraphics2D() {
return g2d;
public AFPGraphics2DAdapter(AFPPaintingState paintingState) {
this.paintingState = paintingState;
}

/** {@inheritDoc} */
public void paintImage(Graphics2DImagePainter painter,
RendererContext context,
RendererContext rendererContext,
int x, int y, int width, int height) throws IOException {

AFPInfo afpInfo = AFPSVGHandler.getAFPInfo(context);

// set resource manager
AFPResourceManager resourceManager = afpInfo.getResourceManager();
g2d.setResourceManager(resourceManager);

// set resource information
AFPResourceInfo resourceInfo = afpInfo.getResourceInfo();
g2d.setResourceInfo(resourceInfo);
AFPRendererContext afpRendererContext = (AFPRendererContext)rendererContext;
AFPInfo afpInfo = afpRendererContext.getInfo();

// set painting state
AFPPaintingState paintingState = afpInfo.getPaintingState();
g2d.setPaintingState(paintingState);

// set graphic context
g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());

float fwidth = width / 1000f;
float fheight = height / 1000f;

// get the 'width' and 'height' attributes of the SVG document
Dimension imageSize = painter.getImageSize();
float imw = (float)imageSize.getWidth() / 1000f;
float imh = (float)imageSize.getHeight() / 1000f;
float sx = fwidth / imw;
float sy = fheight / imh;
AffineTransform at = new AffineTransform(sx, 0, 0, sy, x, y);
final boolean textAsShapes = false;
AFPGraphics2D g2d = afpInfo.createGraphics2D(textAsShapes);

renderer.saveGraphicsState();
paintingState.push();

//Fallback solution: Paint to a BufferedImage
if (afpInfo.paintAsBitmap()) {
//Fallback solution: Paint to a BufferedImage
int resolution = Math.round(context.getUserAgent().getTargetResolution());
RendererContextWrapper ctx = RendererContext.wrapRendererContext(context);
BufferedImage bufferedImage = paintToBufferedImage(painter, ctx, resolution, false, false);

AFPPaintingState state = afpInfo.getPaintingState();
AffineTransform trans = state.getData().getTransform();
float scale = AFPRenderer.NORMAL_AFP_RESOLUTION
/ context.getUserAgent().getTargetResolution();
if (scale != 1) {
at.scale(scale, scale);
}

if (!at.isIdentity()) {
trans.concatenate(at);
}

g2d.drawImage(bufferedImage, trans, null);

// paint image
RendererContextWrapper rendererContextWrapper
= RendererContext.wrapRendererContext(rendererContext);
float targetResolution = rendererContext.getUserAgent().getTargetResolution();
int resolution = Math.round(targetResolution);
boolean colorImages = afpInfo.isColorSupported();
BufferedImage bufferedImage = paintToBufferedImage(
painter, rendererContextWrapper, resolution, !colorImages, false);

// draw image
AffineTransform at = paintingState.getData().getTransform();
at.translate(x, y);
g2d.drawImage(bufferedImage, at, null);
} else {
AFPGraphicsObjectInfo graphicsObjectInfo = new AFPGraphicsObjectInfo();
graphicsObjectInfo.setPainter(painter);
graphicsObjectInfo.setGraphics2D(g2d);

// get the 'width' and 'height' attributes of the SVG document
Dimension imageSize = painter.getImageSize();
float imw = (float)imageSize.getWidth() / 1000f;
float imh = (float)imageSize.getHeight() / 1000f;

Rectangle2D area = new Rectangle2D.Double(0.0, 0.0, imw, imh);
graphicsObjectInfo.setArea(area);
AFPResourceManager resourceManager = afpInfo.getResourceManager();
resourceManager.createObject(graphicsObjectInfo);
}

renderer.restoreGraphicsState();
paintingState.pop();
}

/** {@inheritDoc} */
protected int mpt2px(int unit, int resolution) {
return Math.round(paintingState.getUnitConverter().mpt2units(unit));
}
}

+ 0
- 135
src/java/org/apache/fop/render/afp/AFPImageGraphics2DFactory.java View File

@@ -1,135 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.afp;

import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.io.IOException;

import org.apache.batik.bridge.BridgeContext;
import org.apache.fop.afp.AFPDataObjectInfo;
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.AFPTextElementBridge;
import org.apache.fop.afp.AFPTextHandler;
import org.apache.fop.afp.AFPTextPainter;
import org.apache.fop.render.RendererContext;
import org.apache.fop.svg.SVGUserAgent;
import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
import org.apache.xmlgraphics.util.MimeConstants;


/**
* An AFP image graphics 2d factory
*/
public class AFPImageGraphics2DFactory extends AFPDataObjectInfoFactory {

/**
* Main constructor
*
* @param state the AFP painting state
*/
public AFPImageGraphics2DFactory(AFPPaintingState state) {
super(state);
}

/** {@inheritDoc} */
protected AFPDataObjectInfo createDataObjectInfo() {
return new AFPGraphicsObjectInfo();
}

/** {@inheritDoc} */
public AFPDataObjectInfo create(AFPRendererImageInfo rendererImageInfo) throws IOException {
AFPGraphicsObjectInfo graphicsObjectInfo
= (AFPGraphicsObjectInfo)super.create(rendererImageInfo);

AFPResourceInfo resourceInfo = graphicsObjectInfo.getResourceInfo();
// level not explicitly set/changed so default to inline for GOCA graphic objects
// (due to a bug in the IBM AFP Workbench Viewer (2.04.01.07) - hard copy works just fine)
if (!resourceInfo.levelChanged()) {
resourceInfo.setLevel(new AFPResourceLevel(AFPResourceLevel.INLINE));
}

// set mime type (unsupported by MOD:CA registry)
graphicsObjectInfo.setMimeType(MimeConstants.MIME_AFP_GOCA);

// set graphics 2d
AFPGraphics2DAdapter g2dAdapter = rendererImageInfo.getGraphics2DAdapter();
AFPGraphics2D g2d = g2dAdapter.getGraphics2D();
graphicsObjectInfo.setGraphics2D(g2d);

// set resource, state and font info
RendererContext rendererContext = rendererImageInfo.getRendererContext();
AFPInfo afpInfo = AFPSVGHandler.getAFPInfo(rendererContext);
g2d.setResourceManager(afpInfo.getResourceManager());
g2d.setResourceInfo(afpInfo.getResourceInfo());
g2d.setPaintingState(afpInfo.getPaintingState());
g2d.setFontInfo(afpInfo.getFontInfo());

// set to default graphic context
g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());

// translate to current location
AffineTransform at = state.getData().getTransform();
g2d.translate(at.getTranslateX(), at.getTranslateY());

// set afp state
g2d.setPaintingState(state);

// controls whether text painted by Batik is generated using text or path operations
SVGUserAgent svgUserAgent
= new SVGUserAgent(rendererContext.getUserAgent(), new AffineTransform());
BridgeContext ctx = new BridgeContext(svgUserAgent);
if (!afpInfo.strokeText()) {
AFPTextHandler textHandler = new AFPTextHandler(g2d);
g2d.setCustomTextHandler(textHandler);
AFPTextPainter textPainter = new AFPTextPainter(textHandler);
ctx.setTextPainter(textPainter);
AFPTextElementBridge textElementBridge = new AFPTextElementBridge(textPainter);
ctx.putBridge(textElementBridge);
}

// set painter
ImageGraphics2D imageG2D = (ImageGraphics2D)rendererImageInfo.getImage();
Graphics2DImagePainter painter = imageG2D.getGraphics2DImagePainter();
graphicsObjectInfo.setPainter(painter);

// set object area
AFPObjectAreaInfo objectAreaInfo = graphicsObjectInfo.getObjectAreaInfo();
int width = objectAreaInfo.getWidth();
int height = objectAreaInfo.getHeight();
Rectangle area = new Rectangle(width, height);
graphicsObjectInfo.setArea(area);

// invert y-axis for GOCA
final int sx = 1;
final int sy = -1;
g2d.translate(0, height);
g2d.scale(sx, sy);

return graphicsObjectInfo;
}

}

src/java/org/apache/fop/render/afp/AFPDataObjectInfoFactory.java → src/java/org/apache/fop/render/afp/AFPImageHandler.java View File

@@ -22,51 +22,39 @@ package org.apache.fop.render.afp;
import java.awt.Point;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.util.Map;

import org.apache.fop.afp.AFPDataObjectInfo;
import org.apache.fop.afp.AFPForeignAttributeReader;
import org.apache.fop.afp.AFPObjectAreaInfo;
import org.apache.fop.afp.AFPPaintingState;
import org.apache.fop.afp.AFPResourceInfo;
import org.apache.fop.afp.AFPUnitConverter;
import org.apache.fop.render.ImageHandler;


/**
* Abstract image configurator
*/
public abstract class AFPDataObjectInfoFactory {
public abstract class AFPImageHandler implements ImageHandler {
private static final int X = 0;
private static final int Y = 1;

/** the AFP painting state */
protected final AFPPaintingState state;

/** foreign attribute reader */
private final AFPForeignAttributeReader foreignAttributeReader
= new AFPForeignAttributeReader();

/**
* Main constructor
* Generates an intermediate AFPDataObjectInfo that is later used to construct
* the appropriate data object in the AFP DataStream.
*
* @param state the AFP state
*/
public AFPDataObjectInfoFactory(AFPPaintingState state) {
this.state = state;
}

/**
* Configures the data object info
*
* @param rendererImageInfo the afp image info
* @return the data object info
* @param rendererImageInfo the renderer image info
* @return a data object info object
* @throws IOException thrown if an I/O exception of some sort has occurred.
*/
public AFPDataObjectInfo create(AFPRendererImageInfo rendererImageInfo) throws IOException {
public AFPDataObjectInfo generateDataObjectInfo(
AFPRendererImageInfo rendererImageInfo) throws IOException {
AFPDataObjectInfo dataObjectInfo = createDataObjectInfo();

// set resource information
Map foreignAttributes = rendererImageInfo.getForeignAttributes();
AFPResourceInfo resourceInfo
= foreignAttributeReader.getResourceInfo(rendererImageInfo.getForeignAttributes());
= foreignAttributeReader.getResourceInfo(foreignAttributes);
resourceInfo.setUri(rendererImageInfo.getURI());
dataObjectInfo.setResourceInfo(resourceInfo);

@@ -77,7 +65,12 @@ public abstract class AFPDataObjectInfoFactory {
Rectangle2D position = rendererImageInfo.getPosition();
float srcX = origin.x + (float)position.getX();
float srcY = origin.y + (float)position.getY();
AFPUnitConverter unitConv = state.getUnitConverter();

AFPRendererContext rendererContext
= (AFPRendererContext)rendererImageInfo.getRendererContext();
AFPInfo afpInfo = rendererContext.getInfo();
AFPPaintingState paintingState = afpInfo.getPaintingState();
AFPUnitConverter unitConv = paintingState.getUnitConverter();
int[] coords = unitConv.mpts2units(new float[] {srcX, srcY});
objectAreaInfo.setX(coords[X]);
objectAreaInfo.setY(coords[Y]);
@@ -88,11 +81,11 @@ public abstract class AFPDataObjectInfoFactory {
int height = Math.round(unitConv.mpt2units((float)position.getHeight()));
objectAreaInfo.setHeight(height);

int resolution = state.getResolution();
int resolution = paintingState.getResolution();
objectAreaInfo.setHeightRes(resolution);
objectAreaInfo.setWidthRes(resolution);

objectAreaInfo.setRotation(state.getRotation());
objectAreaInfo.setRotation(paintingState.getRotation());

dataObjectInfo.setObjectAreaInfo(objectAreaInfo);


+ 128
- 0
src/java/org/apache/fop/render/afp/AFPImageHandlerGraphics2D.java View File

@@ -0,0 +1,128 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.afp;

import java.awt.geom.AffineTransform;
import java.io.IOException;

import org.apache.fop.afp.AFPDataObjectInfo;
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.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;
import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
import org.apache.xmlgraphics.util.MimeConstants;

/**
* PDFImageHandler implementation which handles Graphics2D images.
*/
public class AFPImageHandlerGraphics2D extends AFPImageHandler {

private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
ImageFlavor.GRAPHICS2D
};

private static final Class[] CLASSES = new Class[] {
ImageGraphics2D.class
};

/** {@inheritDoc} */
public AFPDataObjectInfo generateDataObjectInfo(
AFPRendererImageInfo rendererImageInfo) throws IOException {

AFPRendererContext rendererContext = (AFPRendererContext)rendererImageInfo.getRendererContext();
AFPInfo afpInfo = rendererContext.getInfo();
ImageGraphics2D imageG2D = (ImageGraphics2D)rendererImageInfo.getImage();
Graphics2DImagePainter painter = imageG2D.getGraphics2DImagePainter();

if (afpInfo.paintAsBitmap()) {
int x = afpInfo.getX();
int y = afpInfo.getY();
int width = afpInfo.getWidth();
int height = afpInfo.getHeight();
AFPPaintingState paintingState = afpInfo.getPaintingState();
AFPGraphics2DAdapter g2dAdapter = new AFPGraphics2DAdapter(paintingState);
g2dAdapter.paintImage(painter, rendererContext, x, y, width, height);
return null;
} else {
AFPGraphicsObjectInfo graphicsObjectInfo
= (AFPGraphicsObjectInfo)super.generateDataObjectInfo(rendererImageInfo);

AFPResourceInfo resourceInfo = graphicsObjectInfo.getResourceInfo();
//level not explicitly set/changed so default to inline for GOCA graphic objects
// (due to a bug in the IBM AFP Workbench Viewer (2.04.01.07) - hard copy works just fine)
if (!resourceInfo.levelChanged()) {
resourceInfo.setLevel(new AFPResourceLevel(AFPResourceLevel.INLINE));
}

// set mime type (unsupported by MOD:CA registry)
graphicsObjectInfo.setMimeType(MimeConstants.MIME_AFP_GOCA);

// set g2d
boolean textAsShapes = false;

AFPGraphics2D g2d = afpInfo.createGraphics2D(textAsShapes);

graphicsObjectInfo.setGraphics2D(g2d);

// translate to current location
AFPPaintingState paintingState = afpInfo.getPaintingState();
AffineTransform at = paintingState.getData().getTransform();
g2d.translate(at.getTranslateX(), at.getTranslateY());

// set painter
graphicsObjectInfo.setPainter(painter);

// invert y-axis for GOCA
final int sx = 1;
final int sy = -1;
AFPObjectAreaInfo objectAreaInfo = graphicsObjectInfo.getObjectAreaInfo();
int height = objectAreaInfo.getHeight();
g2d.translate(0, height);
g2d.scale(sx, sy);

return graphicsObjectInfo;
}
}

/** {@inheritDoc} */
public int getPriority() {
return 200;
}

/** {@inheritDoc} */
public Class[] getSupportedImageClasses() {
return CLASSES;
}

/** {@inheritDoc} */
public ImageFlavor[] getSupportedImageFlavors() {
return FLAVORS;
}

/** {@inheritDoc} */
protected AFPDataObjectInfo createDataObjectInfo() {
return new AFPGraphicsObjectInfo();
}
}

src/java/org/apache/fop/render/afp/AFPRawCCITTFaxFactory.java → src/java/org/apache/fop/render/afp/AFPImageHandlerRawCCITTFax.java View File

@@ -24,36 +24,39 @@ import java.io.IOException;
import org.apache.fop.afp.AFPDataObjectInfo;
import org.apache.fop.afp.AFPImageObjectInfo;
import org.apache.fop.afp.AFPObjectAreaInfo;
import org.apache.fop.afp.AFPPaintingState;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;

/**
* An CITT fax image data object info factory
* PDFImageHandler implementation which handles CCITT encoded images (CCITT fax group 3/4).
*/
public class AFPRawCCITTFaxFactory extends AFPDataObjectInfoFactory {

/**
* Main constructor
*
* @param state the AFP painting state
*/
public AFPRawCCITTFaxFactory(AFPPaintingState state) {
super(state);
}
public class AFPImageHandlerRawCCITTFax extends AFPImageHandler {

private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
ImageFlavor.RAW_CCITTFAX,
};

private static final Class[] CLASSES = new Class[] {
ImageRawCCITTFax.class,
};

/** {@inheritDoc} */
public AFPDataObjectInfo create(AFPRendererImageInfo rendererImageInfo) throws IOException {
AFPImageObjectInfo imageObjectInfo = (AFPImageObjectInfo)super.create(rendererImageInfo);
public AFPDataObjectInfo generateDataObjectInfo(
AFPRendererImageInfo rendererImageInfo) throws IOException {
AFPImageObjectInfo imageObjectInfo
= (AFPImageObjectInfo)super.generateDataObjectInfo(rendererImageInfo);

ImageRawCCITTFax ccitt = (ImageRawCCITTFax) rendererImageInfo.img;
ImageRawCCITTFax ccitt = (ImageRawCCITTFax) rendererImageInfo.getImage();
imageObjectInfo.setCompression(ccitt.getCompression());

AFPObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo();
int xresol = (int) (ccitt.getSize().getDpiHorizontal() * 10);
objectAreaInfo.setWidthRes(xresol);
ImageSize imageSize = ccitt.getSize();
int widthRes = (int) (imageSize.getDpiHorizontal() * 10);
objectAreaInfo.setWidthRes(widthRes);

int yresol = (int) (ccitt.getSize().getDpiVertical() * 10);
objectAreaInfo.setHeightRes(yresol);
int heightRes = (int) (imageSize.getDpiVertical() * 10);
objectAreaInfo.setHeightRes(heightRes);

imageObjectInfo.setInputStream(ccitt.createInputStream());

@@ -64,4 +67,20 @@ public class AFPRawCCITTFaxFactory extends AFPDataObjectInfoFactory {
protected AFPDataObjectInfo createDataObjectInfo() {
return new AFPImageObjectInfo();
}
}

/** {@inheritDoc} */
public int getPriority() {
return 400;
}

/** {@inheritDoc} */
public Class[] getSupportedImageClasses() {
return CLASSES;
}

/** {@inheritDoc} */
public ImageFlavor[] getSupportedImageFlavors() {
return FLAVORS;
}

}

src/java/org/apache/fop/render/afp/AFPImageRawStreamFactory.java → src/java/org/apache/fop/render/afp/AFPImageHandlerRawStream.java View File

@@ -25,35 +25,48 @@ import java.io.InputStream;
import org.apache.fop.afp.AFPDataObjectInfo;
import org.apache.fop.afp.AFPObjectAreaInfo;
import org.apache.fop.afp.AFPPaintingState;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
import org.apache.xmlgraphics.image.loader.impl.ImageRawEPS;
import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
import org.apache.xmlgraphics.image.loader.impl.ImageRawStream;

/**
* A raw stream image data object info factory
* AFPImageHandler implementation which handles raw stream images.
*/
public class AFPImageRawStreamFactory extends AFPDataObjectInfoFactory {

/**
* Main constructor
*
* @param state the AFP painting state
*/
public AFPImageRawStreamFactory(AFPPaintingState state) {
super(state);
}
public class AFPImageHandlerRawStream extends AFPImageHandler {

private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
ImageFlavor.RAW_JPEG,
ImageFlavor.RAW_CCITTFAX,
ImageFlavor.RAW_EPS,
};

private static final Class[] CLASSES = new Class[] {
ImageRawJPEG.class,
ImageRawCCITTFax.class,
ImageRawEPS.class
};

/** {@inheritDoc} */
public AFPDataObjectInfo create(AFPRendererImageInfo rendererImageInfo) throws IOException {
AFPDataObjectInfo dataObjectInfo = super.create(rendererImageInfo);
public AFPDataObjectInfo generateDataObjectInfo(
AFPRendererImageInfo rendererImageInfo) throws IOException {
AFPDataObjectInfo dataObjectInfo = super.generateDataObjectInfo(rendererImageInfo);
ImageInfo imageInfo = rendererImageInfo.getImageInfo();
String mimeType = imageInfo.getMimeType();
if (mimeType != null) {
dataObjectInfo.setMimeType(mimeType);
}
ImageRawStream rawStream = (ImageRawStream) rendererImageInfo.getImage();
int resolution = state.getResolution();

AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo();

AFPRendererContext rendererContext
= (AFPRendererContext)rendererImageInfo.getRendererContext();
AFPInfo afpInfo = rendererContext.getInfo();
AFPPaintingState paintingState = afpInfo.getPaintingState();
int resolution = paintingState.getResolution();
objectAreaInfo.setWidthRes(resolution);
objectAreaInfo.setHeightRes(resolution);

@@ -68,6 +81,21 @@ public class AFPImageRawStreamFactory extends AFPDataObjectInfoFactory {
return dataObjectInfo;
}

/** {@inheritDoc} */
public int getPriority() {
return 100;
}

/** {@inheritDoc} */
public Class[] getSupportedImageClasses() {
return CLASSES;
}

/** {@inheritDoc} */
public ImageFlavor[] getSupportedImageFlavors() {
return FLAVORS;
}

/** {@inheritDoc} */
protected AFPDataObjectInfo createDataObjectInfo() {
return new AFPDataObjectInfo();

+ 42
- 0
src/java/org/apache/fop/render/afp/AFPImageHandlerRegistry.java View File

@@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.afp;

import org.apache.fop.render.AbstractImageHandlerRegistry;

/**
* This class holds references to various image handlers used by the AFP renderer. It also
* supports automatic discovery of additional handlers available through
* the class path.
*/
public class AFPImageHandlerRegistry extends AbstractImageHandlerRegistry {

/**
* Main constructor
*/
public AFPImageHandlerRegistry() {
}

/** {@inheritDoc} */
public Class getHandlerClass() {
return AFPImageHandler.class;
}

}

src/java/org/apache/fop/render/afp/AFPImageRenderedFactory.java → src/java/org/apache/fop/render/afp/AFPImageHandlerRenderedImage.java View File

@@ -27,33 +27,41 @@ import org.apache.fop.afp.AFPDataObjectInfo;
import org.apache.fop.afp.AFPImageObjectInfo;
import org.apache.fop.afp.AFPObjectAreaInfo;
import org.apache.fop.afp.AFPPaintingState;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.ImageBuffered;
import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
import org.apache.xmlgraphics.ps.ImageEncodingHelper;
import org.apache.xmlgraphics.util.MimeConstants;

/**
* A buffered image data object info factory
* PDFImageHandler implementation which handles RenderedImage instances.
*/
public class AFPImageRenderedFactory extends AFPDataObjectInfoFactory {

/**
* Main constructor
*
* @param state the AFP painting state
*/
public AFPImageRenderedFactory(AFPPaintingState state) {
super(state);
}
public class AFPImageHandlerRenderedImage extends AFPImageHandler {

private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
ImageFlavor.BUFFERED_IMAGE,
ImageFlavor.RENDERED_IMAGE
};

private static final Class[] CLASSES = new Class[] {
ImageBuffered.class,
ImageRendered.class
};

/** {@inheritDoc} */
public AFPDataObjectInfo create(AFPRendererImageInfo rendererImageInfo) throws IOException {
public AFPDataObjectInfo generateDataObjectInfo(
AFPRendererImageInfo rendererImageInfo) throws IOException {
AFPImageObjectInfo imageObjectInfo
= (AFPImageObjectInfo)super.create(rendererImageInfo);
= (AFPImageObjectInfo)super.generateDataObjectInfo(rendererImageInfo);

imageObjectInfo.setMimeType(MimeConstants.MIME_AFP_IOCA_FS45);

AFPObjectAreaInfo objectAreaInfo = imageObjectInfo.getObjectAreaInfo();
int resolution = state.getResolution();
AFPRendererContext rendererContext
= (AFPRendererContext)rendererImageInfo.getRendererContext();
AFPInfo afpInfo = rendererContext.getInfo();
AFPPaintingState paintingState = afpInfo.getPaintingState();
int resolution = paintingState.getResolution();
objectAreaInfo.setWidthRes(resolution);
objectAreaInfo.setHeightRes(resolution);

@@ -70,13 +78,13 @@ public class AFPImageRenderedFactory extends AFPDataObjectInfoFactory {
ImageEncodingHelper.encodeRenderedImageAsRGB(renderedImage, baos);
byte[] imageData = baos.toByteArray();

boolean colorImages = state.isColorImages();
boolean colorImages = paintingState.isColorImages();
imageObjectInfo.setColor(colorImages);

// convert to grayscale
if (!colorImages) {
baos.reset();
int bitsPerPixel = state.getBitsPerPixel();
int bitsPerPixel = paintingState.getBitsPerPixel();
imageObjectInfo.setBitsPerPixel(bitsPerPixel);
ImageEncodingHelper.encodeRGBAsGrayScale(
imageData, dataWidth, dataHeight, bitsPerPixel, baos);
@@ -91,4 +99,20 @@ public class AFPImageRenderedFactory extends AFPDataObjectInfoFactory {
protected AFPDataObjectInfo createDataObjectInfo() {
return new AFPImageObjectInfo();
}

/** {@inheritDoc} */
public int getPriority() {
return 300;
}

/** {@inheritDoc} */
public Class[] getSupportedImageClasses() {
return CLASSES;
}

/** {@inheritDoc} */
public ImageFlavor[] getSupportedImageFlavors() {
return FLAVORS;
}

}

+ 82
- 0
src/java/org/apache/fop/render/afp/AFPImageHandlerXML.java View File

@@ -0,0 +1,82 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.afp;

import java.awt.Point;
import java.awt.Rectangle;
import java.io.IOException;
import java.util.Map;

import org.apache.fop.afp.AFPDataObjectInfo;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.RendererContextConstants;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
import org.w3c.dom.Document;

/**
* PDFImageHandler implementation which handles XML-based images.
*/
public class AFPImageHandlerXML extends AFPImageHandler {

private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
ImageFlavor.XML_DOM,
};

private static final Class[] CLASSES = new Class[] {
ImageXMLDOM.class,
};

/** {@inheritDoc} */
public AFPDataObjectInfo generateDataObjectInfo(RendererContext context, Image image,
Point origin, Rectangle pos)
throws IOException {
AFPRenderer renderer = (AFPRenderer)context.getRenderer();
ImageXMLDOM imgXML = (ImageXMLDOM)image;
Document doc = imgXML.getDocument();
String ns = imgXML.getRootNamespace();
Map foreignAttributes = (Map)context.getProperty(
RendererContextConstants.FOREIGN_ATTRIBUTES);
renderer.renderDocument(doc, ns, pos, foreignAttributes);
return null;
}

/** {@inheritDoc} */
public int getPriority() {
return 400;
}

/** {@inheritDoc} */
public Class[] getSupportedImageClasses() {
return CLASSES;
}

/** {@inheritDoc} */
public ImageFlavor[] getSupportedImageFlavors() {
return FLAVORS;
}

/** {@inheritDoc} */
protected AFPDataObjectInfo createDataObjectInfo() {
return null;
}

}

+ 22
- 8
src/java/org/apache/fop/render/afp/AFPInfo.java View File

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

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.fop.afp.AFPGraphics2D;
import org.apache.fop.afp.AFPPaintingState;
import org.apache.fop.afp.AFPResourceInfo;
import org.apache.fop.afp.AFPResourceManager;
@@ -47,18 +48,18 @@ public final class AFPInfo {
/** see AFP_FONT_INFO */
private FontInfo fontInfo;

/** See AFP_STATE */
private AFPPaintingState state;
/** See AFP_PAINTING_STATE */
private AFPPaintingState paintingState;

/** See AFP_RESOURCE_MANAGER */
private AFPResourceManager resourceManager;

/** See AFP_RESOURCE_INFO */
private AFPResourceInfo resourceInfo;

/** true if SVG should be rendered as a bitmap instead of natively */
private boolean paintAsBitmap;

/** the resource information */
private AFPResourceInfo resourceInfo;

/**
* Returns the width.
*
@@ -128,7 +129,7 @@ public final class AFPInfo {
* @return the current AFP state
*/
public AFPPaintingState getPaintingState() {
return this.state;
return this.paintingState;
}

/**
@@ -217,7 +218,7 @@ public final class AFPInfo {
* @param state the AFP state
*/
public void setPaintingState(AFPPaintingState state) {
this.state = state;
this.paintingState = state;
}

/**
@@ -278,6 +279,19 @@ public final class AFPInfo {
return resourceInfo;
}

/**
* Creates an AFPGraphics2D implementation
*
* @param textAsShapes true when text is painted as shapes
* @return a newly created AFPGraphics2D
*/
public AFPGraphics2D createGraphics2D(boolean textAsShapes) {
AFPGraphics2D g2d = new AFPGraphics2D(
textAsShapes, paintingState, resourceManager, resourceInfo, fontInfo);
g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
return g2d;
}

/** {@inheritDoc} */
public String toString() {
return "AFPInfo{width=" + width
@@ -287,7 +301,7 @@ public final class AFPInfo {
+ ", cfg=" + handlerConfiguration
+ ", fontInfo=" + fontInfo
+ ", resourceManager=" + resourceManager
+ ", state=" + state
+ ", paintingState=" + paintingState
+ ", paintAsBitmap=" + paintAsBitmap
+ ", resourceInfo=" + resourceInfo
+ "}";

+ 63
- 65
src/java/org/apache/fop/render/afp/AFPRenderer.java View File

@@ -36,7 +36,6 @@ import java.util.Map;
import org.apache.fop.afp.AFPBorderPainter;
import org.apache.fop.afp.AFPConstants;
import org.apache.fop.afp.AFPDataObjectInfo;
import org.apache.fop.afp.AFPPageFonts;
import org.apache.fop.afp.AFPPaintingState;
import org.apache.fop.afp.AFPRectanglePainter;
import org.apache.fop.afp.AFPResourceManager;
@@ -47,6 +46,7 @@ import org.apache.fop.afp.RectanglePaintInfo;
import org.apache.fop.afp.fonts.AFPFont;
import org.apache.fop.afp.fonts.AFPFontAttributes;
import org.apache.fop.afp.fonts.AFPFontCollection;
import org.apache.fop.afp.fonts.AFPPageFonts;
import org.apache.fop.afp.modca.DataStream;
import org.apache.fop.afp.modca.PageObject;
import org.apache.fop.apps.FOPException;
@@ -77,7 +77,6 @@ import org.apache.xmlgraphics.image.loader.ImageFlavor;
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.impl.ImageXMLDOM;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.xmlgraphics.ps.ImageEncodingHelper;

@@ -137,35 +136,33 @@ import org.apache.xmlgraphics.ps.ImageEncodingHelper;
*/
public class AFPRenderer extends AbstractPathOrientedRenderer {

/** Normal PDF resolution (72dpi) */
public static final int NORMAL_AFP_RESOLUTION = 72;

private static final int X = 0;
private static final int Y = 1;

/** resource manager */
/** the resource manager */
private AFPResourceManager resourceManager;

/** painting state */
/** the painting state */
private final AFPPaintingState paintingState;

/** unit converter */
private final AFPUnitConverter unitConv;

/** line painter */
/** the line painter */
private AFPBorderPainter borderPainter;

/** The map of page segments */
private final Map/*<String,String>*/pageSegmentMap = new java.util.HashMap/*<String,String>*/();
/** the map of page segments */
private final Map/*<String,String>*/pageSegmentMap
= new java.util.HashMap/*<String,String>*/();

/** The map of saved incomplete pages */
/** the map of saved incomplete pages */
private final Map pages = new java.util.HashMap/*<PageViewport,PageObject>*/();

/** the afp datastream */
/** the AFP datastream */
private DataStream dataStream;

/** data object information factory */
private final AFPDataObjectInfoProvider dataObjectInfoProvider;
/** the image handler registry */
private final AFPImageHandlerRegistry imageHandlerRegistry;

private AFPRectanglePainter rectanglePainter;

@@ -176,7 +173,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
super();
this.resourceManager = new AFPResourceManager();
this.paintingState = new AFPPaintingState();
this.dataObjectInfoProvider = new AFPDataObjectInfoProvider(paintingState);
this.imageHandlerRegistry = new AFPImageHandlerRegistry();
this.unitConv = paintingState.getUnitConverter();
}

@@ -252,7 +249,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {

/** {@inheritDoc} */
public Graphics2DAdapter getGraphics2DAdapter() {
return new AFPGraphics2DAdapter(this);
return new AFPGraphics2DAdapter(paintingState);
}

/** {@inheritDoc} */
@@ -379,6 +376,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
rectanglePainter.paint(rectanglePaintInfo);
}

/** {@inheritDoc} */
protected RendererContext instantiateRendererContext() {
return new AFPRendererContext(this, getMimeType());
}

/** {@inheritDoc} */
protected RendererContext createRendererContext(int x, int y, int width,
int height, Map foreignAttributes) {
@@ -394,25 +396,34 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
}

private static final ImageFlavor[] NATIVE_FLAVORS = new ImageFlavor[] {
ImageFlavor.XML_DOM,
/*ImageFlavor.RAW_PNG, */ // PNG not natively supported in AFP
ImageFlavor.XML_DOM, ImageFlavor.RAW_JPEG, ImageFlavor.RAW_CCITTFAX, ImageFlavor.RAW_EPS,
ImageFlavor.RAW_JPEG, ImageFlavor.RAW_CCITTFAX, ImageFlavor.RAW_EPS,
ImageFlavor.GRAPHICS2D, ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE };

private static final ImageFlavor[] FLAVORS = new ImageFlavor[] {
ImageFlavor.XML_DOM, ImageFlavor.GRAPHICS2D, ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE };
ImageFlavor.XML_DOM,
ImageFlavor.GRAPHICS2D, ImageFlavor.BUFFERED_IMAGE, ImageFlavor.RENDERED_IMAGE };

/** {@inheritDoc} */
public void drawImage(String uri, Rectangle2D pos, Map foreignAttributes) {
uri = URISpecification.getURL(uri);
paintingState.setImageUri(uri);
Rectangle posInt = new Rectangle((int) pos.getX(), (int) pos.getY(),
(int) pos.getWidth(), (int) pos.getHeight());

Point origin = new Point(currentIPPosition, currentBPPosition);
Rectangle posInt = new Rectangle(
(int)Math.round(pos.getX()),
(int)Math.round(pos.getY()),
(int)Math.round(pos.getWidth()),
(int)Math.round(pos.getHeight())
);
int x = origin.x + posInt.x;
int y = origin.y + posInt.y;

String name = (String)pageSegmentMap.get(uri);
int x = currentIPPosition + posInt.x;
int y = currentBPPosition + posInt.y;
float[] srcPts = {x, y};
int[] coords = unitConv.mpts2units(srcPts);
if (name != null) {
float[] srcPts = {x, y};
int[] coords = unitConv.mpts2units(srcPts);
dataStream.createIncludePageSegment(name, coords[X], coords[Y]);
} else {
ImageManager manager = userAgent.getFactory().getImageManager();
@@ -425,41 +436,40 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
// Only now fully load/prepare the image
Map hints = ImageUtil.getDefaultHints(sessionContext);

ImageFlavor[] flavors = paintingState.isNativeImages() ? NATIVE_FLAVORS : FLAVORS;
boolean nativeImagesSupported = paintingState.isNativeImagesSupported();
ImageFlavor[] flavors = nativeImagesSupported ? NATIVE_FLAVORS : FLAVORS;

// Load image
org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
info, flavors, hints, sessionContext);

Point origin = new Point(currentIPPosition, currentBPPosition);
AFPDataObjectInfoFactory factory = dataObjectInfoProvider.getFactory(img);
if (factory != null) {
AFPRendererImageInfo afpImageInfo
= new AFPRendererImageInfo(uri, pos, origin, info, img, foreignAttributes);
if (factory instanceof AFPImageGraphics2DFactory) {
RendererContext rendererContext = createRendererContext(
x, y, posInt.width, posInt.height, foreignAttributes);
afpImageInfo.setRendererContext(rendererContext);
AFPGraphics2DAdapter g2dAdapter
= (AFPGraphics2DAdapter)getGraphics2DAdapter();
afpImageInfo.setGraphics2DAdapter(g2dAdapter);
}
// Handle image
AFPImageHandler imageHandler
= (AFPImageHandler)imageHandlerRegistry.getHandler(img);
if (imageHandler != null) {
RendererContext rendererContext = createRendererContext(
x, y, posInt.width, posInt.height, foreignAttributes);
AFPRendererImageInfo rendererImageInfo = new AFPRendererImageInfo(
uri, pos, origin, info, img, rendererContext, foreignAttributes);
AFPDataObjectInfo dataObjectInfo = null;
try {
dataObjectInfo = factory.create(afpImageInfo);
dataObjectInfo = imageHandler.generateDataObjectInfo(rendererImageInfo);
// Create image
if (dataObjectInfo != null) {
resourceManager.createObject(dataObjectInfo);
}
} catch (IOException ioe) {
ResourceEventProducer eventProducer
= ResourceEventProducer.Provider.get(userAgent.getEventBroadcaster());
eventProducer.imageWritingError(this, ioe);
throw ioe;
}
resourceManager.createObject(dataObjectInfo);
} else if (img instanceof ImageXMLDOM) {
ImageXMLDOM imgXML = (ImageXMLDOM) img;
renderDocument(imgXML.getDocument(), imgXML.getRootNamespace(),
posInt, foreignAttributes);
} else {
throw new UnsupportedOperationException(
"Unsupported image type: " + img);
"No AFPImageHandler available for image: "
+ info + " (" + img.getClass().getName() + ")");
}

} catch (ImageException ie) {
ResourceEventProducer eventProducer = ResourceEventProducer.Provider
.get(userAgent.getEventBroadcaster());
@@ -546,29 +556,17 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
public void renderText(TextArea text) {
renderInlineAreaBackAndBorders(text);

// set font size
int fontSize = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
paintingState.setFontSize(fontSize);

String name = getInternalFontNameForArea(text);
AFPFont font = (AFPFont)fontInfo.getFonts().get(name);

// Set letterSpacing
// float ls = fs.getLetterSpacing() / this.currentFontSize;

// Create an AFPFontAttributes object from the current font details
AFPFontAttributes fontAttributes
= new AFPFontAttributes(name, font, fontSize);

// register font as necessary
String internalFontName = getInternalFontNameForArea(text);
AFPFont font = (AFPFont)fontInfo.getFonts().get(internalFontName);
AFPPageFonts pageFonts = paintingState.getPageFonts();
if (!pageFonts.containsKey(fontAttributes.getFontKey())) {
// Font not found on current page, so add the new one
fontAttributes.setFontReference(paintingState.incrementPageFontCount());
pageFonts.put(fontAttributes.getFontKey(), fontAttributes);
} else {
// Use the previously stored font attributes
fontAttributes = (AFPFontAttributes)pageFonts.get(fontAttributes.getFontKey());
}
AFPFontAttributes fontAttributes = pageFonts.registerFont(internalFontName, font, fontSize);

// create text data info
AFPTextDataInfo textDataInfo = new AFPTextDataInfo();

int fontReference = fontAttributes.getFontReference();
@@ -765,8 +763,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
* @param nativeImages
* native image support
*/
public void setNativeImages(boolean nativeImages) {
paintingState.setNativeImages(nativeImages);
public void setNativeImagesSupported(boolean nativeImages) {
paintingState.setNativeImagesSupported(nativeImages);
}

/**

+ 18
- 16
src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java View File

@@ -213,6 +213,12 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {
return fontList;
}

/** images are converted to grayscale bitmapped IOCA */
private static final String IMAGES_MODE_GRAYSCALE = "b+w";

/** images are converted to color bitmapped IOCA */
private static final String IMAGES_MODE_COLOR = "color";

/**
* Configure the AFP renderer.
*
@@ -234,15 +240,21 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {

// image information
Configuration imagesCfg = cfg.getChild("images");
if (!"color".equalsIgnoreCase(imagesCfg.getAttribute("mode", "b+w"))) {
afpRenderer.setColorImages(false);
afpRenderer.setBitsPerPixel(imagesCfg.getAttributeAsInteger("bits-per-pixel", 8));
} else {
// default to grayscale images
String imagesMode = imagesCfg.getAttribute("mode", IMAGES_MODE_GRAYSCALE);
if (IMAGES_MODE_COLOR.equals(imagesMode)) {
afpRenderer.setColorImages(true);
} else {
afpRenderer.setColorImages(false);
// default to 8 bits per pixel
int bitsPerPixel = imagesCfg.getAttributeAsInteger("bits-per-pixel", 8);
afpRenderer.setBitsPerPixel(bitsPerPixel);
}

// images are embedded directly without conversion to bitmapped IOCA
afpRenderer.setNativeImages(imagesCfg.getAttributeAsBoolean("native", false));
// native image support
boolean nativeImageSupport = imagesCfg.getAttributeAsBoolean("native", false);
afpRenderer.setNativeImagesSupported(nativeImageSupport);

// renderer resolution
Configuration rendererResolutionCfg = cfg.getChild("renderer-resolution", false);
@@ -269,16 +281,6 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {
+ resourceGroupDest + "'");
}
}

// TODO: provide support for different MO:DCA interchange sets
// the MO:DCA interchange set in use (defaults to MO:DCA-L)
// Configuration modcaCfg = cfg.getChild("modca", false);
// if (modcaCfg != null) {
// String interchangeSetString = cfg.getAttribute(
// "interchange-set", InterchangeSet.MODCA_PRESENTATION_INTERCHANGE_SET_2);
// InterchangeSet interchangeSet = InterchangeSet.valueOf(interchangeSetString);
// afpRenderer.getAFPDataStream().setInterchangeSet(interchangeSet);
// }
}
}
}

+ 83
- 0
src/java/org/apache/fop/render/afp/AFPRendererContext.java View File

@@ -0,0 +1,83 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.afp;

import java.util.Map;

import org.apache.avalon.framework.configuration.Configuration;
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.render.AbstractRenderer;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.RendererContextConstants;

public class AFPRendererContext extends RendererContext {

/**
* Main constructor
*
* @param renderer the current renderer
* @param mime the MIME type of the output that's generated.
*/
public AFPRendererContext(AbstractRenderer renderer, String mime) {
super(renderer, mime);
}

/**
* Returns a new AFPInfo for this renderer context
*
* @return an AFPInfo for this renderer context
*/
public AFPInfo getInfo() {
AFPInfo info = new AFPInfo();
info.setWidth(((Integer)getProperty(RendererContextConstants.WIDTH)).intValue());
info.setHeight(((Integer)getProperty(RendererContextConstants.HEIGHT)).intValue());
info.setX(((Integer)getProperty(RendererContextConstants.XPOS)).intValue());
info.setY(((Integer)getProperty(RendererContextConstants.YPOS)).intValue());
info.setHandlerConfiguration((Configuration)getProperty(
RendererContextConstants.HANDLER_CONFIGURATION));
info.setFontInfo((org.apache.fop.fonts.FontInfo)getProperty(
AFPRendererContextConstants.AFP_FONT_INFO));
info.setPaintingState((AFPPaintingState)getProperty(
AFPRendererContextConstants.AFP_PAINTING_STATE));
info.setResourceManager(((AFPResourceManager)getProperty(
AFPRendererContextConstants.AFP_RESOURCE_MANAGER)));

Map foreignAttributes = (Map)getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES);
if (foreignAttributes != null) {
String conversionMode = (String)foreignAttributes.get(CONVERSION_MODE);
boolean paintAsBitmap = BITMAP.equalsIgnoreCase(conversionMode);
info.setPaintAsBitmap(paintAsBitmap);

AFPForeignAttributeReader foreignAttributeReader
= new AFPForeignAttributeReader();
AFPResourceInfo resourceInfo
= foreignAttributeReader.getResourceInfo(foreignAttributes);
// default to inline level if painted as GOCA
if (!resourceInfo.levelChanged() && !paintAsBitmap) {
resourceInfo.setLevel(new AFPResourceLevel(AFPResourceLevel.INLINE));
}
info.setResourceInfo(resourceInfo);
}
return info;
}
}

+ 3
- 22
src/java/org/apache/fop/render/afp/AFPRendererImageInfo.java View File

@@ -50,9 +50,6 @@ public class AFPRendererImageInfo {
/** the image */
protected final Image img;

/** the AFP graphics 2d adapter */
protected AFPGraphics2DAdapter g2dAdapter;

/** the renderer context */
protected RendererContext rendererContext;

@@ -64,15 +61,17 @@ public class AFPRendererImageInfo {
* @param origin the current position
* @param info the image info
* @param img the image
* @param rendererContext the renderer context
* @param foreignAttributes the foreign attributes
*/
public AFPRendererImageInfo(String uri, Rectangle2D pos, Point origin,
ImageInfo info, Image img, Map foreignAttributes) {
ImageInfo info, Image img, RendererContext rendererContext, Map foreignAttributes) {
this.uri = uri;
this.pos = pos;
this.origin = origin;
this.info = info;
this.img = img;
this.rendererContext = rendererContext;
this.foreignAttributes = foreignAttributes;
}

@@ -85,15 +84,6 @@ public class AFPRendererImageInfo {
this.rendererContext = rendererContext;
}

/**
* Sets the graphics 2d adapter
*
* @param adapter the graphics 2d adapter
*/
public void setGraphics2DAdapter(AFPGraphics2DAdapter adapter) {
this.g2dAdapter = adapter;
}

/**
* Returns the image info
*
@@ -112,15 +102,6 @@ public class AFPRendererImageInfo {
return this.img;
}

/**
* Returns the graphics 2D adapter
*
* @return the graphics 2D adapter
*/
public AFPGraphics2DAdapter getGraphics2DAdapter() {
return this.g2dAdapter;
}

/**
* Returns the renderer context
*

+ 93
- 137
src/java/org/apache/fop/render/afp/AFPSVGHandler.java View File

@@ -22,39 +22,32 @@ 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;
import java.util.Map;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.BridgeException;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.dom.AbstractDocument;
import org.apache.batik.dom.svg.SVGDOMImplementation;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.fop.afp.AFPForeignAttributeReader;
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.AFPTextElementBridge;
import org.apache.fop.afp.AFPTextHandler;
import org.apache.fop.afp.AFPTextPainter;
import org.apache.fop.afp.AFPUnitConverter;
import org.apache.fop.afp.Graphics2DImagePainterGOCA;
import org.apache.fop.afp.svg.AFPBridgeContext;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fonts.FontInfo;
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.render.RendererContext.RendererContextWrapper;
import org.apache.fop.svg.SVGEventProducer;
import org.apache.fop.svg.SVGUserAgent;
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;
import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
import org.apache.xmlgraphics.util.MimeConstants;
import org.w3c.dom.Document;

/**
@@ -74,177 +67,138 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler {
}
}

/**
* Get the AFP information from the render context.
*
* @param context the renderer context
* @return the AFP information retrieved from the context
*/
public static AFPInfo getAFPInfo(RendererContext context) {
AFPInfo afpi = new AFPInfo();
afpi.setWidth(((Integer)context.getProperty(WIDTH)).intValue());
afpi.setHeight(((Integer)context.getProperty(HEIGHT)).intValue());
afpi.setX(((Integer)context.getProperty(XPOS)).intValue());
afpi.setY(((Integer)context.getProperty(YPOS)).intValue());
afpi.setHandlerConfiguration((Configuration)context.getProperty(HANDLER_CONFIGURATION));
afpi.setFontInfo((org.apache.fop.fonts.FontInfo)context.getProperty(
AFPRendererContextConstants.AFP_FONT_INFO));
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);
// default to inline level if painted as GOCA
if (!resourceInfo.levelChanged() && !paintAsBitmap) {
resourceInfo.setLevel(new AFPResourceLevel(AFPResourceLevel.INLINE));
}
afpi.setResourceInfo(resourceInfo);
}
return afpi;
}

private static final int X = 0;
private static final int Y = 1;

/**
* Render the SVG document.
*
* @param context the renderer context
* @param rendererContext the renderer context
* @param doc the SVG document
* @throws IOException In case of an I/O error while painting the image
*/
protected void renderSVGDocument(final RendererContext context,
protected void renderSVGDocument(final RendererContext rendererContext,
final Document doc) throws IOException {

AFPInfo afpInfo = getAFPInfo(context);
AFPRendererContext afpRendererContext = (AFPRendererContext)rendererContext;
AFPInfo afpInfo = afpRendererContext.getInfo();

this.paintAsBitmap = afpInfo.paintAsBitmap();

FOUserAgent userAgent = rendererContext.getUserAgent();

// fallback paint as bitmap
String uri = getDocumentURI(doc);
if (paintAsBitmap) {
try {
super.renderSVGDocument(context, doc);
super.renderSVGDocument(rendererContext, doc);
} catch (IOException ioe) {
SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
context.getUserAgent().getEventBroadcaster());
eventProducer.svgRenderingError(this, ioe, getDocumentURI(doc));
userAgent.getEventBroadcaster());
eventProducer.svgRenderingError(this, ioe, uri);
}
return;
}

String uri = ((AbstractDocument)doc).getDocumentURI();
AFPPaintingState paintingState = afpInfo.getPaintingState();
// Create a new AFPGraphics2D
final boolean textAsShapes = false;
AFPGraphics2D g2d = afpInfo.createGraphics2D(textAsShapes);

AFPPaintingState paintingState = g2d.getPaintingState();
paintingState.setImageUri(uri);

// Create an AFPBridgeContext
BridgeContext bridgeContext = createBridgeContext(userAgent, g2d);

// Build the SVG DOM and provide the painter with it
GraphicsNode root = buildGraphicsNode(userAgent, bridgeContext, doc);

// Create Graphics2DImagePainter
final RendererContextWrapper wrappedContext
= RendererContext.wrapRendererContext(rendererContext);
Dimension imageSize = getImageSize(wrappedContext);
Graphics2DImagePainter painter
= createGrapics2DImagePainter(bridgeContext, root, imageSize);

// Create AFPObjectAreaInfo
RendererContextWrapper rctx = RendererContext.wrapRendererContext(rendererContext);
int x = rctx.getCurrentXPosition();
int y = rctx.getCurrentYPosition();
int width = afpInfo.getWidth();
int height = afpInfo.getHeight();
int resolution = afpInfo.getResolution();

paintingState.push(); // save

AFPObjectAreaInfo objectAreaInfo
= createObjectAreaInfo(paintingState, x, y, width, height, resolution);

// Create AFPGraphicsObjectInfo
AFPResourceInfo resourceInfo = afpInfo.getResourceInfo();
AFPGraphicsObjectInfo graphicsObjectInfo = createGraphicsObjectInfo(
paintingState, painter, userAgent, resourceInfo, g2d);
graphicsObjectInfo.setObjectAreaInfo(objectAreaInfo);

// Create the GOCA GraphicsObject in the DataStream
AFPResourceManager resourceManager = afpInfo.getResourceManager();
resourceManager.createObject(graphicsObjectInfo);

paintingState.pop(); // resume
}

private AFPObjectAreaInfo createObjectAreaInfo(AFPPaintingState paintingState,
int x, int y, int width, int height, int resolution) {
// set the data object parameters
AFPObjectAreaInfo objectAreaInfo = new AFPObjectAreaInfo();

RendererContextWrapper rctx = RendererContext.wrapRendererContext(context);
int currx = rctx.getCurrentXPosition();
int curry = rctx.getCurrentYPosition();
float[] srcPts = {currx, curry};

AFPUnitConverter unitConv = paintingState.getUnitConverter();
int[] coords = unitConv.mpts2units(srcPts);
objectAreaInfo.setX(coords[X]);
objectAreaInfo.setY(coords[Y]);
AffineTransform at = paintingState.getData().getTransform();
at.translate(x, y);
objectAreaInfo.setX((int)Math.round(at.getTranslateX()));
objectAreaInfo.setY((int)Math.round(at.getTranslateY()));

int resolution = afpInfo.getResolution();
objectAreaInfo.setWidthRes(resolution);
objectAreaInfo.setHeightRes(resolution);

int width = Math.round(unitConv.mpt2units(afpInfo.getWidth()));
objectAreaInfo.setWidth(width);

int height = Math.round(unitConv.mpt2units(afpInfo.getHeight()));
objectAreaInfo.setHeight(height);
AFPUnitConverter unitConv = paintingState.getUnitConverter();
objectAreaInfo.setWidth(Math.round(unitConv.mpt2units(width)));
objectAreaInfo.setHeight(Math.round(unitConv.mpt2units(height)));

int rotation = paintingState.getRotation();
objectAreaInfo.setRotation(rotation);

AFPGraphicsObjectInfo graphicsObjectInfo = new AFPGraphicsObjectInfo();
graphicsObjectInfo.setUri(uri);
return objectAreaInfo;
}

// Configure Graphics2D implementation
final boolean textAsShapes = false;
AFPGraphics2D g2d = new AFPGraphics2D(textAsShapes);
private AFPGraphicsObjectInfo createGraphicsObjectInfo(AFPPaintingState paintingState, Graphics2DImagePainter painter,
FOUserAgent userAgent, AFPResourceInfo resourceInfo, AFPGraphics2D g2d) {
AFPGraphicsObjectInfo graphicsObjectInfo = new AFPGraphicsObjectInfo();

g2d.setPaintingState(paintingState);
String uri = paintingState.getImageUri();
graphicsObjectInfo.setUri(uri);

AFPResourceManager resourceManager = afpInfo.getResourceManager();
g2d.setResourceManager(resourceManager);
graphicsObjectInfo.setMimeType(MimeConstants.MIME_AFP_GOCA);

AFPResourceInfo resourceInfo = afpInfo.getResourceInfo();
g2d.setResourceInfo(resourceInfo);
graphicsObjectInfo.setResourceInfo(resourceInfo);

g2d.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());

FontInfo fontInfo = afpInfo.getFontInfo();
g2d.setFontInfo(fontInfo);

// Configure GraphicsObjectPainter with the Graphics2D implementation
GraphicsObjectPainterAFP painter = new GraphicsObjectPainterAFP(g2d);
(graphicsObjectInfo).setPainter(painter);
graphicsObjectInfo.setPainter(painter);

// Controls whether text painted by Batik is generated using text or path operations
SVGUserAgent svgUserAgent
= new SVGUserAgent(context.getUserAgent(), new AffineTransform());
BridgeContext ctx = new BridgeContext(svgUserAgent);
if (!afpInfo.strokeText()) {
AFPTextHandler textHandler = new AFPTextHandler(g2d);
g2d.setCustomTextHandler(textHandler);
AFPTextPainter textPainter = new AFPTextPainter(textHandler);
ctx.setTextPainter(textPainter);
AFPTextElementBridge tBridge = new AFPTextElementBridge(textPainter);
ctx.putBridge(tBridge);
}
// Set the afp graphics 2d implementation
graphicsObjectInfo.setGraphics2D(g2d);

// Build the SVG DOM and provide the painter with it
GraphicsNode root;
GVTBuilder builder = new GVTBuilder();
try {
root = builder.build(ctx, doc);
painter.setGraphicsNode(root);
} catch (BridgeException e) {
SVGEventProducer eventProducer = SVGEventProducer.Provider.get(
context.getUserAgent().getEventBroadcaster());
eventProducer.svgNotBuilt(this, e, uri);
return;
}
return graphicsObjectInfo;
}

// convert to afp inches
Dimension2D dim = ctx.getDocumentSize();
double w = dim.getWidth() * 1000f;
double h = dim.getHeight() * 1000f;
double wx = (afpInfo.getWidth() / w);
double hx = (afpInfo.getHeight() / h);
double scaleX = unitConv.pt2units((float)wx);
double scaleY = unitConv.pt2units((float)hx);
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, 0, yOffset);
g2d.setTransform(trans);
public static BridgeContext createBridgeContext(FOUserAgent userAgent, AFPGraphics2D g2d) {
ImageManager imageManager = userAgent.getFactory().getImageManager();

// Set the afp graphics 2d implementation
graphicsObjectInfo.setGraphics2D(g2d);
SVGUserAgent svgUserAgent
= new SVGUserAgent(userAgent, new AffineTransform());

// Set the object area info
graphicsObjectInfo.setObjectAreaInfo(objectAreaInfo);
ImageSessionContext imageSessionContext = userAgent.getImageSessionContext();

// Create the graphics object
resourceManager.createObject(graphicsObjectInfo);
FontInfo fontInfo = g2d.getFontInfo();
return new AFPBridgeContext(svgUserAgent, fontInfo, imageManager, imageSessionContext,
new AffineTransform(), g2d);
}

/** {@inheritDoc} */
@@ -259,11 +213,13 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler {
}

/** {@inheritDoc} */
protected Graphics2DImagePainter createPainter(BridgeContext ctx, GraphicsNode root, Dimension imageSize) {
protected Graphics2DImagePainter createGrapics2DImagePainter(BridgeContext ctx, GraphicsNode root, Dimension imageSize) {
Graphics2DImagePainter painter = null;
if (paintAsBitmap()) {
painter = super.createPainter(root, ctx, imageSize);
// paint as IOCA Image
painter = super.createGraphics2DImagePainter(root, ctx, imageSize);
} else {
// paint as GOCA Graphics
painter = new Graphics2DImagePainterGOCA(root, ctx, imageSize);
}
return painter;

+ 0
- 89
src/java/org/apache/fop/render/afp/GraphicsObjectPainterAFP.java View File

@@ -1,89 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.afp;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;

import org.apache.batik.gvt.GraphicsNode;
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 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;

/**
* Main constructor
*
* @param graphics an AFP graphics 2D implementation
*/
public GraphicsObjectPainterAFP(AFPGraphics2D graphics) {
final boolean textAsShapes = false;
this.graphics2D = new AFPGraphics2D(textAsShapes);
}

/**
* Sets the graphics node
*
* @param rootNode the graphics root node
*/
public void setGraphicsNode(GraphicsNode rootNode) {
this.root = rootNode;
}

/** {@inheritDoc} */
public void paint(Graphics2D g2d, Rectangle2D area) {
log.debug("Painting SVG using GOCA");

// tell batik to paint the graphics object
root.paint(g2d);

// dispose of the graphics 2d implementation
g2d.dispose();
}

/** {@inheritDoc} */
public Dimension getImageSize() {
return null;
}

/**
* Sets the GOCA Graphics Object
*
* @param graphicsObject the GOCA Graphics Object
*/
public void setGraphicsObject(GraphicsObject graphicsObject) {
this.graphics2D.setGraphicsObject(graphicsObject);
}

}

+ 23
- 0
src/java/org/apache/fop/render/afp/package.html View File

@@ -0,0 +1,23 @@
<!--
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.html 643433 2008-04-01 15:08:24Z acumiskey $ -->
<HTML>
<TITLE>org.apache.fop.render.afp Package</TITLE>
<BODY>
<P>An AFP Renderer implementation and supporting classes.</P>
</BODY>
</HTML>

+ 3
- 24
src/java/org/apache/fop/render/pdf/PDFImageHandler.java View File

@@ -23,36 +23,15 @@ import java.awt.Point;
import java.awt.Rectangle;
import java.io.IOException;

import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;

import org.apache.fop.pdf.PDFXObject;
import org.apache.fop.render.ImageHandler;
import org.apache.fop.render.RendererContext;
import org.apache.xmlgraphics.image.loader.Image;

/**
* This interface is used for handling all sorts of image type for PDF output.
*/
public interface PDFImageHandler {

/**
* Returns the priority for this image handler. A lower value means higher priority. This
* information is used to build the ordered/prioritized list of supported ImageFlavors for
* the PDF renderer. The built-in handlers use priorities between 100 and 999.
* @return a positive integer (>0) indicating the priority
*/
int getPriority();

/**
* Returns the {@link ImageFlavor}s supported by this instance
* @return the supported image flavors
*/
ImageFlavor[] getSupportedImageFlavors();

/**
* Returns the {@link Image} subclass supported by this instance.
* @return the Image type
*/
Class getSupportedImageClass();
public interface PDFImageHandler extends ImageHandler {

/**
* Generates the PDF objects for the given {@link Image} instance. If the handler generates

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

@@ -23,13 +23,12 @@ import java.awt.Point;
import java.awt.Rectangle;
import java.io.IOException;

import org.apache.fop.pdf.PDFXObject;
import org.apache.fop.render.RendererContext;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.ImageGraphics2D;

import org.apache.fop.pdf.PDFXObject;
import org.apache.fop.render.RendererContext;

/**
* PDFImageHandler implementation which handles Graphics2D images.
*/
@@ -39,6 +38,10 @@ public class PDFImageHandlerGraphics2D implements PDFImageHandler {
ImageFlavor.GRAPHICS2D,
};

private static final Class[] CLASSES = new Class[] {
ImageGraphics2D.class,
};

/** {@inheritDoc} */
public PDFXObject generateImage(RendererContext context, Image image,
Point origin, Rectangle pos)
@@ -56,8 +59,8 @@ public class PDFImageHandlerGraphics2D implements PDFImageHandler {
}

/** {@inheritDoc} */
public Class getSupportedImageClass() {
return ImageGraphics2D.class;
public Class[] getSupportedImageClasses() {
return CLASSES;
}

/** {@inheritDoc} */

+ 9
- 6
src/java/org/apache/fop/render/pdf/PDFImageHandlerRawCCITTFax.java View File

@@ -23,15 +23,14 @@ import java.awt.Point;
import java.awt.Rectangle;
import java.io.IOException;

import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;

import org.apache.fop.pdf.PDFDocument;
import org.apache.fop.pdf.PDFImage;
import org.apache.fop.pdf.PDFResourceContext;
import org.apache.fop.pdf.PDFXObject;
import org.apache.fop.render.RendererContext;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;

/**
* PDFImageHandler implementation which handles CCITT encoded images (CCITT fax group 3/4).
@@ -42,6 +41,10 @@ public class PDFImageHandlerRawCCITTFax implements PDFImageHandler {
ImageFlavor.RAW_CCITTFAX,
};

private static final Class[] CLASSES = new Class[] {
ImageRawCCITTFax.class,
};

/** {@inheritDoc} */
public PDFXObject generateImage(RendererContext context, Image image,
Point origin, Rectangle pos)
@@ -71,8 +74,8 @@ public class PDFImageHandlerRawCCITTFax implements PDFImageHandler {
}

/** {@inheritDoc} */
public Class getSupportedImageClass() {
return ImageRawCCITTFax.class;
public Class[] getSupportedImageClasses() {
return CLASSES;
}

/** {@inheritDoc} */

+ 9
- 6
src/java/org/apache/fop/render/pdf/PDFImageHandlerRawJPEG.java View File

@@ -23,15 +23,14 @@ import java.awt.Point;
import java.awt.Rectangle;
import java.io.IOException;

import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;

import org.apache.fop.pdf.PDFDocument;
import org.apache.fop.pdf.PDFImage;
import org.apache.fop.pdf.PDFResourceContext;
import org.apache.fop.pdf.PDFXObject;
import org.apache.fop.render.RendererContext;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;

/**
* PDFImageHandler implementation which handles raw JPEG images.
@@ -42,6 +41,10 @@ public class PDFImageHandlerRawJPEG implements PDFImageHandler {
ImageFlavor.RAW_JPEG,
};

private static final Class[] CLASSES = new Class[] {
ImageRawJPEG.class,
};

/** {@inheritDoc} */
public PDFXObject generateImage(RendererContext context, Image image,
Point origin, Rectangle pos)
@@ -71,8 +74,8 @@ public class PDFImageHandlerRawJPEG implements PDFImageHandler {
}

/** {@inheritDoc} */
public Class getSupportedImageClass() {
return ImageRawJPEG.class;
public Class[] getSupportedImageClasses() {
return CLASSES;
}

/** {@inheritDoc} */

+ 5
- 158
src/java/org/apache/fop/render/pdf/PDFImageHandlerRegistry.java View File

@@ -19,171 +19,18 @@

package org.apache.fop.render.pdf;

import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.util.Service;
import org.apache.fop.render.AbstractImageHandlerRegistry;

/**
* This class holds references to various image handlers used by the PDF renderer. It also
* supports automatic discovery of additional handlers available through
* the class path.
*/
public class PDFImageHandlerRegistry {

/** the logger */
private static Log log = LogFactory.getLog(PDFImageHandlerRegistry.class);

private static final Comparator HANDLER_COMPARATOR = new Comparator() {
public int compare(Object o1, Object o2) {
PDFImageHandler h1 = (PDFImageHandler)o1;
PDFImageHandler h2 = (PDFImageHandler)o2;
return h1.getPriority() - h2.getPriority();
}
};

/** Map containing PDF image handlers for various MIME types */
private Map handlers = new java.util.HashMap();
/** List containing the same handlers as above but ordered by priority */
private List handlerList = new java.util.LinkedList();
public class PDFImageHandlerRegistry extends AbstractImageHandlerRegistry {

/** Sorted Set of registered handlers */
private ImageFlavor[] supportedFlavors = new ImageFlavor[0];
private int handlerRegistrations;
private int lastSync;

/**
* Default constructor.
*/
public PDFImageHandlerRegistry() {
discoverHandlers();
}

/**
* Add an PDFImageHandler. The handler itself is inspected to find out what it supports.
* @param classname the fully qualified class name
*/
public void addHandler(String classname) {
try {
PDFImageHandler handlerInstance
= (PDFImageHandler)Class.forName(classname).newInstance();
addHandler(handlerInstance);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Could not find "
+ classname);
} catch (InstantiationException e) {
throw new IllegalArgumentException("Could not instantiate "
+ classname);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException("Could not access "
+ classname);
} catch (ClassCastException e) {
throw new IllegalArgumentException(classname
+ " is not an "
+ PDFImageHandler.class.getName());
}
/** {@inheritDoc} */
public Class getHandlerClass() {
return PDFImageHandler.class;
}

/**
* Add an image handler. The handler itself is inspected to find out what it supports.
* @param handler the PDFImageHandler instance
*/
public synchronized void addHandler(PDFImageHandler handler) {
Class imageClass = handler.getSupportedImageClass();
this.handlers.put(imageClass, handler);

//Sorted insert
ListIterator iter = this.handlerList.listIterator();
while (iter.hasNext()) {
PDFImageHandler h = (PDFImageHandler)iter.next();
if (HANDLER_COMPARATOR.compare(handler, h) < 0) {
iter.previous();
break;
}
}
iter.add(handler);
this.handlerRegistrations++;
}

/**
* Returns an PDFImageHandler which handles an specific image type given the MIME type
* of the image.
* @param img the Image to be handled
* @return the PDFImageHandler responsible for handling the image or null if none is available
*/
public PDFImageHandler getHandler(Image img) {
return getHandler(img.getClass());
}

/**
* Returns an PDFImageHandler which handles an specific image type given the MIME type
* of the image.
* @param imageClass the Image subclass for which to get a handler
* @return the PDFImageHandler responsible for handling the image or null if none is available
*/
protected synchronized PDFImageHandler getHandler(Class imageClass) {
PDFImageHandler handler = null;
Class cl = imageClass;
while (cl != null) {
handler = (PDFImageHandler)handlers.get(cl);
if (handler != null) {
break;
}
cl = cl.getSuperclass();
}
return handler;
}

/**
* Returns the ordered array of supported image flavors.
* @return the array of image flavors
*/
public synchronized ImageFlavor[] getSupportedFlavors() {
if (this.lastSync != this.handlerRegistrations) {
//Extract all ImageFlavors into a single array
List flavors = new java.util.ArrayList();
Iterator iter = this.handlerList.iterator();
while (iter.hasNext()) {
ImageFlavor[] f = ((PDFImageHandler)iter.next()).getSupportedImageFlavors();
for (int i = 0; i < f.length; i++) {
flavors.add(f[i]);
}
}
this.supportedFlavors = (ImageFlavor[])flavors.toArray(new ImageFlavor[flavors.size()]);
this.lastSync = this.handlerRegistrations;
}
return this.supportedFlavors;
}

/**
* Discovers PDFImageHandler implementations through the classpath and dynamically
* registers them.
*/
private void discoverHandlers() {
// add mappings from available services
Iterator providers = Service.providers(PDFImageHandler.class);
if (providers != null) {
while (providers.hasNext()) {
PDFImageHandler handler = (PDFImageHandler)providers.next();
try {
if (log.isDebugEnabled()) {
log.debug("Dynamically adding PDFImageHandler: "
+ handler.getClass().getName());
}
addHandler(handler);
} catch (IllegalArgumentException e) {
log.error("Error while adding PDFImageHandler", e);
}

}
}
}
}

+ 10
- 6
src/java/org/apache/fop/render/pdf/PDFImageHandlerRenderedImage.java View File

@@ -23,15 +23,14 @@ import java.awt.Point;
import java.awt.Rectangle;
import java.io.IOException;

import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.ImageRendered;

import org.apache.fop.pdf.PDFDocument;
import org.apache.fop.pdf.PDFImage;
import org.apache.fop.pdf.PDFResourceContext;
import org.apache.fop.pdf.PDFXObject;
import org.apache.fop.render.RendererContext;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.ImageRendered;

/**
* PDFImageHandler implementation which handles RenderedImage instances.
@@ -43,6 +42,11 @@ public class PDFImageHandlerRenderedImage implements PDFImageHandler {
ImageFlavor.RENDERED_IMAGE
};

private static final Class[] CLASSES = new Class[] {
ImageRendered.class,
};


/** {@inheritDoc} */
public PDFXObject generateImage(RendererContext context, Image image,
Point origin, Rectangle pos)
@@ -72,8 +76,8 @@ public class PDFImageHandlerRenderedImage implements PDFImageHandler {
}

/** {@inheritDoc} */
public Class getSupportedImageClass() {
return ImageRendered.class;
public Class[] getSupportedImageClasses() {
return CLASSES;
}

/** {@inheritDoc} */

+ 9
- 7
src/java/org/apache/fop/render/pdf/PDFImageHandlerXML.java View File

@@ -24,14 +24,12 @@ import java.awt.Rectangle;
import java.io.IOException;
import java.util.Map;

import org.w3c.dom.Document;
import org.apache.fop.pdf.PDFXObject;
import org.apache.fop.render.RendererContext;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;

import org.apache.fop.pdf.PDFXObject;
import org.apache.fop.render.RendererContext;
import org.w3c.dom.Document;

/**
* PDFImageHandler implementation which handles XML-based images.
@@ -42,6 +40,10 @@ public class PDFImageHandlerXML implements PDFImageHandler {
ImageFlavor.XML_DOM,
};

private static final Class[] CLASSES = new Class[] {
ImageXMLDOM.class,
};

/** {@inheritDoc} */
public PDFXObject generateImage(RendererContext context, Image image,
Point origin, Rectangle pos)
@@ -62,8 +64,8 @@ public class PDFImageHandlerXML implements PDFImageHandler {
}

/** {@inheritDoc} */
public Class getSupportedImageClass() {
return ImageXMLDOM.class;
public Class[] getSupportedImageClasses() {
return CLASSES;
}

/** {@inheritDoc} */

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

@@ -1658,7 +1658,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
info, imageHandlerRegistry.getSupportedFlavors(), hints, sessionContext);

//First check for a dynamically registered handler
PDFImageHandler handler = imageHandlerRegistry.getHandler(img.getClass());
PDFImageHandler handler
= (PDFImageHandler)imageHandlerRegistry.getHandler(img.getClass());
if (handler != null) {
if (log.isDebugEnabled()) {
log.debug("Using PDFImageHandler: " + handler.getClass().getName());

+ 19
- 25
src/java/org/apache/fop/render/ps/PSTextPainter.java View File

@@ -19,40 +19,34 @@

package org.apache.fop.render.ps;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.font.TextAttribute;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
/* java.awt.Font is not imported to avoid confusion with
org.apache.fop.fonts.Font */

import java.io.IOException;
import java.text.AttributedCharacterIterator;
import java.text.CharacterIterator;
import java.awt.font.TextAttribute;
import java.awt.Shape;
import java.awt.Paint;
import java.awt.Stroke;
import java.awt.Color;
import java.io.IOException;
import java.util.List;
import java.util.Iterator;
import java.util.List;

import org.apache.batik.dom.svg.SVGOMTextElement;
import org.apache.batik.gvt.TextNode;
import org.apache.batik.gvt.TextPainter;
import org.apache.batik.gvt.font.GVTFontFamily;
import org.apache.batik.gvt.renderer.StrokingTextPainter;
import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
import org.apache.batik.gvt.text.Mark;
import org.apache.batik.gvt.text.TextPaintInfo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;

import org.apache.xmlgraphics.java2d.ps.PSGraphics2D;
import org.apache.xmlgraphics.java2d.TextHandler;

import org.apache.batik.dom.svg.SVGOMTextElement;
import org.apache.batik.gvt.text.Mark;
import org.apache.batik.gvt.TextPainter;
import org.apache.batik.gvt.TextNode;
import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
import org.apache.batik.gvt.text.TextPaintInfo;
import org.apache.batik.gvt.font.GVTFontFamily;
import org.apache.batik.gvt.renderer.StrokingTextPainter;


/**
@@ -74,8 +68,8 @@ public class PSTextPainter implements TextPainter {
/** the logger for this class */
protected Log log = LogFactory.getLog(PSTextPainter.class);

private NativeTextHandler nativeTextHandler;
private FontInfo fontInfo;
private final NativeTextHandler nativeTextHandler;
private final FontInfo fontInfo;

/**
* Use the stroking text painter to get the bounds and shape.
@@ -317,7 +311,7 @@ public class PSTextPainter implements TextPainter {
}

drawPrimitiveString(g2d, loc, font, txt, tx);
loc.setLocation(loc.getX() + (double)advance, loc.getY());
loc.setLocation(loc.getX() + advance, loc.getY());
return loc;
}

@@ -422,7 +416,7 @@ public class PSTextPainter implements TextPainter {
fStyle |= java.awt.Font.ITALIC;
}
return new java.awt.Font(font.getFontName(), fStyle,
(int)(font.getFontSize() / 1000));
(font.getFontSize() / 1000));
}

private float getStringWidth(String str, Font font) {

+ 139
- 0
src/java/org/apache/fop/svg/AbstractFOPBridgeContext.java View File

@@ -0,0 +1,139 @@
/*
* 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.svg;

import java.awt.geom.AffineTransform;
import java.lang.reflect.Constructor;

import org.apache.batik.bridge.Bridge;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.DocumentLoader;
import org.apache.batik.bridge.UserAgent;
import org.apache.fop.fonts.FontInfo;
import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;

public abstract class AbstractFOPBridgeContext extends BridgeContext {

/** The font list. */
protected final FontInfo fontInfo;

protected final ImageManager imageManager;
protected final ImageSessionContext imageSessionContext;

protected final AffineTransform linkTransform;

/**
* Constructs a new bridge context.
* @param userAgent the user agent
* @param loader the Document Loader to use for referenced documents.
* @param fontInfo the font list for the text painter, may be null
* in which case text is painted as shapes
* @param linkTransform AffineTransform to properly place links,
* may be null
* @param imageManager an image manager
* @param imageSessionContext an image session context
* @param linkTransform AffineTransform to properly place links,
* may be null
*/
public AbstractFOPBridgeContext(UserAgent userAgent,
DocumentLoader loader,
FontInfo fontInfo,
ImageManager imageManager,
ImageSessionContext imageSessionContext,
AffineTransform linkTransform) {
super(userAgent, loader);
this.fontInfo = fontInfo;
this.imageManager = imageManager;
this.imageSessionContext = imageSessionContext;
this.linkTransform = linkTransform;
}

/**
* Constructs a new bridge context.
* @param userAgent the user agent
* @param fontInfo the font list for the text painter, may be null
* in which case text is painted as shapes
* @param imageManager an image manager
* @param imageSessionContext an image session context
* @param linkTransform AffineTransform to properly place links,
* may be null
*/
public AbstractFOPBridgeContext(UserAgent userAgent,
FontInfo fontInfo,
ImageManager imageManager,
ImageSessionContext imageSessionContext,
AffineTransform linkTransform) {
super(userAgent);
this.fontInfo = fontInfo;
this.imageManager = imageManager;
this.imageSessionContext = imageSessionContext;
this.linkTransform = linkTransform;
}

/**
* Constructs a new bridge context.
* @param userAgent the user agent
* @param fontInfo the font list for the text painter, may be null
* in which case text is painted as shapes
* @param imageManager an image manager
* @param imageSessionContext an image session context
*/
public AbstractFOPBridgeContext(UserAgent userAgent,
FontInfo fontInfo,
ImageManager imageManager,
ImageSessionContext imageSessionContext) {
this(userAgent, fontInfo, imageManager, imageSessionContext, null);
}

/**
* Returns the ImageManager to be used by the ImageElementBridge.
* @return the image manager
*/
public ImageManager getImageManager() {
return this.imageManager;
}

/**
* Returns the ImageSessionContext to be used by the ImageElementBridge.
* @return the image session context
*/
public ImageSessionContext getImageSessionContext() {
return this.imageSessionContext;
}

protected void putElementBridgeConditional(String className, String testFor) {
try {
Class.forName(testFor);
//if we get here the test class is available

Class clazz = Class.forName(className);
Constructor constructor = clazz.getConstructor(new Class[] {FontInfo.class});
putBridge((Bridge)constructor.newInstance(new Object[] {fontInfo}));
} catch (Throwable t) {
//simply ignore (bridges instantiated over this method are optional)
}
}

// Make sure any 'sub bridge contexts' also have our bridges.
//TODO There's no matching method in the super-class here
public abstract BridgeContext createBridgeContext();

}

+ 284
- 0
src/java/org/apache/fop/svg/AbstractFOPImageElementBridge.java View File

@@ -0,0 +1,284 @@
/*
* 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.svg;

import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;

import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.SVGImageElementBridge;
import org.apache.batik.gvt.AbstractGraphicsNode;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.util.ParsedURL;
import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
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.impl.ImageGraphics2D;
import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;
import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;
import org.w3c.dom.Element;
import org.w3c.dom.svg.SVGDocument;

/**
* Bridge class for the &lt;image> element when jpeg images.
*
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
*/
public abstract class AbstractFOPImageElementBridge extends SVGImageElementBridge {

/**
* Constructs a new bridge for the &lt;image> element.
*/
public AbstractFOPImageElementBridge() { }

/**
* Create the raster image node.
* THis checks if it is a jpeg file and creates a jpeg node
* so the jpeg can be inserted directly into the pdf document.
* @param ctx the bridge context
* @param imageElement the svg element for the image
* @param purl the parsed url for the image resource
* @return a new graphics node
*/
protected GraphicsNode createImageGraphicsNode
(BridgeContext ctx, Element imageElement, ParsedURL purl) {
AbstractFOPBridgeContext bridgeCtx = (AbstractFOPBridgeContext)ctx;

ImageManager manager = bridgeCtx.getImageManager();
ImageSessionContext sessionContext = bridgeCtx.getImageSessionContext();
try {
ImageInfo info = manager.getImageInfo(purl.toString(), sessionContext);
ImageFlavor[] supportedFlavors = getSupportedFlavours();
Image image = manager.getImage(info, supportedFlavors, sessionContext);

//TODO color profile overrides aren't handled, yet!
//ICCColorSpaceExt colorspaceOverride = extractColorSpace(e, ctx);
AbstractGraphicsNode specializedNode = null;
if (image instanceof ImageXMLDOM) {
ImageXMLDOM xmlImage = (ImageXMLDOM)image;
if (xmlImage.getDocument() instanceof SVGDocument) {
return createSVGImageNode(ctx, imageElement,
(SVGDocument)xmlImage.getDocument());
} else {
//Convert image to Graphics2D
image = manager.convertImage(xmlImage,
new ImageFlavor[] {ImageFlavor.GRAPHICS2D});
}
}
if (image instanceof ImageRawJPEG) {
specializedNode = createLoaderImageNode(image, ctx, imageElement, purl);
} else if (image instanceof ImageRawCCITTFax) {
specializedNode = createLoaderImageNode(image, ctx, imageElement, purl);
} else if (image instanceof ImageGraphics2D) {
ImageGraphics2D g2dImage = (ImageGraphics2D)image;
specializedNode = new Graphics2DNode(g2dImage);
} else {
ctx.getUserAgent().displayError(
new ImageException("Cannot convert an image to a usable format: " + purl));
}

Rectangle2D imgBounds = getImageBounds(ctx, imageElement);
Rectangle2D bounds = specializedNode.getPrimitiveBounds();
float [] vb = new float[4];
vb[0] = 0; // x
vb[1] = 0; // y
vb[2] = (float) bounds.getWidth(); // width
vb[3] = (float) bounds.getHeight(); // height

// handles the 'preserveAspectRatio', 'overflow' and 'clip'
// and sets the appropriate AffineTransform to the image node
initializeViewport(ctx, imageElement, specializedNode, vb, imgBounds);
return specializedNode;
} catch (Exception e) {
ctx.getUserAgent().displayError(e);
}

return superCreateGraphicsNode(ctx, imageElement, purl);
}

/**
* Calls the superclass' createImageGraphicNode() method to create the normal GraphicsNode.
* @param ctx the bridge context
* @param imageElement the image element
* @param purl the parsed URL
* @return the newly created graphics node
* @see org.apache.batik.bridge.SVGImageElementBridge#createGraphicsNode(BridgeContext, Element)
*/
protected GraphicsNode superCreateGraphicsNode
(BridgeContext ctx, Element imageElement, ParsedURL purl) {
return super.createImageGraphicsNode(ctx, imageElement, purl);
}

/**
* Returns an array of supported image flavours
*
* @return an array of supported image flavours
*/
protected abstract ImageFlavor[] getSupportedFlavours();

/**
* Creates a loader image node implementation
* @param purl the parsed url
* @param imageElement the image element
* @param ctx the batik bridge context
* @param image the image
*
* @return a loader image node implementation
*/
protected LoaderImageNode createLoaderImageNode(
Image image, BridgeContext ctx, Element imageElement, ParsedURL purl) {
return new LoaderImageNode(image, ctx, imageElement, purl);
}

/**
* An image node for natively handled Image instance.
* This holds a natively handled image so that it can be drawn into
* the PDFGraphics2D.
*/
public class LoaderImageNode extends AbstractGraphicsNode {

protected final Image image;
protected final BridgeContext ctx;
protected final Element imageElement;
protected final ParsedURL purl;
protected GraphicsNode origGraphicsNode = null;

/**
* Create a new image node for drawing natively handled images
* into PDF graphics.
* @param image the JPEG image
* @param ctx the bridge context
* @param imageElement the SVG image element
* @param purl the URL to the image
*/
public LoaderImageNode(Image image, BridgeContext ctx,
Element imageElement, ParsedURL purl) {
this.image = image;
this.ctx = ctx;
this.imageElement = imageElement;
this.purl = purl;
}

/** {@inheritDoc} */
public Shape getOutline() {
return getPrimitiveBounds();
}

/** {@inheritDoc} */
public void primitivePaint(Graphics2D g2d) {
if (g2d instanceof NativeImageHandler) {
NativeImageHandler nativeImageHandler = (NativeImageHandler) g2d;
float x = 0;
float y = 0;
try {
float width = image.getSize().getWidthPx();
float height = image.getSize().getHeightPx();
nativeImageHandler.addNativeImage(image, x, y, width, height);
} catch (Exception e) {
ctx.getUserAgent().displayError(e);
}
} else {
// Not going directly into PDF so use
// original implementation so filters etc work.
if (origGraphicsNode == null) {
// Haven't constructed base class Graphics Node,
// so do so now.
origGraphicsNode
= superCreateGraphicsNode(ctx, imageElement, purl);
}
origGraphicsNode.primitivePaint(g2d);
}
}

/** {@inheritDoc} */
public Rectangle2D getGeometryBounds() {
return getPrimitiveBounds();
}

/** {@inheritDoc} */
public Rectangle2D getPrimitiveBounds() {
return new Rectangle2D.Double(0, 0,
image.getSize().getWidthPx(),
image.getSize().getHeightPx());
}

/** {@inheritDoc} */
public Rectangle2D getSensitiveBounds() {
//No interactive features, just return primitive bounds
return getPrimitiveBounds();
}

}

/**
* A node that holds a Graphics2D image.
*/
public class Graphics2DNode extends AbstractGraphicsNode {

private final ImageGraphics2D image;

/**
* Create a new Graphics2D node.
* @param g2d the Graphics2D image
*/
public Graphics2DNode(ImageGraphics2D g2d) {
this.image = g2d;
}

/** {@inheritDoc} */
public Shape getOutline() {
return getPrimitiveBounds();
}

/** {@inheritDoc} */
public void primitivePaint(Graphics2D g2d) {
int width = image.getSize().getWidthPx();
int height = image.getSize().getHeightPx();
Rectangle2D area = new Rectangle2D.Double(0, 0, width, height);
Graphics2DImagePainter painter = image.getGraphics2DImagePainter();
painter.paint(g2d, area);
}

/** {@inheritDoc} */
public Rectangle2D getGeometryBounds() {
return getPrimitiveBounds();
}

/** {@inheritDoc} */
public Rectangle2D getPrimitiveBounds() {
return new Rectangle2D.Double(0, 0,
image.getSize().getWidthPx(),
image.getSize().getHeightPx());
}

/** {@inheritDoc} */
public Rectangle2D getSensitiveBounds() {
//No interactive features, just return primitive bounds
return getPrimitiveBounds();
}

}
}

src/java/org/apache/fop/afp/AFPTextElementBridge.java → src/java/org/apache/fop/svg/AbstractFOPTextElementBridge.java View File

@@ -5,9 +5,9 @@
* 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.
@@ -17,10 +17,10 @@

/* $Id$ */

package org.apache.fop.afp;
package org.apache.fop.svg;

import org.apache.batik.bridge.SVGTextElementBridge;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.SVGTextElementBridge;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.gvt.TextNode;
import org.apache.batik.gvt.TextPainter;
@@ -31,21 +31,26 @@ import org.w3c.dom.Node;
* Bridge class for the &lt;text> element.
* This bridge will use the direct text painter if the text
* for the element is simple.
*
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
*/
public class AFPTextElementBridge extends SVGTextElementBridge {
private AFPTextPainter textPainter;
public abstract class AbstractFOPTextElementBridge extends SVGTextElementBridge {

/** text painter */
protected TextPainter textPainter;

/**
* Constructs a new bridge for the &lt;text> element.
* @param textPainter the text painter to use
* Main constructor
*
* @param textPainter the text painter
*/
public AFPTextElementBridge(AFPTextPainter textPainter) {
public AbstractFOPTextElementBridge(TextPainter textPainter) {
this.textPainter = textPainter;
}

/**
* Create a text element bridge.
*
* This set the text painter on the node if the text is simple.
* @param ctx the bridge context
* @param e the svg element
@@ -53,16 +58,13 @@ public class AFPTextElementBridge extends SVGTextElementBridge {
*/
public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
GraphicsNode node = super.createGraphicsNode(ctx, e);
if (node != null && isSimple(ctx, e, node)) {
((TextNode)node).setTextPainter(getTextPainter());
if (node != null) {
//Set our own text painter
((TextNode)node).setTextPainter(textPainter);
}
return node;
}

private TextPainter getTextPainter() {
return this.textPainter;
}

/**
* Check if text element contains simple text.
* This checks the children of the text element to determine
@@ -75,9 +77,9 @@ public class AFPTextElementBridge extends SVGTextElementBridge {
* @param element the svg text element
* @param node the graphics node
* @return true if this text is simple of false if it cannot be
* easily rendered using normal drawString on the PDFGraphics2D
* easily rendered using normal drawString on the Graphics2D
*/
private boolean isSimple(BridgeContext ctx, Element element, GraphicsNode node) {
protected boolean isSimple(BridgeContext ctx, Element element, GraphicsNode node) {
for (Node n = element.getFirstChild();
n != null;
n = n.getNextSibling()) {
@@ -106,5 +108,6 @@ public class AFPTextElementBridge extends SVGTextElementBridge {

return true;
}

}


+ 40
- 0
src/java/org/apache/fop/svg/NativeImageHandler.java View File

@@ -0,0 +1,40 @@
/*
* 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.svg;

public interface NativeImageHandler {

/**
* Add a natively handled image directly to the document.
* This is used by the ImageElementBridge to draw a natively handled image
* (like JPEG or CCITT images)
* directly into the document rather than converting the image into
* a bitmap and increasing the size.
*
* @param image the image to draw
* @param x the x position
* @param y the y position
* @param width the width to draw the image
* @param height the height to draw the image
*/
void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, float x, float y,
float width, float height);

}

+ 30
- 74
src/java/org/apache/fop/svg/PDFBridgeContext.java View File

@@ -20,30 +20,20 @@
package org.apache.fop.svg;

import java.awt.geom.AffineTransform;
import java.lang.reflect.Constructor;

import org.apache.batik.bridge.Bridge;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.DocumentLoader;
import org.apache.batik.bridge.SVGTextElementBridge;
import org.apache.batik.bridge.UserAgent;
import org.apache.batik.gvt.TextPainter;
import org.apache.fop.fonts.FontInfo;

import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;


/**
* BridgeContext which registers the custom bridges for PDF output.
*/
public class PDFBridgeContext extends BridgeContext {

/** The font list. */
private final FontInfo fontInfo;

private final ImageManager imageManager;
private final ImageSessionContext imageSessionContext;

private AffineTransform linkTransform;
public class PDFBridgeContext extends AbstractFOPBridgeContext {

/**
* Constructs a new bridge context.
@@ -53,18 +43,16 @@ public class PDFBridgeContext extends BridgeContext {
* in which case text is painted as shapes
* @param linkTransform AffineTransform to properly place links,
* may be null
* @param imageManager an image manager
* @param imageSessionContext an image session context
* @param linkTransform AffineTransform to properly place links,
* may be null
*/
public PDFBridgeContext(UserAgent userAgent,
DocumentLoader loader,
FontInfo fontInfo,
ImageManager imageManager,
ImageSessionContext imageSessionContext,
AffineTransform linkTransform) {
super(userAgent, loader);
this.fontInfo = fontInfo;
this.imageManager = imageManager;
this.imageSessionContext = imageSessionContext;
this.linkTransform = linkTransform;
public PDFBridgeContext(UserAgent userAgent, DocumentLoader documentLoader,
FontInfo fontInfo, ImageManager imageManager,
ImageSessionContext imageSessionContext,
AffineTransform linkTransform) {
super(userAgent, documentLoader, fontInfo, imageManager, imageSessionContext, linkTransform);
}

/**
@@ -72,19 +60,12 @@ public class PDFBridgeContext extends BridgeContext {
* @param userAgent the user agent
* @param fontInfo the font list for the text painter, may be null
* in which case text is painted as shapes
* @param linkTransform AffineTransform to properly place links,
* may be null
* @param imageManager an image manager
* @param imageSessionContext an image session context
*/
public PDFBridgeContext(UserAgent userAgent,
FontInfo fontInfo,
ImageManager imageManager,
ImageSessionContext imageSessionContext,
AffineTransform linkTransform) {
super(userAgent);
this.fontInfo = fontInfo;
this.imageManager = imageManager;
this.imageSessionContext = imageSessionContext;
this.linkTransform = linkTransform;
public PDFBridgeContext(UserAgent userAgent, FontInfo fontInfo,
ImageManager imageManager, ImageSessionContext imageSessionContext) {
super(userAgent, fontInfo, imageManager, imageSessionContext);
}

/**
@@ -92,41 +73,15 @@ public class PDFBridgeContext extends BridgeContext {
* @param userAgent the user agent
* @param fontInfo the font list for the text painter, may be null
* in which case text is painted as shapes
* @param imageManager an image manager
* @param imageSessionContext an image session context
* @param linkTransform AffineTransform to properly place links,
* may be null
*/
public PDFBridgeContext(UserAgent userAgent,
FontInfo fontInfo,
ImageManager imageManager,
ImageSessionContext imageSessionContext) {
this(userAgent, fontInfo, imageManager, imageSessionContext, null);
}

/**
* Returns the ImageManager to be used by the ImageElementBridge.
* @return the image manager
*/
public ImageManager getImageManager() {
return this.imageManager;
}

/**
* Returns the ImageSessionContext to be used by the ImageElementBridge.
* @return the image session context
*/
public ImageSessionContext getImageSessionContext() {
return this.imageSessionContext;
}

private void putPDFElementBridgeConditional(String className, String testFor) {
try {
Class.forName(testFor);
//if we get here the test class is available

Class clazz = Class.forName(className);
Constructor constructor = clazz.getConstructor(new Class[] {FontInfo.class});
putBridge((Bridge)constructor.newInstance(new Object[] {fontInfo}));
} catch (Throwable t) {
//simply ignore (bridges instantiated over this method are optional)
}
public PDFBridgeContext(SVGUserAgent userAgent, FontInfo fontInfo,
ImageManager imageManager, ImageSessionContext imageSessionContext,
AffineTransform linkTransform) {
super(userAgent, fontInfo, imageManager, imageSessionContext, linkTransform);
}

/** {@inheritDoc} */
@@ -134,23 +89,24 @@ public class PDFBridgeContext extends BridgeContext {
super.registerSVGBridges();

if (fontInfo != null) {
PDFTextElementBridge textElementBridge = new PDFTextElementBridge(fontInfo);
TextPainter textPainter = new PDFTextPainter(fontInfo);
SVGTextElementBridge textElementBridge = new PDFTextElementBridge(textPainter);
putBridge(textElementBridge);

//Batik flow text extension (may not always be available)
//putBridge(new PDFBatikFlowTextElementBridge(fontInfo);
putPDFElementBridgeConditional(
putElementBridgeConditional(
"org.apache.fop.svg.PDFBatikFlowTextElementBridge",
"org.apache.batik.extension.svg.BatikFlowTextElementBridge");

//SVG 1.2 flow text support
//putBridge(new PDFSVG12TextElementBridge(fontInfo)); //-->Batik 1.7
putPDFElementBridgeConditional(
putElementBridgeConditional(
"org.apache.fop.svg.PDFSVG12TextElementBridge",
"org.apache.batik.bridge.svg12.SVG12TextElementBridge");

//putBridge(new PDFSVGFlowRootElementBridge(fontInfo));
putPDFElementBridgeConditional(
putElementBridgeConditional(
"org.apache.fop.svg.PDFSVGFlowRootElementBridge",
"org.apache.batik.bridge.svg12.SVGFlowRootElementBridge");
}

+ 4
- 3
src/java/org/apache/fop/svg/PDFGraphics2D.java View File

@@ -100,7 +100,7 @@ import org.apache.xmlgraphics.java2d.GraphicContext;
* @version $Id$
* @see org.apache.batik.ext.awt.g2d.AbstractGraphics2D
*/
public class PDFGraphics2D extends AbstractGraphics2D {
public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHandler {

private static final AffineTransform IDENTITY_TRANSFORM = new AffineTransform();

@@ -414,7 +414,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
* @param width the width to draw the image
* @param height the height to draw the image
*/
void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, float x, float y,
public void addNativeImage(org.apache.xmlgraphics.image.loader.Image image, float x, float y,
float width, float height) {
preparePainting();
String key = image.getInfo().getOriginalURI();
@@ -521,7 +521,8 @@ public class PDFGraphics2D extends AbstractGraphics2D {
g.clip(new Rectangle(0, 0, imageWidth, imageHeight));
g.setComposite(gc.getComposite());

if (!g.drawImage(img, 0, 0, imageWidth, imageHeight, observer)) {
boolean drawn = g.drawImage(img, 0, 0, imageWidth, imageHeight, observer);
if (!drawn) {
return false;
}
g.dispose();

+ 5
- 228
src/java/org/apache/fop/svg/PDFImageElementBridge.java View File

@@ -19,36 +19,14 @@

package org.apache.fop.svg;

import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;

import org.w3c.dom.Element;
import org.w3c.dom.svg.SVGDocument;

import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.SVGImageElementBridge;
import org.apache.batik.gvt.AbstractGraphicsNode;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.util.ParsedURL;

import org.apache.xmlgraphics.image.loader.Image;
import org.apache.xmlgraphics.image.loader.ImageException;
import org.apache.xmlgraphics.image.loader.ImageFlavor;
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.impl.ImageGraphics2D;
import org.apache.xmlgraphics.image.loader.impl.ImageRawCCITTFax;
import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
import org.apache.xmlgraphics.image.loader.impl.ImageXMLDOM;

/**
* Bridge class for the &lt;image> element when jpeg images.
* PDF Image Element Bridge class for the &lt;image> element when jpeg images.
*
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
*/
public class PDFImageElementBridge extends SVGImageElementBridge {
public class PDFImageElementBridge extends AbstractFOPImageElementBridge {

/**
* Constructs a new bridge for the &lt;image> element.
@@ -60,210 +38,9 @@ public class PDFImageElementBridge extends SVGImageElementBridge {
ImageFlavor.RAW_CCITTFAX,
ImageFlavor.GRAPHICS2D,
ImageFlavor.XML_DOM};
/**
* Create the raster image node.
* THis checks if it is a jpeg file and creates a jpeg node
* so the jpeg can be inserted directly into the pdf document.
* @param ctx the bridge context
* @param imageElement the svg element for the image
* @param purl the parsed url for the image resource
* @return a new graphics node
*/
protected GraphicsNode createImageGraphicsNode
(BridgeContext ctx, Element imageElement, ParsedURL purl) {
PDFBridgeContext pdfCtx = (PDFBridgeContext)ctx;

ImageManager manager = pdfCtx.getImageManager();
ImageSessionContext sessionContext = pdfCtx.getImageSessionContext();
try {
ImageInfo info = manager.getImageInfo(purl.toString(), sessionContext);
Image image = manager.getImage(info, supportedFlavors, sessionContext);

//TODO color profile overrides aren't handled, yet!
//ICCColorSpaceExt colorspaceOverride = extractColorSpace(e, ctx);
AbstractGraphicsNode specializedNode = null;
if (image instanceof ImageXMLDOM) {
ImageXMLDOM xmlImage = (ImageXMLDOM)image;
if (xmlImage.getDocument() instanceof SVGDocument) {
return createSVGImageNode(ctx, imageElement,
(SVGDocument)xmlImage.getDocument());
} else {
//Convert image to Graphics2D
image = manager.convertImage(xmlImage,
new ImageFlavor[] {ImageFlavor.GRAPHICS2D});
}
}
if (image instanceof ImageRawJPEG) {
specializedNode = new LoaderImageNode(image, ctx, imageElement, purl);
} else if (image instanceof ImageRawCCITTFax) {
specializedNode = new LoaderImageNode(image, ctx, imageElement, purl);
} else if (image instanceof ImageGraphics2D) {
ImageGraphics2D g2dImage = (ImageGraphics2D)image;
specializedNode = new Graphics2DNode(g2dImage);
} else {
ctx.getUserAgent().displayError(
new ImageException("Cannot convert an image to a usable format: " + purl));
}

Rectangle2D imgBounds = getImageBounds(ctx, imageElement);
Rectangle2D bounds = specializedNode.getPrimitiveBounds();
float [] vb = new float[4];
vb[0] = 0; // x
vb[1] = 0; // y
vb[2] = (float) bounds.getWidth(); // width
vb[3] = (float) bounds.getHeight(); // height

// handles the 'preserveAspectRatio', 'overflow' and 'clip'
// and sets the appropriate AffineTransform to the image node
initializeViewport(ctx, imageElement, specializedNode, vb, imgBounds);
return specializedNode;
} catch (Exception e) {
ctx.getUserAgent().displayError(e);
}

return superCreateGraphicsNode(ctx, imageElement, purl);
}

/**
* Calls the superclass' createImageGraphicNode() method to create the normal GraphicsNode.
* @param ctx the bridge context
* @param imageElement the image element
* @param purl the parsed URL
* @return the newly created graphics node
* @see org.apache.batik.bridge.SVGImageElementBridge#createGraphicsNode(BridgeContext, Element)
*/
protected GraphicsNode superCreateGraphicsNode
(BridgeContext ctx, Element imageElement, ParsedURL purl) {
return super.createImageGraphicsNode(ctx, imageElement, purl);
}


/**
* An image node for natively handled Image instance.
* This holds a natively handled image so that it can be drawn into
* the PDFGraphics2D.
*/
public class LoaderImageNode extends AbstractGraphicsNode {

private Image image;
private BridgeContext ctx;
private Element imageElement;
private ParsedURL purl;
private GraphicsNode origGraphicsNode = null;

/**
* Create a new image node for drawing natively handled images
* into PDF graphics.
* @param image the JPEG image
* @param ctx the bridge context
* @param imageElement the SVG image element
* @param purl the URL to the image
*/
public LoaderImageNode(Image image, BridgeContext ctx,
Element imageElement, ParsedURL purl) {
this.image = image;
this.ctx = ctx;
this.imageElement = imageElement;
this.purl = purl;
}

/** {@inheritDoc} */
public Shape getOutline() {
return getPrimitiveBounds();
}

/** {@inheritDoc} */
public void primitivePaint(Graphics2D g2d) {
if (g2d instanceof PDFGraphics2D) {
PDFGraphics2D pdfg = (PDFGraphics2D) g2d;
float x = 0;
float y = 0;
try {
float width = image.getSize().getWidthPx();
float height = image.getSize().getHeightPx();
pdfg.addNativeImage(image, x, y, width, height);
} catch (Exception e) {
ctx.getUserAgent().displayError(e);
}
} else {
// Not going directly into PDF so use
// original implementation so filters etc work.
if (origGraphicsNode == null) {
// Haven't constructed baseclass Graphics Node,
// so do so now.
origGraphicsNode
= PDFImageElementBridge.this.superCreateGraphicsNode
(ctx, imageElement, purl);
}
origGraphicsNode.primitivePaint(g2d);
}
}

/** {@inheritDoc} */
public Rectangle2D getGeometryBounds() {
return getPrimitiveBounds();
}

/** {@inheritDoc} */
public Rectangle2D getPrimitiveBounds() {
return new Rectangle2D.Double(0, 0,
image.getSize().getWidthPx(),
image.getSize().getHeightPx());
}

/** {@inheritDoc} */
public Rectangle2D getSensitiveBounds() {
//No interactive features, just return primitive bounds
return getPrimitiveBounds();
}

}

/**
* A node that holds a Graphics2D image.
*/
public class Graphics2DNode extends AbstractGraphicsNode {

private ImageGraphics2D image;

/**
* Create a new Graphics2D node.
* @param g2d the Graphics2D image
*/
public Graphics2DNode(ImageGraphics2D g2d) {
this.image = g2d;
}

/** {@inheritDoc} */
public Shape getOutline() {
return getPrimitiveBounds();
}

/** {@inheritDoc} */
public void primitivePaint(Graphics2D g2d) {
int width = image.getSize().getWidthPx();
int height = image.getSize().getHeightPx();
Rectangle2D area = new Rectangle2D.Double(0, 0, width, height);
image.getGraphics2DImagePainter().paint(g2d, area);
}

/** {@inheritDoc} */
public Rectangle2D getGeometryBounds() {
return getPrimitiveBounds();
}

/** {@inheritDoc} */
public Rectangle2D getPrimitiveBounds() {
return new Rectangle2D.Double(0, 0,
image.getSize().getWidthPx(),
image.getSize().getHeightPx());
}

/** {@inheritDoc} */
public Rectangle2D getSensitiveBounds() {
//No interactive features, just return primitive bounds
return getPrimitiveBounds();
}

/** {@inheritDoc} */
protected ImageFlavor[] getSupportedFlavours() {
return supportedFlavors;
}
}

+ 5
- 37
src/java/org/apache/fop/svg/PDFTextElementBridge.java View File

@@ -19,13 +19,7 @@

package org.apache.fop.svg;

import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.SVGTextElementBridge;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.gvt.TextNode;
import org.apache.batik.gvt.TextPainter;
import org.apache.fop.fonts.FontInfo;
import org.w3c.dom.Element;

/**
* Bridge class for the &lt;text> element.
@@ -34,41 +28,15 @@ import org.w3c.dom.Element;
*
* @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
*/
public class PDFTextElementBridge extends SVGTextElementBridge {

private PDFTextPainter pdfTextPainter;
public class PDFTextElementBridge extends AbstractFOPTextElementBridge {

/**
* Constructs a new bridge for the &lt;text> element.
* @param fi the font information
*/
public PDFTextElementBridge(FontInfo fi) {
pdfTextPainter = new PDFTextPainter(fi);
}

/**
* Create a text element bridge.
* This set the text painter on the node if the text is simple.
* @param ctx the bridge context
* @param e the svg element
* @return the text graphics node created by the super class
*
* @param textPainter the text painter to use
*/
public GraphicsNode createGraphicsNode(BridgeContext ctx, Element e) {
GraphicsNode node = super.createGraphicsNode(ctx, e);
if (node != null) {
//Set our own text painter
((TextNode)node).setTextPainter(getTextPainter());
}
return node;
public PDFTextElementBridge(TextPainter textPainter) {
super(textPainter);
}

/**
* Returns the TextPainter instance used by this bridge.
* @return the text painter
*/
public TextPainter getTextPainter() {
return pdfTextPainter;
}

}


+ 3
- 4
src/java/org/apache/fop/svg/PDFTextPainter.java View File

@@ -43,7 +43,6 @@ import org.apache.batik.gvt.renderer.StrokingTextPainter;
import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
import org.apache.batik.gvt.text.TextPaintInfo;
import org.apache.batik.gvt.text.TextSpanLayout;

import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
@@ -63,8 +62,8 @@ public class PDFTextPainter extends StrokingTextPainter {

private static final boolean DEBUG = false;

private boolean strokeText = false;
private FontInfo fontInfo;
private final boolean strokeText = false;
private final FontInfo fontInfo;

/**
* Create a new PDF text painter with the given font information.
@@ -280,7 +279,7 @@ public class PDFTextPainter extends StrokingTextPainter {
Float fontSize = (Float) aci.getAttribute(TextAttribute.SIZE);

String style = ((posture != null) && (posture.floatValue() > 0.0))
? "italic" : "normal";
? Font.STYLE_ITALIC : Font.STYLE_NORMAL;
int weight = ((taWeight != null)
&& (taWeight.floatValue() > 1.0)) ? Font.WEIGHT_BOLD
: Font.WEIGHT_NORMAL;

Loading…
Cancel
Save