Ver código fonte

AFP GOCA:

fonts were not embedded from within AFPGraphics2D.
Changed the way FOP fonts are selected based on Batik's GVT fonts to match the behaviour of PDF/PS output.


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1099829 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-1_1rc1old
Jeremias Maerki 13 anos atrás
pai
commit
5e95f76c26

+ 21
- 0
src/java/org/apache/fop/afp/AFPGraphics2D.java Ver arquivo

@@ -165,6 +165,14 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand
this.resourceManager = resourceManager;
}

/**
* Returns the AFP resource manager associated with this {@link Graphics2D} instance.
* @return the resource manager
*/
public AFPResourceManager getResourceManager() {
return this.resourceManager;
}

/**
* Sets the AFP resource info
*
@@ -497,12 +505,14 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand
}

/** {@inheritDoc} */
@Override
public void draw(Shape shape) {
LOG.debug("draw() shape=" + shape);
doDrawing(shape, false);
}

/** {@inheritDoc} */
@Override
public void fill(Shape shape) {
LOG.debug("fill() shape=" + shape);
doDrawing(shape, true);
@@ -521,6 +531,7 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand
}

/** {@inheritDoc} */
@Override
public void drawString(String str, float x, float y) {
try {
if (customTextHandler != null && !textAsShapes) {
@@ -534,21 +545,25 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand
}

/** {@inheritDoc} */
@Override
public GraphicsConfiguration getDeviceConfiguration() {
return graphicsConfig;
}

/** {@inheritDoc} */
@Override
public Graphics create() {
return new AFPGraphics2D(this);
}

/** {@inheritDoc} */
@Override
public void dispose() {
this.graphicsObj = null;
}

/** {@inheritDoc} */
@Override
public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
return drawImage(img, x, y, img.getWidth(observer), img.getHeight(observer), observer);
}
@@ -595,6 +610,7 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand
}

/** {@inheritDoc} */
@Override
public boolean drawImage(Image img, int x, int y, int width, int height,
ImageObserver observer) {
// draw with AWT Graphics2D
@@ -609,6 +625,7 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand
}

/** {@inheritDoc} */
@Override
public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
int imgWidth = img.getWidth();
int imgHeight = img.getHeight();
@@ -658,17 +675,20 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand
}

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

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

/** {@inheritDoc} */
@Override
public void setXORMode(Color col) {
LOG.debug("setXORMode() NYI: col=" + col);
}
@@ -681,6 +701,7 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand
}

/** {@inheritDoc} */
@Override
public void copyArea(int x, int y, int width, int height, int dx, int dy) {
LOG.debug("copyArea() NYI: ");
}

+ 7
- 3
src/java/org/apache/fop/afp/svg/AFPBridgeContext.java Ver arquivo

@@ -25,11 +25,13 @@ 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.xmlgraphics.image.loader.ImageManager;
import org.apache.xmlgraphics.image.loader.ImageSessionContext;

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;

/**
* An AFP specific implementation of a Batik BridgeContext
@@ -79,11 +81,12 @@ public class AFPBridgeContext extends AbstractFOPBridgeContext {
}

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

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

TextPainter textPainter = new AFPTextPainter(textHandler);
@@ -96,6 +99,7 @@ public class AFPBridgeContext extends AbstractFOPBridgeContext {
}

/** {@inheritDoc} */
@Override
public BridgeContext createBridgeContext() {
return new AFPBridgeContext(getUserAgent(), getDocumentLoader(),
fontInfo,

+ 23
- 1
src/java/org/apache/fop/afp/svg/AFPTextHandler.java Ver arquivo

@@ -21,15 +21,18 @@ package org.apache.fop.afp.svg;

import java.awt.Color;
import java.awt.Graphics2D;
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.AFPResourceManager;
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.fonts.CharacterSet;
import org.apache.fop.afp.modca.GraphicsObject;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
@@ -50,13 +53,17 @@ public class AFPTextHandler extends FOPTextHandlerAdapter {
/** Font information */
private final FontInfo fontInfo;

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

/**
* Main constructor.
*
* @param fontInfo the AFPGraphics2D instance
*/
public AFPTextHandler(FontInfo fontInfo) {
public AFPTextHandler(FontInfo fontInfo, AFPResourceManager resourceManager) {
this.fontInfo = fontInfo;
this.resourceManager = resourceManager;
}

/**
@@ -83,6 +90,14 @@ public class AFPTextHandler extends FOPTextHandlerAdapter {
afpFont,
fontSize
);
if (afpFont.isEmbeddable()) {
try {
final CharacterSet charSet = afpFont.getCharacterSet(fontSize);
this.resourceManager.embedFont(afpFont, charSet);
} catch (IOException ioe) {
throw new RuntimeException("Error while embedding font resources", ioe);
}
}
return afpFontAttributes.getFontReference();
}

@@ -92,6 +107,7 @@ public class AFPTextHandler extends FOPTextHandlerAdapter {
*
* {@inheritDoc}
*/
@Override
public void drawString(Graphics2D g, String str, float x, float y) {
if (log.isDebugEnabled()) {
log.debug("drawString() str=" + str + ", x=" + x + ", y=" + y);
@@ -115,9 +131,15 @@ public class AFPTextHandler extends FOPTextHandlerAdapter {
if (overrideFont != null) {
internalFontName = overrideFont.getFontName();
fontSize = overrideFont.getFontSize();
if (log.isDebugEnabled()) {
log.debug(" with overriding font: " + internalFontName + ", " + fontSize);
}
} else {
java.awt.Font awtFont = g2d.getFont();
Font fopFont = fontInfo.getFontInstanceForAWTFont(awtFont);
if (log.isDebugEnabled()) {
log.debug(" with font: " + fopFont);
}
internalFontName = fopFont.getFontName();
fontSize = fopFont.getFontSize();
}

+ 139
- 4
src/java/org/apache/fop/svg/ACIUtils.java Ver arquivo

@@ -19,29 +19,164 @@

package org.apache.fop.svg;

import java.awt.font.TextAttribute;
import java.text.AttributedCharacterIterator;
import java.text.CharacterIterator;
import java.util.Iterator;
import java.text.AttributedCharacterIterator.Attribute;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import org.apache.batik.bridge.SVGFontFamily;
import org.apache.batik.gvt.font.GVTFont;
import org.apache.batik.gvt.font.GVTFontFamily;
import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
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;

/**
* Utilities for java.text.AttributedCharacterIterator.
*/
public final class ACIUtils {

/** the logger for this class */
private static final Log LOG = LogFactory.getLog(ACIUtils.class);

private ACIUtils() {
//This class shouldn't be instantiated.
}

/**
* Tries to find matching fonts in FOP's {@link FontInfo} instance for fonts used by
* Apache Batik. The method inspects the various GVT attributes found in the ACI.
* @param aci the ACI to find matching fonts for
* @param fontInfo the font info instance with FOP's fonts
* @return an array of matching fonts
*/
public static Font[] findFontsForBatikACI(AttributedCharacterIterator aci, FontInfo fontInfo) {
List<Font> fonts = new java.util.ArrayList<Font>();
@SuppressWarnings("unchecked")
List<GVTFontFamily> gvtFonts = (List<GVTFontFamily>) aci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
Float posture = (Float) aci.getAttribute(TextAttribute.POSTURE);
Float taWeight = (Float) aci.getAttribute(TextAttribute.WEIGHT);
Float fontSize = (Float) aci.getAttribute(TextAttribute.SIZE);

String style = toStyle(posture);
int weight = toCSSWeight(taWeight);
int fsize = (int)(fontSize.floatValue() * 1000);

String firstFontFamily = null;

//GVT_FONT can sometimes be different from the fonts in GVT_FONT_FAMILIES
//or GVT_FONT_FAMILIES can even be empty and only GVT_FONT is set
/* The following code section is not available until Batik 1.7 is released. */
GVTFont gvtFont = (GVTFont)aci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.GVT_FONT);
if (gvtFont != null) {
try {
String gvtFontFamily = gvtFont.getFamilyName(); //Not available in Batik 1.6!
if (fontInfo.hasFont(gvtFontFamily, style, weight)) {
FontTriplet triplet = fontInfo.fontLookup(gvtFontFamily, style,
weight);
Font f = fontInfo.getFontInstance(triplet, fsize);
if (LOG.isDebugEnabled()) {
LOG.debug("Found a font that matches the GVT font: "
+ gvtFontFamily + ", " + weight + ", " + style
+ " -> " + f);
}
fonts.add(f);
}
firstFontFamily = gvtFontFamily;
} catch (Exception e) {
//Most likely NoSuchMethodError here when using Batik 1.6
//Just skip this section in this case
}
}

if (gvtFonts != null) {
for (GVTFontFamily fam : gvtFonts) {
if (fam instanceof SVGFontFamily) {
return null; //Let Batik paint this text!
}
String fontFamily = fam.getFamilyName();
if (fontInfo.hasFont(fontFamily, style, weight)) {
FontTriplet triplet = fontInfo.fontLookup(fontFamily, style,
weight);
Font f = fontInfo.getFontInstance(triplet, fsize);
if (LOG.isDebugEnabled()) {
LOG.debug("Found a font that matches the GVT font family: "
+ fontFamily + ", " + weight + ", " + style
+ " -> " + f);
}
fonts.add(f);
}
if (firstFontFamily == null) {
firstFontFamily = fontFamily;
}
}
}
if (fonts.isEmpty()) {
if (firstFontFamily == null) {
//This will probably never happen. Just to be on the safe side.
firstFontFamily = "any";
}
//lookup with fallback possibility (incl. substitution notification)
FontTriplet triplet = fontInfo.fontLookup(firstFontFamily, style, weight);
Font f = fontInfo.getFontInstance(triplet, fsize);
if (LOG.isDebugEnabled()) {
LOG.debug("Falling back to adjustable font lookup up for: "
+ firstFontFamily + ", " + weight + ", " + style
+ " -> " + f);
}
fonts.add(f);
}
return fonts.toArray(new Font[fonts.size()]);
}

private static int toCSSWeight(Float weight) {
if (weight == null) {
return 400;
} else if (weight <= TextAttribute.WEIGHT_EXTRA_LIGHT.floatValue()) {
return 100;
} else if (weight <= TextAttribute.WEIGHT_LIGHT.floatValue()) {
return 200;
} else if (weight <= TextAttribute.WEIGHT_DEMILIGHT.floatValue()) {
return 300;
} else if (weight <= TextAttribute.WEIGHT_REGULAR.floatValue()) {
return 400;
} else if (weight <= TextAttribute.WEIGHT_SEMIBOLD.floatValue()) {
return 500;
} else if (weight <= TextAttribute.WEIGHT_BOLD.floatValue()) {
return 600;
} else if (weight <= TextAttribute.WEIGHT_HEAVY.floatValue()) {
return 700;
} else if (weight <= TextAttribute.WEIGHT_EXTRABOLD.floatValue()) {
return 800;
} else {
return 900;
}
}

private static String toStyle(Float posture) {
return ((posture != null) && (posture.floatValue() > 0.0))
? Font.STYLE_ITALIC
: Font.STYLE_NORMAL;
}

/**
* Dumps the contents of an ACI to System.out. Used for debugging only.
* @param aci the ACI to dump
*/
public static void dumpAttrs(AttributedCharacterIterator aci) {
aci.first();
Iterator i = aci.getAttributes().entrySet().iterator();
while (i.hasNext()) {
Map.Entry entry = (Map.Entry)i.next();
Set<Entry<Attribute, Object>> entries = aci.getAttributes().entrySet();
for (Map.Entry<Attribute, Object> entry : entries) {
if (entry.getValue() != null) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}

+ 2
- 49
src/java/org/apache/fop/svg/AbstractFOPTextPainter.java Ver arquivo

@@ -36,7 +36,6 @@ 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;
@@ -46,8 +45,6 @@ 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;

/**
* Renders the attributed character iterator of a {@link TextNode}.
@@ -336,53 +333,9 @@ public abstract class AbstractFOPTextPainter implements TextPainter {
}
}

private String getStyle(AttributedCharacterIterator aci) {
Float posture = (Float)aci.getAttribute(TextAttribute.POSTURE);
return ((posture != null) && (posture.floatValue() > 0.0))
? Font.STYLE_ITALIC
: Font.STYLE_NORMAL;
}

private int getWeight(AttributedCharacterIterator aci) {
Float taWeight = (Float)aci.getAttribute(TextAttribute.WEIGHT);
return ((taWeight != null) && (taWeight.floatValue() > 1.0))
? Font.WEIGHT_BOLD
: Font.WEIGHT_NORMAL;
}

private Font getFont(AttributedCharacterIterator aci) {
Float fontSize = (Float)aci.getAttribute(TextAttribute.SIZE);
if (fontSize == null) {
fontSize = new Float(10f);
}
String style = getStyle(aci);
int weight = getWeight(aci);

FontInfo fontInfo = nativeTextHandler.getFontInfo();
String fontFamily = null;
List gvtFonts = (List) aci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
if (gvtFonts != null) {
Iterator i = gvtFonts.iterator();
while (i.hasNext()) {
GVTFontFamily fam = (GVTFontFamily) i.next();
/* (todo) Enable SVG Font painting
if (fam instanceof SVGFontFamily) {
PROXY_PAINTER.paint(node, g2d);
return;
}*/
fontFamily = fam.getFamilyName();
if (fontInfo.hasFont(fontFamily, style, weight)) {
FontTriplet triplet = fontInfo.fontLookup(
fontFamily, style, weight);
int fsize = (int)(fontSize.floatValue() * 1000);
return fontInfo.getFontInstance(triplet, fsize);
}
}
}
FontTriplet triplet = fontInfo.fontLookup("any", style, Font.WEIGHT_NORMAL);
int fsize = (int)(fontSize.floatValue() * 1000);
return fontInfo.getFontInstance(triplet, fsize);
Font[] fonts = ACIUtils.findFontsForBatikACI(aci, nativeTextHandler.getFontInfo());
return fonts[0];
}

private float getStringWidth(String str, Font font) {

+ 3
- 101
src/java/org/apache/fop/svg/NativeTextPainter.java Ver arquivo

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

import java.awt.Graphics2D;
import java.awt.font.TextAttribute;
import java.io.IOException;
import java.text.AttributedCharacterIterator;
import java.util.Iterator;
import java.util.List;

import org.apache.batik.bridge.SVGFontFamily;
import org.apache.batik.gvt.font.GVTFont;
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.TextSpanLayout;
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.fop.util.CharUtilities;

/**
@@ -77,6 +70,7 @@ public abstract class NativeTextPainter extends StrokingTextPainter {
protected abstract void paintTextRun(TextRun textRun, Graphics2D g2d) throws IOException;

/** {@inheritDoc} */
@Override
protected void paintTextRuns(List textRuns, Graphics2D g2d) {
if (log.isTraceEnabled()) {
log.trace("paintTextRuns: count = " + textRuns.size());
@@ -102,100 +96,8 @@ public abstract class NativeTextPainter extends StrokingTextPainter {
* @return the array of fonts
*/
protected Font[] findFonts(AttributedCharacterIterator aci) {
List fonts = new java.util.ArrayList();
List gvtFonts = (List) aci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES);
Float posture = (Float) aci.getAttribute(TextAttribute.POSTURE);
Float taWeight = (Float) aci.getAttribute(TextAttribute.WEIGHT);
Float fontSize = (Float) aci.getAttribute(TextAttribute.SIZE);

String style = ((posture != null) && (posture.floatValue() > 0.0))
? Font.STYLE_ITALIC : Font.STYLE_NORMAL;
int weight = toCSSWeight(taWeight != null
? taWeight.floatValue()
: TextAttribute.WEIGHT_REGULAR.floatValue());

String firstFontFamily = null;

//GVT_FONT can sometimes be different from the fonts in GVT_FONT_FAMILIES
//or GVT_FONT_FAMILIES can even be empty and only GVT_FONT is set
/* The following code section is not available until Batik 1.7 is released. */
GVTFont gvtFont = (GVTFont)aci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.GVT_FONT);
if (gvtFont != null) {
try {
String gvtFontFamily = gvtFont.getFamilyName(); //Not available in Batik 1.6!
if (log.isDebugEnabled()) {
log.debug("Matching font family: " + gvtFontFamily);
}
if (fontInfo.hasFont(gvtFontFamily, style, weight)) {
FontTriplet triplet = fontInfo.fontLookup(gvtFontFamily, style,
weight);
int fsize = (int)(fontSize.floatValue() * 1000);
fonts.add(fontInfo.getFontInstance(triplet, fsize));
}
firstFontFamily = gvtFontFamily;
} catch (Exception e) {
//Most likely NoSuchMethodError here when using Batik 1.6
//Just skip this section in this case
}
}

if (gvtFonts != null) {
Iterator i = gvtFonts.iterator();
while (i.hasNext()) {
GVTFontFamily fam = (GVTFontFamily) i.next();
if (fam instanceof SVGFontFamily) {
return null; //Let Batik paint this text!
}
String fontFamily = fam.getFamilyName();
if (log.isDebugEnabled()) {
log.debug("Matching font family: " + fontFamily);
}
if (fontInfo.hasFont(fontFamily, style, weight)) {
FontTriplet triplet = fontInfo.fontLookup(fontFamily, style,
weight);
int fsize = (int)(fontSize.floatValue() * 1000);
fonts.add(fontInfo.getFontInstance(triplet, fsize));
}
if (firstFontFamily == null) {
firstFontFamily = fontFamily;
}
}
}
if (fonts.size() == 0) {
if (firstFontFamily == null) {
//This will probably never happen. Just to be on the safe side.
firstFontFamily = "any";
}
//lookup with fallback possibility (incl. substitution notification)
FontTriplet triplet = fontInfo.fontLookup(firstFontFamily, style, weight);
int fsize = (int)(fontSize.floatValue() * 1000);
fonts.add(fontInfo.getFontInstance(triplet, fsize));
}
return (Font[])fonts.toArray(new Font[fonts.size()]);
}

private int toCSSWeight(float weight) {
if (weight <= TextAttribute.WEIGHT_EXTRA_LIGHT.floatValue()) {
return 100;
} else if (weight <= TextAttribute.WEIGHT_LIGHT.floatValue()) {
return 200;
} else if (weight <= TextAttribute.WEIGHT_DEMILIGHT.floatValue()) {
return 300;
} else if (weight <= TextAttribute.WEIGHT_REGULAR.floatValue()) {
return 400;
} else if (weight <= TextAttribute.WEIGHT_SEMIBOLD.floatValue()) {
return 500;
} else if (weight <= TextAttribute.WEIGHT_BOLD.floatValue()) {
return 600;
} else if (weight <= TextAttribute.WEIGHT_HEAVY.floatValue()) {
return 700;
} else if (weight <= TextAttribute.WEIGHT_EXTRABOLD.floatValue()) {
return 800;
} else {
return 900;
}
Font[] fonts = ACIUtils.findFontsForBatikACI(aci, fontInfo);
return fonts;
}

/**

+ 7
- 0
status.xml Ver arquivo

@@ -59,6 +59,13 @@
documents. Example: the fix of marks layering will be such a case when it's done.
-->
<release version="FOP Trunk" date="TBD">
<action context="Renderers" dev="JM" type="fix">
AFP GOCA: fonts were not embedded from within AFPGraphics2D.
</action>
<action context="Renderers" dev="JM" type="fix">
AFP GOCA: Changed the way FOP fonts are selected based on Batik's GVT fonts to match
the behaviour of PDF/PS output.
</action>
<action context="Renderers" dev="JM" type="add">
Added option to place AFP NOPs right before the end of a named page group (page-sequence),
rather than after the start.

Carregando…
Cancelar
Salvar