You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by je...@apache.org on 2008/03/27 09:49:44 UTC
svn commit: r641742 [2/2] - in /xmlgraphics/fop/trunk: ./ lib/
src/codegen/fonts/ src/java/org/apache/fop/fo/properties/
src/java/org/apache/fop/fonts/ src/java/org/apache/fop/fonts/truetype/
src/java/org/apache/fop/fonts/type1/ src/java/org/apache/fop...
Copied: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFTextUtil.java (from r631256, xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java)
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFTextUtil.java?p2=xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFTextUtil.java&p1=xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java&r1=631256&r2=641742&rev=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFTextUtil.java Thu Mar 27 01:49:41 2008
@@ -17,18 +17,15 @@
/* $Id$ */
-package org.apache.fop.svg;
+package org.apache.fop.pdf;
import java.awt.geom.AffineTransform;
-import org.apache.fop.fonts.Font;
-import org.apache.fop.pdf.PDFNumber;
-import org.apache.fop.pdf.PDFText;
-
/**
- * Utility class for generating PDF text objects.
+ * Utility class for generating PDF text objects. It needs to be subclassed to add writing
+ * functionality (see {@link #write(String)}).
*/
-public class PDFTextUtil {
+public abstract class PDFTextUtil {
/** The number of decimal places. */
private static final int DEC = 8;
@@ -50,25 +47,29 @@
/** PDF text rendering mode: Add text to path for clipping */
public static final int TR_CLIP = 7;
-
- private PDFGraphics2D g2d;
private boolean inTextObject = false;
- private Font[] fonts;
- private Font font;
private String startText;
private String endText;
private boolean useMultiByte;
private StringBuffer bufTJ;
- private int textRenderingMode = 0;
+ private int textRenderingMode = TR_FILL;
+
+ private String currentFontName;
+ private double currentFontSize;
/**
* Main constructor.
- * @param g2d the PDFGraphics2D instance to work with
*/
- public PDFTextUtil(PDFGraphics2D g2d) {
- this.g2d = g2d;
+ public PDFTextUtil() {
+ //nop
}
+ /**
+ * Writes PDF code.
+ * @param code the PDF code to write
+ */
+ protected abstract void write(String code);
+
private void writeAffineTransform(AffineTransform at, StringBuffer sb) {
double[] lt = new double[6];
at.getMatrix(lt);
@@ -82,7 +83,7 @@
private void writeChar(char ch, StringBuffer sb) {
if (!useMultiByte) {
- if (ch > 127) {
+ if (ch < 32 || ch > 127) {
sb.append("\\").append(Integer.toOctalString((int)ch));
} else {
switch (ch) {
@@ -107,6 +108,14 @@
}
/**
+ * Indicates whether we are in a text object or not.
+ * @return true if we are in a text object
+ */
+ public boolean isInTextObject() {
+ return inTextObject;
+ }
+
+ /**
* Called when a new text object should be started. Be sure to call setFont() before
* issuing any text painting commands.
*/
@@ -114,7 +123,7 @@
if (inTextObject) {
throw new IllegalStateException("Already in text object");
}
- g2d.currentStream.write("BT\n");
+ write("BT\n");
this.inTextObject = true;
}
@@ -123,13 +132,17 @@
*/
public void endTextObject() {
checkInTextObject();
- g2d.currentStream.write("ET\n");
+ write("ET\n");
this.inTextObject = false;
initValues();
}
- private void initValues() {
- this.font = null;
+ /**
+ * Resets the state fields.
+ */
+ protected void initValues() {
+ this.currentFontName = null;
+ this.currentFontSize = 0.0;
this.textRenderingMode = TR_FILL;
}
@@ -137,7 +150,7 @@
* Creates a "q" command, pushing a copy of the entire graphics state onto the stack.
*/
public void saveGraphicsState() {
- g2d.currentStream.write("q\n");
+ write("q\n");
}
/**
@@ -145,70 +158,54 @@
* it from the stack.
*/
public void restoreGraphicsState() {
- g2d.currentStream.write("Q\n");
+ write("Q\n");
}
/**
- * Creates a "cm" command using the current transformation as the matrix.
+ * Creates a "cm" command.
+ * @param at the transformation matrix
*/
- public void concatMatrixCurrentTransform() {
- StringBuffer sb = new StringBuffer();
- if (!g2d.getTransform().isIdentity()) {
- writeAffineTransform(g2d.getTransform(), sb);
+ public void concatMatrix(AffineTransform at) {
+ if (!at.isIdentity()) {
+ writeTJ();
+ StringBuffer sb = new StringBuffer();
+ writeAffineTransform(at, sb);
sb.append(" cm\n");
+ write(sb.toString());
}
- g2d.currentStream.write(sb.toString());
- }
-
- /**
- * Sets the current fonts for the text object. For every character, the suitable font will
- * be selected.
- * @param fonts the new fonts
- */
- public void setFonts(Font[] fonts) {
- this.fonts = fonts;
- }
-
- /**
- * Sets the current font for the text object.
- * @param font the new font
- */
- public void setFont(Font font) {
- setFonts(new Font[] {font});
- }
-
- /**
- * Returns the current font in use.
- * @return the current font or null if no font is currently active.
- */
- public Font getCurrentFont() {
- return this.font;
- }
-
- /**
- * Sets the current font.
- * @param f the new font to use
- */
- public void setCurrentFont(Font f) {
- this.font = f;
}
/**
* Writes a "Tf" command, setting a new current font.
- * @param f the font to select
+ * @param fontName the name of the font to select
+ * @param fontSize the font size (in points)
*/
- public void writeTf(Font f) {
+ public void writeTf(String fontName, double fontSize) {
checkInTextObject();
- String fontName = f.getFontName();
- float fontSize = (float)f.getFontSize() / 1000f;
- g2d.currentStream.write("/" + fontName + " " + PDFNumber.doubleOut(fontSize) + " Tf\n");
+ write("/" + fontName + " " + PDFNumber.doubleOut(fontSize) + " Tf\n");
- this.useMultiByte = g2d.isMultiByteFont(fontName);
this.startText = useMultiByte ? "<" : "(";
this.endText = useMultiByte ? ">" : ")";
}
/**
+ * Updates the current font. This method only writes a "Tf" if the current font changes.
+ * @param fontName the name of the font to select
+ * @param fontSize the font size (in points)
+ * @param multiByte true indicates the font is a multi-byte font, false means single-byte
+ */
+ public void updateTf(String fontName, double fontSize, boolean multiByte) {
+ checkInTextObject();
+ if (!fontName.equals(this.currentFontName) || (fontSize != this.currentFontSize)) {
+ writeTJ();
+ this.currentFontName = fontName;
+ this.currentFontSize = fontSize;
+ this.useMultiByte = multiByte;
+ writeTf(fontName, fontSize);
+ }
+ }
+
+ /**
* Sets the text rendering mode.
* @param mode the rendering mode (value 0 to 7, see PDF Spec, constants: TR_*)
*/
@@ -218,8 +215,9 @@
"Illegal value for text rendering mode. Expected: 0-7");
}
if (mode != this.textRenderingMode) {
+ writeTJ();
this.textRenderingMode = mode;
- g2d.currentStream.write(this.textRenderingMode + " Tr\n");
+ write(this.textRenderingMode + " Tr\n");
}
}
@@ -249,37 +247,22 @@
public void writeTextMatrix(AffineTransform localTransform) {
StringBuffer sb = new StringBuffer();
writeAffineTransform(localTransform, sb);
- sb.append(" Tm\n");
- g2d.currentStream.write(sb.toString());
+ sb.append(" Tm ");
+ write(sb.toString());
}
/**
- * Selects a font from the font list suitable to display the given character.
- * @param ch the character
- * @return the recommended Font to use
- */
- public Font selectFontForChar(char ch) {
- for (int i = 0, c = fonts.length; i < c; i++) {
- if (fonts[i].hasChar(ch)) {
- return fonts[i];
- }
- }
- return fonts[0]; //TODO Maybe fall back to painting with shapes
- }
-
- /**
* Writes a char to the "TJ-Buffer".
- * @param ch the unmapped character
+ * @param codepoint the mapped character (code point/character code)
*/
- public void writeTJChar(char ch) {
+ public void writeTJMappedChar(char codepoint) {
if (bufTJ == null) {
bufTJ = new StringBuffer();
}
if (bufTJ.length() == 0) {
bufTJ.append("[").append(startText);
}
- char mappedChar = font.mapChar(ch);
- writeChar(mappedChar, bufTJ);
+ writeChar(codepoint, bufTJ);
}
/**
@@ -298,11 +281,15 @@
* positioning values. The buffer is reset afterwards.
*/
public void writeTJ() {
- if (bufTJ != null && bufTJ.length() > 0) {
+ if (isInString()) {
bufTJ.append(endText).append("] TJ\n");
- g2d.currentStream.write(bufTJ.toString());
+ write(bufTJ.toString());
bufTJ.setLength(0);
}
+ }
+
+ private boolean isInString() {
+ return bufTJ != null && bufTJ.length() > 0;
}
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java Thu Mar 27 01:49:41 2008
@@ -174,11 +174,8 @@
return charSet.mapChar(c);
}
- /**
- * Get the encoding of the font.
- * @return the encoding
- */
- public String getEncoding() {
+ /** {@inheritDoc} */
+ public String getEncodingName() {
return charSet.getEncoding();
}
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/RasterFont.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/RasterFont.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/RasterFont.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/afp/fonts/RasterFont.java Thu Mar 27 01:49:41 2008
@@ -25,6 +25,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.apache.fop.fo.properties.FixedLength;
import org.apache.fop.render.afp.exceptions.FontRuntimeException;
@@ -229,11 +230,8 @@
return charSet.mapChar(c);
}
- /**
- * Get the encoding of the font.
- * @return the encoding
- */
- public String getEncoding() {
+ /** {@inheritDoc} */
+ public String getEncodingName() {
return charSet.getEncoding();
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java Thu Mar 27 01:49:41 2008
@@ -112,7 +112,7 @@
}
/** {@inheritDoc} */
- public final String getEncoding() {
+ public final String getEncodingName() {
return null; //Not applicable to Java2D rendering
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java Thu Mar 27 01:49:41 2008
@@ -172,7 +172,7 @@
}
/** {@inheritDoc} */
- public String getEncoding() {
+ public String getEncodingName() {
return null; //Not applicable to Java2D rendering
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java Thu Mar 27 01:49:41 2008
@@ -89,8 +89,8 @@
PDFGraphics2D graphics = new PDFGraphics2D(textAsShapes,
pdfInfo.fi, pdfInfo.pdfDoc,
pdfInfo.pdfContext, pdfInfo.pdfPage.referencePDF(),
- renderer.currentFontName,
- renderer.currentFontSize);
+ pdfInfo.currentFontName,
+ pdfInfo.currentFontSize);
graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
AffineTransform transform = new AffineTransform();
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderer.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderer.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/pdf/PDFRenderer.java Thu Mar 27 01:49:41 2008
@@ -63,7 +63,6 @@
import org.apache.fop.area.OffDocumentItem;
import org.apache.fop.area.PageSequence;
import org.apache.fop.area.PageViewport;
-import org.apache.fop.area.RegionViewport;
import org.apache.fop.area.Trait;
import org.apache.fop.area.inline.AbstractTextArea;
import org.apache.fop.area.inline.Image;
@@ -78,6 +77,8 @@
import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.fop.fo.extensions.xmp.XMPMetadata;
import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.LazyFont;
+import org.apache.fop.fonts.SingleByteFont;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.pdf.PDFAMode;
import org.apache.fop.pdf.PDFAction;
@@ -106,7 +107,7 @@
import org.apache.fop.pdf.PDFResources;
import org.apache.fop.pdf.PDFState;
import org.apache.fop.pdf.PDFStream;
-import org.apache.fop.pdf.PDFText;
+import org.apache.fop.pdf.PDFTextUtil;
import org.apache.fop.pdf.PDFXMode;
import org.apache.fop.pdf.PDFXObject;
import org.apache.fop.render.AbstractPathOrientedRenderer;
@@ -250,21 +251,14 @@
/** drawing state */
protected PDFState currentState = null;
- /** Name of currently selected font */
- protected String currentFontName = "";
- /** Size of currently selected font */
- protected int currentFontSize = 0;
+ /** Text generation utility holding the current font status */
+ protected PDFTextUtil textutil;
/** page height */
protected int pageHeight;
/** Registry of PDF filters */
protected Map filterMap;
- /**
- * true if a BT command has been written.
- */
- protected boolean inTextMode = false;
-
/** Image handler registry */
private PDFImageHandlerRegistry imageHandlerRegistry = new PDFImageHandlerRegistry();
@@ -527,7 +521,7 @@
currentContext = null;
currentPage = null;
currentState = null;
- currentFontName = "";
+ this.textutil = null;
idPositions.clear();
idGoTos.clear();
@@ -665,19 +659,15 @@
/** Indicates the beginning of a text object. */
protected void beginTextObject() {
- if (!inTextMode) {
- currentStream.add("BT\n");
- currentFontName = "";
- inTextMode = true;
+ if (!textutil.isInTextObject()) {
+ textutil.beginTextObject();
}
}
/** Indicates the end of a text object. */
protected void endTextObject() {
- closeText();
- if (inTextMode) {
- currentStream.add("ET\n");
- inTextMode = false;
+ if (textutil.isInTextObject()) {
+ textutil.endTextObject();
}
}
@@ -787,6 +777,11 @@
currentStream = this.pdfDoc.getFactory()
.makeStream(PDFFilterList.CONTENT_FILTER, false);
+ this.textutil = new PDFTextUtil() {
+ protected void write(String code) {
+ currentStream.add(code);
+ }
+ };
currentState = new PDFState();
// Transform the PDF's default coordinate system (0,0 at lower left) to the PDFRenderer's
@@ -795,9 +790,6 @@
currentState.concatenate(basicPageTransform);
currentStream.add(CTMHelper.toPDFString(basicPageTransform, false) + " cm\n");
-
- currentFontName = "";
-
super.renderPage(page);
this.pdfDoc.registerObject(currentStream);
@@ -808,6 +800,7 @@
}
this.pdfDoc.addObject(currentPage);
this.pdfDoc.output(ostream);
+ this.textutil = null;
}
/** {@inheritDoc} */
@@ -841,17 +834,6 @@
}
/**
- * Handle the traits for a region
- * This is used to draw the traits for the given page region.
- * (See Sect. 6.4.1.2 of XSL-FO spec.)
- * @param region the RegionViewport whose region is to be drawn
- */
- protected void handleRegionTraits(RegionViewport region) {
- currentFontName = "";
- super.handleRegionTraits(region);
- }
-
- /**
* Formats a float value (normally coordinates) as Strings.
* @param value the value
* @return the formatted value
@@ -866,7 +848,8 @@
float w = x2 - x1;
float h = y2 - y1;
if ((w < 0) || (h < 0)) {
- log.error("Negative extent received (w=" + w + ", h=" + h + "). Border won't be painted.");
+ log.error("Negative extent received (w=" + w + ", h=" + h
+ + "). Border won't be painted.");
return;
}
switch (style) {
@@ -1329,12 +1312,9 @@
super.renderBlock(block);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void renderLineArea(LineArea line) {
super.renderLineArea(line);
- closeText();
}
/**
@@ -1423,11 +1403,20 @@
}
}
- /**
- * {@inheritDoc}
- */
+ private Typeface getTypeface(String fontName) {
+ Typeface tf = (Typeface) fontInfo.getFonts().get(fontName);
+ if (tf instanceof LazyFont) {
+ tf = ((LazyFont)tf).getRealFont();
+ }
+ return tf;
+ }
+
+ /** {@inheritDoc} */
public void renderText(TextArea text) {
renderInlineAreaBackAndBorders(text);
+ Color ct = (Color) text.getTrait(Trait.COLOR);
+ updateColor(ct, true);
+
beginTextObject();
StringBuffer pdf = new StringBuffer();
@@ -1435,12 +1424,10 @@
int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
// This assumes that *all* CIDFonts use a /ToUnicode mapping
- Typeface tf = (Typeface) fontInfo.getFonts().get(fontName);
- boolean useMultiByte = tf.isMultiByte();
+ Typeface tf = getTypeface(fontName);
+
+ textutil.updateTf(fontName, size / 1000f, tf.isMultiByte());
- updateFont(fontName, size, pdf);
- Color ct = (Color) text.getTrait(Trait.COLOR);
- updateColor(ct, true, pdf);
// word.getOffset() = only height of text itself
// currentBlockIPPosition: 0 for beginning of line; nonzero
@@ -1448,66 +1435,46 @@
int rx = currentIPPosition + text.getBorderAndPaddingWidthStart();
int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset();
- pdf.append("1 0 0 -1 " + format(rx / 1000f) + " " + format(bl / 1000f) + " Tm "
- /*+ format(text.getTextLetterSpaceAdjust() / 1000f) + " Tc\n"*/
- /*+ format(text.getTextWordSpaceAdjust() / 1000f) + " Tw ["*/);
+ textutil.writeTextMatrix(new AffineTransform(1, 0, 0, -1, rx / 1000f, bl / 1000f));
- pdf.append("[");
currentStream.add(pdf.toString());
super.renderText(text);
- currentStream.add("] TJ\n");
+ textutil.writeTJ();
renderTextDecoration(tf, size, text, bl, rx);
}
-
- /**
- * {@inheritDoc}
- */
+
+ /** {@inheritDoc} */
public void renderWord(WordArea word) {
Font font = getFontFromArea(word.getParentArea());
- Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName());
- boolean useMultiByte = tf.isMultiByte();
-
- StringBuffer pdf = new StringBuffer();
-
String s = word.getWord();
- escapeText(s, word.getLetterAdjustArray(),
- font, (AbstractTextArea)word.getParentArea(), useMultiByte, pdf);
- currentStream.add(pdf.toString());
+ escapeText(s, word.getLetterAdjustArray(),
+ font, (AbstractTextArea)word.getParentArea());
super.renderWord(word);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void renderSpace(SpaceArea space) {
Font font = getFontFromArea(space.getParentArea());
- Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName());
- boolean useMultiByte = tf.isMultiByte();
-
String s = space.getSpace();
- StringBuffer pdf = new StringBuffer();
-
AbstractTextArea textArea = (AbstractTextArea)space.getParentArea();
- escapeText(s, null, font, textArea, useMultiByte, pdf);
+ escapeText(s, null, font, textArea);
if (space.isAdjustable()) {
int tws = -((TextArea) space.getParentArea()).getTextWordSpaceAdjust()
- 2 * textArea.getTextLetterSpaceAdjust();
if (tws != 0) {
- pdf.append(format(tws / (font.getFontSize() / 1000f)));
- pdf.append(" ");
+ float adjust = tws / (font.getFontSize() / 1000f);
+ textutil.adjustGlyphTJ(adjust);
}
}
- currentStream.add(pdf.toString());
-
super.renderSpace(space);
}
@@ -1515,101 +1482,77 @@
* Escapes text according to PDF rules.
* @param s Text to escape
* @param letterAdjust an array of widths for letter adjustment (may be null)
- * @param fs Font state
+ * @param font to font in use
* @param parentArea the parent text area to retrieve certain traits from
- * @param useMultiByte Indicates the use of multi byte convention
- * @param pdf target buffer for the escaped text
*/
- public void escapeText(String s, int[] letterAdjust,
- Font fs, AbstractTextArea parentArea,
- boolean useMultiByte, StringBuffer pdf) {
- String startText = useMultiByte ? "<" : "(";
- String endText = useMultiByte ? "> " : ") ";
-
- /*
- boolean kerningAvailable = false;
- Map kerning = fs.getKerning();
- if (kerning != null && !kerning.isEmpty()) {
- //kerningAvailable = true;
- //TODO Reenable me when the layout engine supports kerning, too
- log.warn("Kerning support is disabled until it is supported by the layout engine!");
+ protected void escapeText(String s,
+ int[] letterAdjust,
+ Font font, AbstractTextArea parentArea) {
+ escapeText(s, 0, s.length(), letterAdjust, font, parentArea);
+ }
+
+ /**
+ * Escapes text according to PDF rules.
+ * @param s Text to escape
+ * @param start the start position in the text
+ * @param end the end position in the text
+ * @param letterAdjust an array of widths for letter adjustment (may be null)
+ * @param font to font in use
+ * @param parentArea the parent text area to retrieve certain traits from
+ */
+ protected void escapeText(String s, int start, int end,
+ int[] letterAdjust,
+ Font font, AbstractTextArea parentArea) {
+ String fontName = font.getFontName();
+ float fontSize = font.getFontSize() / 1000f;
+ Typeface tf = getTypeface(fontName);
+ SingleByteFont singleByteFont = null;
+ if (tf instanceof SingleByteFont) {
+ singleByteFont = (SingleByteFont)tf;
}
- */
int l = s.length();
-
- float fontSize = fs.getFontSize() / 1000f;
- boolean startPending = true;
- for (int i = 0; i < l; i++) {
+
+ for (int i = start; i < end; i++) {
char orgChar = s.charAt(i);
char ch;
float glyphAdjust = 0;
- if (fs.hasChar(orgChar)) {
- ch = fs.mapChar(orgChar);
+ if (font.hasChar(orgChar)) {
+ ch = font.mapChar(orgChar);
+ if (singleByteFont != null && singleByteFont.hasAdditionalEncodings()) {
+ int encoding = ch / 256;
+ if (encoding == 0) {
+ textutil.updateTf(fontName, fontSize, tf.isMultiByte());
+ } else {
+ textutil.updateTf(fontName + "_" + Integer.toString(encoding),
+ fontSize, tf.isMultiByte());
+ ch = (char)(ch % 256);
+ }
+ }
int tls = (i < l - 1 ? parentArea.getTextLetterSpaceAdjust() : 0);
glyphAdjust -= tls;
} else {
if (CharUtilities.isFixedWidthSpace(orgChar)) {
//Fixed width space are rendered as spaces so copy/paste works in a reader
- ch = fs.mapChar(CharUtilities.SPACE);
- glyphAdjust = fs.getCharWidth(ch) - fs.getCharWidth(orgChar);
+ ch = font.mapChar(CharUtilities.SPACE);
+ glyphAdjust = font.getCharWidth(ch) - font.getCharWidth(orgChar);
} else {
- ch = fs.mapChar(orgChar);
+ ch = font.mapChar(orgChar);
}
}
if (letterAdjust != null && i < l - 1) {
glyphAdjust -= letterAdjust[i + 1];
}
- if (startPending) {
- pdf.append(startText);
- startPending = false;
- }
- if (!useMultiByte) {
- if (ch < 32 || ch > 127) {
- pdf.append("\\");
- pdf.append(Integer.toOctalString((int) ch));
- } else {
- switch (ch) {
- case '(':
- case ')':
- case '\\':
- pdf.append("\\");
- break;
- default:
- }
- pdf.append(ch);
- }
- } else {
- pdf.append(PDFText.toUnicodeHex(ch));
- }
+ textutil.writeTJMappedChar(ch);
float adjust = glyphAdjust / fontSize;
if (adjust != 0) {
- pdf.append(endText).append(format(adjust)).append(' ');
- startPending = true;
+ textutil.adjustGlyphTJ(adjust);
}
}
- if (!startPending) {
- pdf.append(endText);
- }
- }
-
- /**
- * Checks to see if we have some text rendering commands open
- * still and writes out the TJ command to the stream if we do
- */
- protected void closeText() {
- /*
- if (textOpen) {
- currentStream.add("] TJ\n");
- textOpen = false;
- prevWordX = 0;
- prevWordY = 0;
- currentFontName = "";
- }*/
}
/**
@@ -1623,8 +1566,6 @@
protected void setColor(Color col, boolean fill, StringBuffer pdf) {
PDFColor color = new PDFColor(this.pdfDoc, col);
- closeText();
-
if (pdf != null) {
pdf.append(color.getColorSpaceOut(fill));
} else {
@@ -1656,22 +1597,10 @@
}
/** {@inheritDoc} */
- protected void updateColor(Color col, boolean fill) {
+ protected void updateColor(Color col, boolean fill) {
updateColor(col, fill, null);
}
- private void updateFont(String name, int size, StringBuffer pdf) {
- if ((!name.equals(this.currentFontName))
- || (size != this.currentFontSize)) {
- closeText();
-
- this.currentFontName = name;
- this.currentFontSize = size;
- pdf = pdf.append("/" + name + " " + format((float) size / 1000f)
- + " Tf\n");
- }
- }
-
/** {@inheritDoc} */
public void renderImage(Image image, Rectangle2D pos) {
endTextObject();
@@ -1727,8 +1656,6 @@
ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
info = manager.getImageInfo(uri, sessionContext);
-
-
Map hints = ImageUtil.getDefaultHints(sessionContext);
org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
info, imageHandlerRegistry.getSupportedFlavors(), hints, sessionContext);
@@ -1802,9 +1729,8 @@
context.setProperty(PDFRendererContextConstants.PDF_CONTEXT, currentContext);
context.setProperty(PDFRendererContextConstants.PDF_STREAM, currentStream);
context.setProperty(PDFRendererContextConstants.PDF_FONT_INFO, fontInfo);
- context.setProperty(PDFRendererContextConstants.PDF_FONT_NAME, currentFontName);
- context.setProperty(PDFRendererContextConstants.PDF_FONT_SIZE,
- new Integer(currentFontSize));
+ context.setProperty(PDFRendererContextConstants.PDF_FONT_NAME, "");
+ context.setProperty(PDFRendererContextConstants.PDF_FONT_SIZE, new Integer(0));
return context;
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSFontUtils.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSFontUtils.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSFontUtils.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSFontUtils.java Thu Mar 27 01:49:41 2008
@@ -32,16 +32,20 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.xmlgraphics.fonts.Glyphs;
import org.apache.xmlgraphics.ps.DSCConstants;
import org.apache.xmlgraphics.ps.PSGenerator;
import org.apache.xmlgraphics.ps.PSResource;
import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
+import org.apache.fop.fonts.Base14Font;
import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontType;
import org.apache.fop.fonts.LazyFont;
+import org.apache.fop.fonts.SingleByteEncoding;
+import org.apache.fop.fonts.SingleByteFont;
import org.apache.fop.fonts.Typeface;
/**
@@ -81,9 +85,21 @@
while (iter.hasNext()) {
String key = (String)iter.next();
Typeface tf = getTypeFace(fontInfo, fonts, key);
- PSResource fontRes = new PSResource("font", tf.getFontName());
+ PSResource fontRes = new PSResource(PSResource.TYPE_FONT, tf.getFontName());
fontResources.put(key, fontRes);
embedFont(gen, tf, fontRes);
+
+ if (tf instanceof SingleByteFont) {
+ SingleByteFont sbf = (SingleByteFont)tf;
+ for (int i = 0, c = sbf.getAdditionalEncodingCount(); i < c; i++) {
+ SingleByteEncoding encoding = sbf.getAdditionalEncoding(i);
+ defineEncoding(gen, encoding);
+ String postFix = "_" + (i + 1);
+ PSResource derivedFontRes = defineDerivedFont(gen, tf.getFontName(),
+ tf.getFontName() + postFix, encoding.getName());
+ fontResources.put(key + postFix, derivedFontRes);
+ }
+ }
}
gen.commentln("%FOPEndFontDict");
reencodeFonts(gen, fonts);
@@ -91,29 +107,35 @@
}
private static void reencodeFonts(PSGenerator gen, Map fonts) throws IOException {
+ ResourceTracker tracker = gen.getResourceTracker();
+
+ if (!tracker.isResourceSupplied(WINANSI_ENCODING_RESOURCE)) {
+ defineWinAnsiEncoding(gen);
+ }
gen.commentln("%FOPBeginFontReencode");
- defineWinAnsiEncoding(gen);
//Rewrite font encodings
Iterator iter = fonts.keySet().iterator();
while (iter.hasNext()) {
String key = (String)iter.next();
- Typeface fm = (Typeface)fonts.get(key);
- if (fm instanceof LazyFont && ((LazyFont)fm).getRealFont() == null) {
- continue;
- } else if (null == fm.getEncoding()) {
+ Typeface tf = (Typeface)fonts.get(key);
+ if (tf instanceof LazyFont) {
+ tf = ((LazyFont)tf).getRealFont();
+ if (tf == null) {
+ continue;
+ }
+ }
+ if (null == tf.getEncodingName()) {
//ignore (ZapfDingbats and Symbol used to run through here, kept for safety reasons)
- } else if ("SymbolEncoding".equals(fm.getEncoding())) {
+ } else if ("SymbolEncoding".equals(tf.getEncodingName())) {
//ignore (no encoding redefinition)
- } else if ("ZapfDingbatsEncoding".equals(fm.getEncoding())) {
+ } else if ("ZapfDingbatsEncoding".equals(tf.getEncodingName())) {
//ignore (no encoding redefinition)
- } else if ("WinAnsiEncoding".equals(fm.getEncoding())) {
- redefineFontEncoding(gen, fm.getFontName(), fm.getEncoding());
} else {
- /* Don't complain anymore, just use the font's default encoding.
- gen.commentln("%WARNING: Only WinAnsiEncoding is supported. Font '"
- + fm.getFontName() + "' asks for: " + fm.getEncoding());
- */
+ if (tf instanceof Base14Font) {
+ //Our Base 14 fonts don't use the default encoding
+ redefineFontEncoding(gen, tf.getFontName(), tf.getEncodingName());
+ }
}
}
gen.commentln("%FOPEndFontReencode");
@@ -233,10 +255,88 @@
if (isEmbeddable(cf)) {
resTracker.registerSuppliedResource(fontRes);
}
+ if (tf instanceof SingleByteFont) {
+ SingleByteFont sbf = (SingleByteFont)tf;
+ for (int i = 0, c = sbf.getAdditionalEncodingCount(); i < c; i++) {
+ SingleByteEncoding encoding = sbf.getAdditionalEncoding(i);
+ PSResource encodingRes = new PSResource(
+ PSResource.TYPE_ENCODING, encoding.getName());
+ resTracker.registerSuppliedResource(encodingRes);
+ PSResource derivedFontRes = new PSResource(
+ PSResource.TYPE_FONT, tf.getFontName() + "_" + (i + 1));
+ resTracker.registerSuppliedResource(derivedFontRes);
+ }
+ }
}
}
}
return fontResources;
}
+ /**
+ * Defines the single-byte encoding for use in PostScript files.
+ * @param gen the PostScript generator
+ * @param encoding the single-byte encoding
+ * @return the PSResource instance that represents the encoding
+ * @throws IOException In case of an I/O problem
+ */
+ public static PSResource defineEncoding(PSGenerator gen, SingleByteEncoding encoding)
+ throws IOException {
+ PSResource res = new PSResource(PSResource.TYPE_ENCODING, encoding.getName());
+ gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, res);
+ gen.writeln("/" + encoding.getName() + " [");
+ String[] charNames = encoding.getCharNameMap();
+ for (int i = 0; i < 256; i++) {
+ if (i > 0) {
+ if ((i % 5) == 0) {
+ gen.newLine();
+ } else {
+ gen.write(" ");
+ }
+ }
+ String glyphname = null;
+ if (i < charNames.length) {
+ glyphname = charNames[i];
+ }
+ if (glyphname == null || "".equals(glyphname)) {
+ glyphname = Glyphs.NOTDEF;
+ }
+ gen.write("/");
+ gen.write(glyphname);
+ }
+ gen.newLine();
+ gen.writeln("] def");
+ gen.writeDSCComment(DSCConstants.END_RESOURCE);
+ gen.getResourceTracker().registerSuppliedResource(res);
+ return res;
+ }
+
+ /**
+ * Derives a new font based on an existing font with a given encoding. The encoding must
+ * have been registered before.
+ * @param gen the PostScript generator
+ * @param baseFontName the font name of the font to derive from
+ * @param fontName the font name of the new font to be define
+ * @param encoding the new encoding (must be predefined in the PS file)
+ * @return the PSResource representing the derived font
+ * @throws IOException In case of an I/O problem
+ */
+ public static PSResource defineDerivedFont(PSGenerator gen, String baseFontName, String fontName,
+ String encoding) throws IOException {
+ PSResource res = new PSResource(PSResource.TYPE_FONT, fontName);
+ gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, res);
+ gen.commentln("%XGCDependencies: font " + baseFontName);
+ gen.commentln("%XGC+ encoding " + encoding);
+ gen.writeln("/" + baseFontName + " findfont");
+ gen.writeln("dup length dict begin");
+ gen.writeln(" {1 index /FID ne {def} {pop pop} ifelse} forall");
+ gen.writeln(" /Encoding " + encoding + " def");
+ gen.writeln(" currentdict");
+ gen.writeln("end");
+ gen.writeln("/" + fontName + " exch definefont pop");
+ gen.writeDSCComment(DSCConstants.END_RESOURCE);
+ gen.getResourceTracker().registerSuppliedResource(res);
+ return res;
+ }
+
}
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSRenderer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSRenderer.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSRenderer.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/render/ps/PSRenderer.java Thu Mar 27 01:49:41 2008
@@ -89,6 +89,7 @@
import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.LazyFont;
+import org.apache.fop.fonts.SingleByteFont;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.render.AbstractPathOrientedRenderer;
import org.apache.fop.render.Graphics2DAdapter;
@@ -660,6 +661,12 @@
}
private String getPostScriptNameForFontKey(String key) {
+ int pos = key.indexOf('_');
+ String postFix = null;
+ if (pos > 0) {
+ postFix = key.substring(pos);
+ key = key.substring(0, pos);
+ }
Map fonts = fontInfo.getFonts();
Typeface tf = (Typeface)fonts.get(key);
if (tf instanceof LazyFont) {
@@ -668,7 +675,11 @@
if (tf == null) {
throw new IllegalStateException("Font not available: " + key);
}
- return tf.getFontName();
+ if (postFix == null) {
+ return tf.getFontName();
+ } else {
+ return tf.getFontName() + postFix;
+ }
}
/**
@@ -698,7 +709,6 @@
protected void useFont(String key, int size) {
try {
PSResource res = getPSResourceForFontKey(key);
- //gen.useFont(key, size / 1000f);
gen.useFont("/" + res.getName(), size / 1000f);
gen.getResourceTracker().notifyResourceUsageOnPage(res);
} catch (IOException ioe) {
@@ -951,7 +961,7 @@
if (!isOptimizeResources()) {
this.fontResources = PSFontUtils.writeFontDict(gen, fontInfo);
} else {
- gen.commentln("%FOPFontSetup");
+ gen.commentln("%FOPFontSetup"); //Place-holder, will be replaced in the second pass
}
gen.writeDSCComment(DSCConstants.END_SETUP);
}
@@ -1292,17 +1302,16 @@
*/
public void renderText(TextArea area) {
renderInlineAreaBackAndBorders(area);
- String fontname = getInternalFontNameForArea(area);
+ String fontkey = getInternalFontNameForArea(area);
int fontsize = area.getTraitAsInteger(Trait.FONT_SIZE);
// This assumes that *all* CIDFonts use a /ToUnicode mapping
- Typeface tf = (Typeface) fontInfo.getFonts().get(fontname);
+ Typeface tf = (Typeface) fontInfo.getFonts().get(fontkey);
//Determine position
int rx = currentIPPosition + area.getBorderAndPaddingWidthStart();
int bl = currentBPPosition + area.getOffset() + area.getBaselineOffset();
- useFont(fontname, fontsize);
Color ct = (Color)area.getTrait(Trait.COLOR);
if (ct != null) {
try {
@@ -1347,30 +1356,75 @@
super.renderSpace(space);
}
+ private Typeface getTypeface(String fontName) {
+ Typeface tf = (Typeface)fontInfo.getFonts().get(fontName);
+ if (tf instanceof LazyFont) {
+ tf = ((LazyFont)tf).getRealFont();
+ }
+ return tf;
+ }
+
private void renderText(AbstractTextArea area, String text, int[] letterAdjust) {
+ String fontkey = getInternalFontNameForArea(area);
+ int fontSize = area.getTraitAsInteger(Trait.FONT_SIZE);
Font font = getFontFromArea(area);
- Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName());
+ Typeface tf = getTypeface(font.getFontName());
+ SingleByteFont singleByteFont = null;
+ if (tf instanceof SingleByteFont) {
+ singleByteFont = (SingleByteFont)tf;
+ }
+ int textLen = text.length();
+ if (singleByteFont != null && singleByteFont.hasAdditionalEncodings()) {
+ int start = 0;
+ int currentEncoding = -1;
+ for (int i = 0; i < textLen; i++) {
+ char c = text.charAt(i);
+ char mapped = tf.mapChar(c);
+ int encoding = mapped / 256;
+ if (currentEncoding != encoding) {
+ if (i > 0) {
+ writeText(area, text, start, i - start, letterAdjust, fontSize, tf);
+ }
+ if (encoding == 0) {
+ useFont(fontkey, fontSize);
+ } else {
+ useFont(fontkey + "_" + Integer.toString(encoding), fontSize);
+ }
+ currentEncoding = encoding;
+ start = i;
+ }
+ }
+ writeText(area, text, start, textLen - start, letterAdjust, fontSize, tf);
+ } else {
+ useFont(fontkey, fontSize);
+ writeText(area, text, 0, textLen, letterAdjust, fontSize, tf);
+ }
+ }
+
+ private void writeText(AbstractTextArea area, String text, int start, int len,
+ int[] letterAdjust, int fontsize, Typeface tf) {
+ int end = start + len;
int initialSize = text.length();
initialSize += initialSize / 2;
StringBuffer sb = new StringBuffer(initialSize);
- int textLen = text.length();
if (letterAdjust == null
&& area.getTextLetterSpaceAdjust() == 0
&& area.getTextWordSpaceAdjust() == 0) {
sb.append("(");
- for (int i = 0; i < textLen; i++) {
+ for (int i = start; i < end; i++) {
final char c = text.charAt(i);
- final char mapped = tf.mapChar(c);
+ final char mapped = (char)(tf.mapChar(c) % 256);
PSGenerator.escapeChar(mapped, sb);
}
sb.append(") t");
} else {
sb.append("(");
- int[] offsets = new int[textLen];
- for (int i = 0; i < textLen; i++) {
+ int[] offsets = new int[len];
+ for (int i = start; i < end; i++) {
final char c = text.charAt(i);
final char mapped = tf.mapChar(c);
+ char codepoint = (char)(mapped % 256);
int wordSpace;
if (CharUtilities.isAdjustableSpace(mapped)) {
@@ -1378,14 +1432,14 @@
} else {
wordSpace = 0;
}
- int cw = tf.getWidth(mapped, font.getFontSize()) / 1000;
- int ladj = (letterAdjust != null && i < textLen - 1 ? letterAdjust[i + 1] : 0);
- int tls = (i < textLen - 1 ? area.getTextLetterSpaceAdjust() : 0);
- offsets[i] = cw + ladj + tls + wordSpace;
- PSGenerator.escapeChar(mapped, sb);
+ int cw = tf.getWidth(mapped, fontsize) / 1000;
+ int ladj = (letterAdjust != null && i < end - 1 ? letterAdjust[i + 1] : 0);
+ int tls = (i < end - 1 ? area.getTextLetterSpaceAdjust() : 0);
+ offsets[i - start] = cw + ladj + tls + wordSpace;
+ PSGenerator.escapeChar(codepoint, sb);
}
sb.append(")" + PSGenerator.LF + "[");
- for (int i = 0; i < textLen; i++) {
+ for (int i = 0; i < len; i++) {
if (i > 0) {
if (i % 8 == 0) {
sb.append(PSGenerator.LF);
@@ -1398,7 +1452,6 @@
sb.append("]" + PSGenerator.LF + "xshow");
}
writeln(sb.toString());
-
}
/** {@inheritDoc} */
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFGraphics2D.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFGraphics2D.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFGraphics2D.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFGraphics2D.java Thu Mar 27 01:49:41 2008
@@ -70,12 +70,10 @@
import org.apache.xmlgraphics.java2d.AbstractGraphics2D;
import org.apache.xmlgraphics.java2d.GraphicContext;
-import org.apache.fop.fonts.CIDFont;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.fonts.FontTriplet;
-import org.apache.fop.fonts.LazyFont;
import org.apache.fop.pdf.BitmapImage;
import org.apache.fop.pdf.PDFAnnotList;
import org.apache.fop.pdf.PDFColor;
@@ -1473,14 +1471,7 @@
// This assumes that *all* CIDFonts use a /ToUnicode mapping
org.apache.fop.fonts.Typeface f
= (org.apache.fop.fonts.Typeface)fontInfo.getFonts().get(name);
- if (f instanceof LazyFont) {
- if (((LazyFont) f).getRealFont() instanceof CIDFont) {
- return true;
- }
- } else if (f instanceof CIDFont) {
- return true;
- }
- return false;
+ return f.isMultiByte();
}
private void addKerning(StringWriter buf, Integer ch1, Integer ch2,
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextPainter.java Thu Mar 27 01:49:41 2008
@@ -43,6 +43,7 @@
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;
@@ -83,8 +84,12 @@
super.paintTextRuns(textRuns, g2d);
return;
}
- PDFGraphics2D pdf = (PDFGraphics2D)g2d;
- PDFTextUtil textUtil = new PDFTextUtil(pdf);
+ final PDFGraphics2D pdf = (PDFGraphics2D)g2d;
+ PDFTextUtil textUtil = new PDFTextUtil(pdf.fontInfo) {
+ protected void write(String code) {
+ pdf.currentStream.write(code);
+ }
+ };
for (int i = 0; i < textRuns.size(); i++) {
TextRun textRun = (TextRun)textRuns.get(i);
AttributedCharacterIterator runaci = textRun.getACI();
@@ -134,7 +139,7 @@
}
textUtil.saveGraphicsState();
- textUtil.concatMatrixCurrentTransform();
+ textUtil.concatMatrix(g2d.getTransform());
Shape imclip = g2d.getClip();
pdf.writeClip(imclip);
Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/svg/PDFTextUtil.java Thu Mar 27 01:49:41 2008
@@ -19,145 +19,33 @@
package org.apache.fop.svg;
-import java.awt.geom.AffineTransform;
-
import org.apache.fop.fonts.Font;
-import org.apache.fop.pdf.PDFNumber;
-import org.apache.fop.pdf.PDFText;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.Typeface;
/**
- * Utility class for generating PDF text objects.
+ * Utility class for generating PDF text objects. It needs to be subclassed to add writing
+ * functionality (see {@link #write(String)}).
*/
-public class PDFTextUtil {
+public abstract class PDFTextUtil extends org.apache.fop.pdf.PDFTextUtil {
- /** The number of decimal places. */
- private static final int DEC = 8;
-
- /** PDF text rendering mode: Fill text */
- public static final int TR_FILL = 0;
- /** PDF text rendering mode: Stroke text */
- public static final int TR_STROKE = 1;
- /** PDF text rendering mode: Fill, then stroke text */
- public static final int TR_FILL_STROKE = 2;
- /** PDF text rendering mode: Neither fill nor stroke text (invisible) */
- public static final int TR_INVISIBLE = 3;
- /** PDF text rendering mode: Fill text and add to path for clipping */
- public static final int TR_FILL_CLIP = 4;
- /** PDF text rendering mode: Stroke text and add to path for clipping */
- public static final int TR_STROKE_CLIP = 5;
- /** PDF text rendering mode: Fill, then stroke text and add to path for clipping */
- public static final int TR_FILL_STROKE_CLIP = 6;
- /** PDF text rendering mode: Add text to path for clipping */
- public static final int TR_CLIP = 7;
-
-
- private PDFGraphics2D g2d;
- private boolean inTextObject = false;
+ private FontInfo fontInfo;
private Font[] fonts;
private Font font;
- private String startText;
- private String endText;
- private boolean useMultiByte;
- private StringBuffer bufTJ;
- private int textRenderingMode = 0;
/**
* Main constructor.
- * @param g2d the PDFGraphics2D instance to work with
+ * @param fontInfo the font catalog
*/
- public PDFTextUtil(PDFGraphics2D g2d) {
- this.g2d = g2d;
+ public PDFTextUtil(FontInfo fontInfo) {
+ super();
+ this.fontInfo = fontInfo;
}
- private void writeAffineTransform(AffineTransform at, StringBuffer sb) {
- double[] lt = new double[6];
- at.getMatrix(lt);
- sb.append(PDFNumber.doubleOut(lt[0], DEC)).append(" ");
- sb.append(PDFNumber.doubleOut(lt[1], DEC)).append(" ");
- sb.append(PDFNumber.doubleOut(lt[2], DEC)).append(" ");
- sb.append(PDFNumber.doubleOut(lt[3], DEC)).append(" ");
- sb.append(PDFNumber.doubleOut(lt[4], DEC)).append(" ");
- sb.append(PDFNumber.doubleOut(lt[5], DEC));
- }
-
- private void writeChar(char ch, StringBuffer sb) {
- if (!useMultiByte) {
- if (ch > 127) {
- sb.append("\\").append(Integer.toOctalString((int)ch));
- } else {
- switch (ch) {
- case '(':
- case ')':
- case '\\':
- sb.append("\\");
- break;
- default:
- }
- sb.append(ch);
- }
- } else {
- sb.append(PDFText.toUnicodeHex(ch));
- }
- }
-
- private void checkInTextObject() {
- if (!inTextObject) {
- throw new IllegalStateException("Not in text object");
- }
- }
-
- /**
- * Called when a new text object should be started. Be sure to call setFont() before
- * issuing any text painting commands.
- */
- public void beginTextObject() {
- if (inTextObject) {
- throw new IllegalStateException("Already in text object");
- }
- g2d.currentStream.write("BT\n");
- this.inTextObject = true;
- }
-
- /**
- * Called when a text object should be ended.
- */
- public void endTextObject() {
- checkInTextObject();
- g2d.currentStream.write("ET\n");
- this.inTextObject = false;
- initValues();
- }
-
- private void initValues() {
+ /** {@inheritDoc} */
+ protected void initValues() {
+ super.initValues();
this.font = null;
- this.textRenderingMode = TR_FILL;
- }
-
- /**
- * Creates a "q" command, pushing a copy of the entire graphics state onto the stack.
- */
- public void saveGraphicsState() {
- g2d.currentStream.write("q\n");
- }
-
- /**
- * Creates a "Q" command, restoring the entire graphics state to its former value by popping
- * it from the stack.
- */
- public void restoreGraphicsState() {
- g2d.currentStream.write("Q\n");
- }
-
- /**
- * Creates a "cm" command using the current transformation as the matrix.
- */
- public void concatMatrixCurrentTransform() {
- StringBuffer sb = new StringBuffer();
- if (!g2d.getTransform().isIdentity()) {
- writeAffineTransform(g2d.getTransform(), sb);
- sb.append(" cm\n");
- }
- g2d.currentStream.write(sb.toString());
}
/**
@@ -194,63 +82,23 @@
}
/**
+ * Determines whether the font with the given name is a multi-byte font.
+ * @param name the name of the font
+ * @return true if it's a multi-byte font
+ */
+ protected boolean isMultiByteFont(String name) {
+ Typeface f = (Typeface)fontInfo.getFonts().get(name);
+ return f.isMultiByte();
+ }
+
+ /**
* Writes a "Tf" command, setting a new current font.
* @param f the font to select
*/
public void writeTf(Font f) {
- checkInTextObject();
String fontName = f.getFontName();
float fontSize = (float)f.getFontSize() / 1000f;
- g2d.currentStream.write("/" + fontName + " " + PDFNumber.doubleOut(fontSize) + " Tf\n");
-
- this.useMultiByte = g2d.isMultiByteFont(fontName);
- this.startText = useMultiByte ? "<" : "(";
- this.endText = useMultiByte ? ">" : ")";
- }
-
- /**
- * Sets the text rendering mode.
- * @param mode the rendering mode (value 0 to 7, see PDF Spec, constants: TR_*)
- */
- public void setTextRenderingMode(int mode) {
- if (mode < 0 || mode > 7) {
- throw new IllegalArgumentException(
- "Illegal value for text rendering mode. Expected: 0-7");
- }
- if (mode != this.textRenderingMode) {
- this.textRenderingMode = mode;
- g2d.currentStream.write(this.textRenderingMode + " Tr\n");
- }
- }
-
- /**
- * Sets the text rendering mode.
- * @param fill true if the text should be filled
- * @param stroke true if the text should be stroked
- * @param addToClip true if the path should be added for clipping
- */
- public void setTextRenderingMode(boolean fill, boolean stroke, boolean addToClip) {
- int mode;
- if (fill) {
- mode = (stroke ? 2 : 0);
- } else {
- mode = (stroke ? 1 : 3);
- }
- if (addToClip) {
- mode += 4;
- }
- setTextRenderingMode(mode);
- }
-
- /**
- * Writes a "Tm" command, setting a new text transformation matrix.
- * @param localTransform the new text transformation matrix
- */
- public void writeTextMatrix(AffineTransform localTransform) {
- StringBuffer sb = new StringBuffer();
- writeAffineTransform(localTransform, sb);
- sb.append(" Tm\n");
- g2d.currentStream.write(sb.toString());
+ updateTf(fontName, fontSize, isMultiByteFont(fontName));
}
/**
@@ -272,37 +120,8 @@
* @param ch the unmapped character
*/
public void writeTJChar(char ch) {
- if (bufTJ == null) {
- bufTJ = new StringBuffer();
- }
- if (bufTJ.length() == 0) {
- bufTJ.append("[").append(startText);
- }
char mappedChar = font.mapChar(ch);
- writeChar(mappedChar, bufTJ);
- }
-
- /**
- * Writes a glyph adjust value to the "TJ-Buffer".
- * @param adjust the glyph adjust value in thousands of text unit space.
- */
- public void adjustGlyphTJ(double adjust) {
- bufTJ.append(endText).append(" ");
- bufTJ.append(PDFNumber.doubleOut(adjust, DEC - 4));
- bufTJ.append(" ");
- bufTJ.append(startText);
- }
-
- /**
- * Writes a "TJ" command, writing out the accumulated buffer with the characters and glyph
- * positioning values. The buffer is reset afterwards.
- */
- public void writeTJ() {
- if (bufTJ != null && bufTJ.length() > 0) {
- bufTJ.append(endText).append("] TJ\n");
- g2d.currentStream.write(bufTJ.toString());
- bufTJ.setLength(0);
- }
+ writeTJMappedChar(mappedChar);
}
}
Modified: xmlgraphics/fop/trunk/status.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/status.xml?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/status.xml (original)
+++ xmlgraphics/fop/trunk/status.xml Thu Mar 27 01:49:41 2008
@@ -52,13 +52,17 @@
</contexts>
<changes>
- <!--release version="FOP Trunk" date="TBD"-->
+ <release version="FOP Trunk" date="TBD">
<!-- change reverted, to be added back later
<action context="Renderers" dev="AC" importance="high" type="add">
Added SVG support for AFP (GOCA).
</action>
-->
- <!--/release-->
+ <action context="Fonts" dev="JM" type="add">
+ Added support for addressing all glyphs available in a Type 1 font, not just the ones
+ in the font's primary encoding.
+ </action>
+ </release>
<release version="0.95beta" date="22 March 2008">
<notes>
<section>
Modified: xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFEncodingTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFEncodingTestCase.java?rev=641742&r1=641741&r2=641742&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFEncodingTestCase.java (original)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/render/pdf/PDFEncodingTestCase.java Thu Mar 27 01:49:41 2008
@@ -65,7 +65,7 @@
* The following array is used to look for these patterns
*/
final String[] testPatterns = {
- TEST_MARKER + "1", "(Standard)",
+ TEST_MARKER + "1", "Standard",
TEST_MARKER + "2", "XX_\\351_XX",
TEST_MARKER + "3", "XX_\\342\\352\\356\\364\\373_XX"
};
@@ -75,7 +75,9 @@
/**
* TODO test disabled for now, fails due (probably) do different PDF
- * encoding when custom font is used
+ * encoding when custom font is used.
+ * TODO This should be tested using PDFBox. If PDFBox can extract the text correctly,
+ * everything is fine. The tests here are too unstable.
*
* @throws Exception
* checkstyle wants a comment here, even a silly one
---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org