Browse Source

Improved font selection strategy when matching AWT Font against FontTriplet.

Fonts looking too big still when processed through AFPTextHandler.


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AFPGOCAResources@711563 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-1_0
Adrian Cumiskey 15 years ago
parent
commit
9db4cd2992

+ 37
- 12
src/java/org/apache/fop/afp/AFPTextHandler.java View File

@@ -51,6 +51,7 @@ public class AFPTextHandler implements TextHandler {

/**
* Main constructor.
*
* @param g2d the AFPGraphics2D instance
*/
public AFPTextHandler(AFPGraphics2D g2d) {
@@ -66,6 +67,27 @@ public class AFPTextHandler implements TextHandler {
return g2d.getFontInfo();
}

/**
* Registers a page font
*
* @param internalFontName the internal font name
* @param fontSize the font size
* @return a font reference
*/
private int registerPageFont(String internalFontName, int fontSize) {
FontInfo fontInfo = getFontInfo();
AFPFont afpFont = (AFPFont)fontInfo.getFonts().get(internalFontName);
AFPPaintingState paintingState = g2d.getPaintingState();
AFPPageFonts pageFonts = paintingState.getPageFonts();
// register if necessary
AFPFontAttributes afpFontAttributes = pageFonts.registerFont(
internalFontName,
afpFont,
fontSize
);
return afpFontAttributes.getFontReference();
}

/**
* Add a text string to the current data object of the AFP datastream.
* The text is painted using text operations.
@@ -77,26 +99,28 @@ public class AFPTextHandler implements TextHandler {
GraphicsObject graphicsObj = g2d.getGraphicsObject();
Color color = g2d.getColor();

// set the color
AFPPaintingState paintingState = g2d.getPaintingState();
if (paintingState.setColor(color)) {
graphicsObj.setColor(color);
}

// set the character set
int fontReference = 0;
if (overrideFont != null) {
FontInfo fontInfo = getFontInfo();
AFPPageFonts pageFonts = paintingState.getPageFonts();
String internalFontName = overrideFont.getFontName();
int fontSize = overrideFont.getFontSize();
if (paintingState.setFontName(internalFontName) || paintingState.setFontSize(fontSize)) {
AFPFont font = (AFPFont)fontInfo.getFonts().get(internalFontName);
AFPFontAttributes afpFontAttributes = pageFonts.registerFont(
internalFontName,
font,
fontSize
);
int fontReference = afpFontAttributes.getFontReference();
graphicsObj.setCharacterSet(fontReference);
}
fontReference = registerPageFont(internalFontName, fontSize);
} else {
java.awt.Font awtFont = g2d.getFont();
AffineTransform fontTransform = awtFont.getTransform();
FontInfo fontInfo = getFontInfo();
Font fopFont = fontInfo.getFontInstanceForAWTFont(awtFont);
String internalFontName = fopFont.getFontName();
int fontSize = fopFont.getFontSize();
fontReference = registerPageFont(internalFontName, fontSize);
}
graphicsObj.setCharacterSet(fontReference);

// calculate x, y plotting coordinates from graphics context
AffineTransform at = g2d.getTransform();
@@ -104,6 +128,7 @@ public class AFPTextHandler implements TextHandler {
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]));
}


+ 60
- 61
src/java/org/apache/fop/afp/AFPTextPainter.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.
@@ -19,34 +19,33 @@

package org.apache.fop.afp;

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.Point2D;
import java.awt.geom.Rectangle2D;
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.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.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;


/**
* Renders the attributed character iterator of a <tt>TextNode</tt>.
@@ -57,17 +56,17 @@ import org.apache.batik.gvt.renderer.StrokingTextPainter;
* into a simple drawString the StrokingTextPainter is used instead.
*/
public class AFPTextPainter implements TextPainter {
/** the logger for this class */
protected Log log = LogFactory.getLog(AFPTextPainter.class);
private AFPTextHandler nativeTextHandler;
private final AFPTextHandler nativeTextHandler;

/**
* Use the stroking text painter to get the bounds and shape.
* Also used as a fallback to draw the string with strokes.
*/
protected static final TextPainter
protected static final TextPainter
PROXY_PAINTER = StrokingTextPainter.getInstance();

/**
@@ -95,11 +94,11 @@ public class AFPTextPainter implements TextPainter {
paintTextRuns(node.getTextRuns(), g2d, loc);
}
}
private boolean hasUnsupportedAttributes(TextNode node) {
Iterator iter = node.getTextRuns().iterator();
while (iter.hasNext()) {
StrokingTextPainter.TextRun
StrokingTextPainter.TextRun
run = (StrokingTextPainter.TextRun)iter.next();
AttributedCharacterIterator aci = run.getACI();
boolean hasUnsupported = hasUnsupportedAttributes(aci);
@@ -111,24 +110,24 @@ public class AFPTextPainter implements TextPainter {
}

private boolean hasUnsupportedAttributes(AttributedCharacterIterator aci) {
boolean hasunsupported = false;
boolean hasUnsupported = false;
String text = getText(aci);
Font font = makeFont(aci);
if (hasUnsupportedGlyphs(text, font)) {
log.trace("-> Unsupported glyphs found");
hasunsupported = true;
hasUnsupported = true;
}
TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
if ((tpi != null)
if ((tpi != null)
&& ((tpi.strokeStroke != null && tpi.strokePaint != null)
|| (tpi.strikethroughStroke != null)
|| (tpi.underlineStroke != null)
|| (tpi.overlineStroke != null))) {
log.trace("-> under/overlines etc. found");
hasunsupported = true;
hasUnsupported = true;
}

//Alpha is not supported
@@ -137,7 +136,7 @@ public class AFPTextPainter implements TextPainter {
Color col = (Color)foreground;
if (col.getAlpha() != 255) {
log.trace("-> transparency found");
hasunsupported = true;
hasUnsupported = true;
}
}

@@ -145,30 +144,30 @@ public class AFPTextPainter implements TextPainter {
GVTAttributedCharacterIterator.TextAttribute.LETTER_SPACING);
if (letSpace != null) {
log.trace("-> letter spacing found");
hasunsupported = true;
hasUnsupported = true;
}

Object wordSpace = aci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.WORD_SPACING);
if (wordSpace != null) {
log.trace("-> word spacing found");
hasunsupported = true;
hasUnsupported = true;
}
Object lengthAdjust = aci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.LENGTH_ADJUST);
if (lengthAdjust != null) {
log.trace("-> length adjustments found");
hasunsupported = true;
hasUnsupported = true;
}

Object writeMod = aci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE);
if (writeMod != null
if (writeMod != null
&& !GVTAttributedCharacterIterator.TextAttribute.WRITING_MODE_LTR.equals(
writeMod)) {
log.trace("-> Unsupported writing modes found");
hasunsupported = true;
hasUnsupported = true;
}

Object vertOr = aci.getAttribute(
@@ -176,22 +175,22 @@ public class AFPTextPainter implements TextPainter {
if (GVTAttributedCharacterIterator.TextAttribute.ORIENTATION_ANGLE.equals(
vertOr)) {
log.trace("-> vertical orientation found");
hasunsupported = true;
hasUnsupported = true;
}
Object rcDel = aci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER);
//Batik 1.6 returns null here which makes it impossible to determine whether this can
//be painted or not, i.e. fall back to stroking. :-(
if (rcDel != null && !(rcDel instanceof SVGOMTextElement)) {
log.trace("-> spans found");
hasunsupported = true; //Filter spans
hasUnsupported = true; //Filter spans
}
if (hasunsupported) {
if (hasUnsupported) {
log.trace("Unsupported attributes found in ACI, using StrokingTextPainter");
}
return hasunsupported;
return hasUnsupported;
}

/**
@@ -204,7 +203,7 @@ public class AFPTextPainter implements TextPainter {
Point2D currentloc = loc;
Iterator i = textRuns.iterator();
while (i.hasNext()) {
StrokingTextPainter.TextRun
StrokingTextPainter.TextRun
run = (StrokingTextPainter.TextRun)i.next();
currentloc = paintTextRun(run, g2d, currentloc);
}
@@ -227,7 +226,7 @@ public class AFPTextPainter implements TextPainter {
// font
Font font = makeFont(aci);
nativeTextHandler.setOverrideFont(font);
// color
TextPaintInfo tpi = (TextPaintInfo) aci.getAttribute(
GVTAttributedCharacterIterator.TextAttribute.PAINT_INFO);
@@ -240,7 +239,7 @@ public class AFPTextPainter implements TextPainter {
g2d.setColor(col);
}
g2d.setPaint(foreground);
String txt = getText(aci);
float advance = getStringWidth(txt, font);
float tx = 0;
@@ -270,7 +269,7 @@ public class AFPTextPainter implements TextPainter {
} finally {
nativeTextHandler.setOverrideFont(null);
}
loc.setLocation(loc.getX() + (double)advance, loc.getY());
loc.setLocation(loc.getX() + advance, loc.getY());
return loc;
}

@@ -304,25 +303,25 @@ public class AFPTextPainter implements TextPainter {
}
if (ypos != null) {
loc.setLocation(loc.getX(), ypos.doubleValue());
}
}
if (dxpos != null) {
loc.setLocation(loc.getX() + dxpos.doubleValue(), loc.getY());
}
}
if (dypos != null) {
loc.setLocation(loc.getX(), loc.getY() + dypos.doubleValue());
}
}
}

private String getStyle(AttributedCharacterIterator aci) {
Float posture = (Float)aci.getAttribute(TextAttribute.POSTURE);
return ((posture != null) && (posture.floatValue() > 0.0))
? "italic"
: "normal";
? 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))
return ((taWeight != null) && (taWeight.floatValue() > 1.0))
? Font.WEIGHT_BOLD
: Font.WEIGHT_NORMAL;
}
@@ -415,8 +414,8 @@ public class AFPTextPainter implements TextPainter {
* @return the bounds of the text
*/
public Rectangle2D getBounds2D(TextNode node) {
/* (todo) getBounds2D() is too slow
* because it uses the StrokingTextPainter. We should implement this
/* (todo) getBounds2D() is too slow
* because it uses the StrokingTextPainter. We should implement this
* method ourselves. */
return PROXY_PAINTER.getBounds2D(node);
}
@@ -436,7 +435,7 @@ public class AFPTextPainter implements TextPainter {

/**
* Get the mark.
* This does nothing since the output is pdf and not interactive.
* 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,7 +447,7 @@ public class AFPTextPainter implements TextPainter {

/**
* Select at.
* This does nothing since the output is pdf and not interactive.
* 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,7 +459,7 @@ public class AFPTextPainter implements TextPainter {

/**
* Select to.
* This does nothing since the output is pdf and not interactive.
* 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,7 +471,7 @@ public class AFPTextPainter implements TextPainter {

/**
* Selec first.
* This does nothing since the output is pdf and not interactive.
* This does nothing since the output is AFP and not interactive.
* @param node the text node
* @return null
*/
@@ -482,7 +481,7 @@ public class AFPTextPainter implements TextPainter {

/**
* Select last.
* This does nothing since the output is pdf and not interactive.
* This does nothing since the output is AFP and not interactive.
* @param node the text node
* @return null
*/
@@ -492,7 +491,7 @@ public class AFPTextPainter implements TextPainter {

/**
* Get selected.
* This does nothing since the output is pdf and not interactive.
* This does nothing since the output is AFP and not interactive.
* @param start the start mark
* @param finish the finish mark
* @return null
@@ -503,7 +502,7 @@ public class AFPTextPainter implements TextPainter {

/**
* Get the highlighted shape.
* This does nothing since the output is pdf and not interactive.
* This does nothing since the output is AFP and not interactive.
* @param beginMark the start mark
* @param endMark the end mark
* @return null

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

@@ -318,6 +318,7 @@ public class FontInfo {

/**
* Retrieves a (possibly cached) Font instance based on a FontTriplet and a font size.
*
* @param triplet the font triplet designating the requested font
* @param fontSize the font size
* @return the requested Font instance
@@ -341,6 +342,57 @@ public class FontInfo {
return font;
}

private List/*<FontTriplet>*/ getTripletsForName(String fontName) {
List/*<FontTriplet>*/ matchedTriplets = new java.util.ArrayList/*<FontTriplet>*/();
Iterator it = triplets.keySet().iterator();
while (it.hasNext()) {
FontTriplet triplet = (FontTriplet)it.next();
String tripletName = triplet.getName();
if (tripletName.toLowerCase().equals(fontName.toLowerCase())) {
matchedTriplets.add(triplet);
}
}
return matchedTriplets;
}

/**
* Returns a suitable internal font given an AWT Font instance.
*
* @param awtFont the AWT font
* @return a best matching internal Font
*/
public Font getFontInstanceForAWTFont(java.awt.Font awtFont) {
String awtFontName = awtFont.getName();
String awtFontFamily = awtFont.getFamily();
String awtFontStyle = awtFont.isItalic() ? Font.STYLE_ITALIC : Font.STYLE_NORMAL;
int awtFontWeight = awtFont.isBold() ? Font.WEIGHT_BOLD : Font.WEIGHT_NORMAL;

FontTriplet matchedTriplet = null;
List/*<FontTriplet>*/ triplets = getTripletsForName(awtFontName);
if (!triplets.isEmpty()) {
Iterator it = triplets.iterator();
while (it.hasNext()) {
FontTriplet triplet = (FontTriplet)it.next();
boolean styleMatched = triplet.getStyle().equals(awtFontStyle);
boolean weightMatched = triplet.getWeight() == awtFontWeight;
if (styleMatched && weightMatched) {
matchedTriplet = triplet;
break;
}
}
}

// not matched on font name so do a lookup using family
if (matchedTriplet == null) {
if (awtFontFamily.equals("sanserif")) {
awtFontFamily = "sans-serif";
}
matchedTriplet = fontLookup(awtFontFamily, awtFontStyle, awtFontWeight);
}
float awtFontSize = awtFont.getSize2D();
return getFontInstance(matchedTriplet, (int)(awtFontSize * 1000 + 0.5));
}

/**
* Lookup a font.
* <br>

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

@@ -1325,7 +1325,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
if (ovFontState == null) {
java.awt.Font gFont = getFont();
fontTransform = gFont.getTransform();
fontState = getInternalFontForAWTFont(gFont);
fontState = fontInfo.getFontInstanceForAWTFont(gFont);
} else {
fontState = fontInfo.getFontInstance(
ovFontState.getFontTriplet(), ovFontState.getFontSize());

Loading…
Cancel
Save