Browse Source

enabling CID keyed truetype fonts; this gives support

         for other encodings than WinAnsiEncoding (eg japanese, chinese, arabic,
         iso-whatever, etc). Also makes font inclusion easier Tore Engvig


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194095 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-0_18_1
fotis 23 years ago
parent
commit
375b678502
35 changed files with 3286 additions and 1127 deletions
  1. 2
    0
      conf/config.xml
  2. 22
    20
      conf/userconfig.xml
  3. 11
    0
      src/org/apache/fop/configuration/Configuration.java
  4. 68
    14
      src/org/apache/fop/configuration/ConfigurationParser.java
  5. 51
    7
      src/org/apache/fop/configuration/ConfigurationReader.java
  6. 44
    0
      src/org/apache/fop/configuration/FontInfo.java
  7. 39
    0
      src/org/apache/fop/configuration/FontTriplet.java
  8. 248
    1
      src/org/apache/fop/fonts/Glyphs.java
  9. 3
    3
      src/org/apache/fop/fonts/PFMFile.java
  10. 34
    7
      src/org/apache/fop/fonts/TTFCmapEntry.java
  11. 32
    30
      src/org/apache/fop/fonts/TTFDirTabEntry.java
  12. 1018
    456
      src/org/apache/fop/fonts/TTFFile.java
  13. 24
    21
      src/org/apache/fop/fonts/TTFMtxEntry.java
  14. 76
    154
      src/org/apache/fop/fonts/apps/PFMReader.java
  15. 186
    206
      src/org/apache/fop/fonts/apps/TTFReader.java
  16. 12
    5
      src/org/apache/fop/layout/FontInfo.java
  17. 94
    60
      src/org/apache/fop/layout/FontState.java
  18. 16
    18
      src/org/apache/fop/layout/LineArea.java
  19. 27
    10
      src/org/apache/fop/pdf/PDFCIDFont.java
  20. 1
    0
      src/org/apache/fop/pdf/PDFCIDFontDescriptor.java
  21. 60
    11
      src/org/apache/fop/pdf/PDFCMap.java
  22. 100
    38
      src/org/apache/fop/pdf/PDFDocument.java
  23. 6
    4
      src/org/apache/fop/pdf/PDFFont.java
  24. 4
    1
      src/org/apache/fop/pdf/PDFFontDescriptor.java
  25. 16
    8
      src/org/apache/fop/pdf/PDFFontType0.java
  26. 1
    1
      src/org/apache/fop/pdf/PDFWArray.java
  27. 29
    0
      src/org/apache/fop/render/pdf/CIDFont.java
  28. 55
    0
      src/org/apache/fop/render/pdf/CMap.java
  29. 28
    12
      src/org/apache/fop/render/pdf/Font.java
  30. 334
    0
      src/org/apache/fop/render/pdf/FontReader.java
  31. 50
    2
      src/org/apache/fop/render/pdf/FontSetup.java
  32. 90
    38
      src/org/apache/fop/render/pdf/PDFRenderer.java
  33. 73
    0
      src/org/apache/fop/render/pdf/fonts/BFEntry.java
  34. 236
    0
      src/org/apache/fop/render/pdf/fonts/MultiByteFont.java
  35. 196
    0
      src/org/apache/fop/render/pdf/fonts/SingleByteFont.java

+ 2
- 0
conf/config.xml View File

@@ -50,4 +50,6 @@
<!-- <value>ascii-hex</value> -->
</list>
</entry>
<fonts>
</fonts>
</configuration>

+ 22
- 20
conf/userconfig.xml View File

@@ -42,30 +42,32 @@ basedir: normally the base directory is the directory where the fo file is

<!--
************************************************************************
Use kerning, default is to noe use kerning, uncomment to use kerning
Add fonts here
************************************************************************
-->

<entry>
<key>use-kerning</key>
<value>yes</value>
</entry>

<fonts>
<!-- example -->
<!--
<font metrics-file="arial.xml" kerning="yes" embed-file="arial.ttf">
<font-triplet name="Arial" style="normal" weight="normal"/>
<font-triplet name="ArialMT" style="normal" weight="normal"/>
</font>
<font metrics-file="arialb.xml" kerning="yes" embed-file="arialb.ttf">
<font-triplet name="Arial" style="normal" weight="bold"/>
<font-triplet name="ArialMT" style="normal" weight="bold"/>
</font>
<font metrics-file="ariali.xml" kerning="yes" embed-file="ariali.ttf">
<font-triplet name="Arial" style="italics" weight="normal"/>
<font-triplet name="ArialMT" style="italics" weight="normal"/>
</font>
<font metrics-file="arialbi.xml" kerning="yes" embed-file="arialbi.ttf">
<font-triplet name="Arial" style="italics" weight="bold"/>
<font-triplet name="ArialMT" style="italics" weight="bold"/>
</font>
-->
</fonts>

<!--
************************************************************************
Font embedding, only the fonts mentioned here is embedded
The value is the name of the font (the name is what is returned by
the font's fontName() method
************************************************************************
-->
<entry>
<key>embed-fonts</key>
<list>
<value>Perpetua</value>
<value>Perpetua,Bold</value>
</list>
</entry>

</configuration>


+ 11
- 0
src/org/apache/fop/configuration/Configuration.java View File

@@ -219,6 +219,17 @@ public class Configuration {
}


/**
* method to access fonts values in the standard configuration
*
* @param key a string containing the key value for the configuration value
* @return Hashtable a Hashtable containing the values
* null if the key is not defined.
*/
public static Vector getFonts() {
return (Vector) Configuration.getValue("fonts", Configuration.STANDARD);
}
/**
* initializes this configuration
* @param config contains the configuration information

+ 68
- 14
src/org/apache/fop/configuration/ConfigurationParser.java View File

@@ -7,14 +7,19 @@

package org.apache.fop.configuration;

//sax
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;

//java
import java.util.Hashtable;
import java.util.Vector;

//fop
import org.apache.fop.messaging.MessageHandler;


/**
* SAX2 Handler which retrieves the configuration information and stores them in Configuration.
* Normally this class doesn't need to be accessed directly.
@@ -28,6 +33,8 @@ public class ConfigurationParser extends DefaultHandler {
private final int IN_LIST = 8;
private final int IN_SUBENTRY = 16;
private final int IN_SUBKEY = 32;
private final int IN_FONTS = 64;
private final int IN_FONT = 128;

private final int STRING = 0;
private final int LIST = 1;
@@ -62,6 +69,23 @@ public class ConfigurationParser extends DefaultHandler {
/** determines role / target of configuration information, default is standard */
private String role = "standard";

//stores fonts
private Vector fontList = null;
//stores information on one font
private FontInfo fontInfo = null;

//stores information on a font triplet
private FontTriplet fontTriplet = null;
//information on a font
private String fontName, metricsFile, embedFile, kerningAsString;
private boolean kerning;
private Vector fontTriplets;
//information on a font triplet
private String fontTripletName, weight, style;
public void startDocument() {
configuration = Configuration.getConfiguration();
}
@@ -93,6 +117,25 @@ public class ConfigurationParser extends DefaultHandler {
role = attributes.getValue("role");
}
} else if (localName.equals("configuration") ) {
} else if (localName.equals("fonts") ) { //list of fonts starts
fontList = new Vector (10);
} else if (localName.equals("font") ) {
kerningAsString = attributes.getValue("kerning");
if (kerningAsString.equalsIgnoreCase("yes")) {
kerning = true;
} else {
kerning = false;
}
metricsFile = attributes.getValue("metrics-file");
embedFile = attributes.getValue("embed-file");
fontName = attributes.getValue("name");
fontTriplets = new Vector(5);
} else if (localName.equals("font-triplet") ) {
fontTripletName = attributes.getValue("name");
weight = attributes.getValue("weight");
style = attributes.getValue("style");
fontTriplet = new FontTriplet(fontTripletName,weight,style);
fontTriplets.addElement(fontTriplet);
} else {
//to make sure that user knows about false tag
MessageHandler.errorln(
@@ -117,20 +160,31 @@ public class ConfigurationParser extends DefaultHandler {
}
status = OUT;
role = "standard";
key = "";
value = "";
} else if (localName.equals("subentry")) {
map.put(subkey, value);
status -= IN_SUBENTRY;
key = "";
value = "";
} else if (localName.equals("key")) {
status -= IN_KEY;
} else if (localName.equals("list")) {
status -= IN_LIST;
value = "";
} else if (localName.equals("value")) {
status -= IN_VALUE;
key = "";
value = "";
} else if (localName.equals("subentry")) {
map.put(subkey, value);
status -= IN_SUBENTRY;
key = "";
value = "";
} else if (localName.equals("key")) {
status -= IN_KEY;
} else if (localName.equals("list")) {
status -= IN_LIST;
value = "";
} else if (localName.equals("value")) {
status -= IN_VALUE;
} else if (localName.equals("fonts") ) {
this.store("standard", "fonts", fontList);
} else if (localName.equals("font") ) {
fontInfo = new FontInfo(fontName,metricsFile,kerning,fontTriplets,embedFile);
fontList.addElement(fontInfo);
fontTriplets = null;
metricsFile = null;
embedFile = null;
fontName = null;
kerningAsString = "";
} else if (localName.equals("font-triplet") ) {
}
}


+ 51
- 7
src/org/apache/fop/configuration/ConfigurationReader.java View File

@@ -1,9 +1,53 @@
/*
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
* For details on use and redistribution please refer to the
* LICENSE file included with these sources."
*/
/*

============================================================================
The Apache Software License, Version 1.1
============================================================================

Copyright (C) 1999 The Apache Software Foundation. All rights reserved.

Redistribution and use in source and binary forms, with or without modifica-
tion, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. The end-user documentation included with the redistribution, if any, must
include the following acknowledgment: "This product includes software
developed by the Apache Software Foundation (http://www.apache.org/)."
Alternately, this acknowledgment may appear in the software itself, if
and wherever such third-party acknowledgments normally appear.

4. The names "Fop" and "Apache Software Foundation" must not be used to
endorse or promote products derived from this software without prior
written permission. For written permission, please contact
apache@apache.org.

5. Products derived from this software may not be called "Apache", nor may
"Apache" appear in their name, without prior written permission of the
Apache Software Foundation.

THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This software consists of voluntary contributions made by many individuals
on behalf of the Apache Software Foundation and was originally created by
James Tauber <jtauber@jtauber.com>. For more information on the Apache
Software Foundation, please see <http://www.apache.org/>.

*/

package org.apache.fop.configuration;

@@ -31,7 +75,7 @@ import org.apache.fop.configuration.Configuration;
* }
* </code>
* Once the configuration has been setup, the information can be accessed with
* the methods of Configuration.
* the methods of StandardConfiguration.
*/

public class ConfigurationReader {
@@ -103,7 +147,7 @@ public class ConfigurationReader {
*
* @return the created SAX parser
*/
static XMLReader createParser() {
public static XMLReader createParser() {
String parserClassName = System.getProperty("org.xml.sax.parser");
if (parserClassName == null) {
parserClassName = "org.apache.xerces.parsers.SAXParser";

+ 44
- 0
src/org/apache/fop/configuration/FontInfo.java View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
* For details on use and redistribution please refer to the
* LICENSE file included with these sources."
*/


package org.apache.fop.configuration;

import java.util.Vector;

/**
* FontInfo contains meta information on fonts (where is the metrics file etc.)
*/

public class FontInfo {
private String metricsFile, embedFile, name;
private boolean kerning;
private Vector fontTriplets;

public FontInfo (String name, String metricsFile, boolean kerning,
Vector fontTriplets, String embedFile) {
this.name = name;
this.metricsFile = metricsFile;
this.embedFile = embedFile;
this.kerning = kerning;
this.fontTriplets = fontTriplets;
}

public String getMetricsFile() {
return metricsFile;
}
public String getEmbedFile() {
return embedFile;
}
public boolean getKerning() {
return kerning;
}
public Vector getFontTriplets() {
return fontTriplets;
}

}


+ 39
- 0
src/org/apache/fop/configuration/FontTriplet.java View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
* For details on use and redistribution please refer to the
* LICENSE file included with these sources."
*/


package org.apache.fop.configuration;

/**
* FontTriplet contains information on name, weight, style of one font
*/


public class FontTriplet {
private String name, weight, style;
public FontTriplet(String name, String weight, String style) {
this.name = name;
this.weight = weight;
this.style = style;
}

public String getName() {
return name;
}

public String getWeight() {
return weight;
}

public String getStyle() {
return style;
}

}





+ 248
- 1
src/org/apache/fop/fonts/Glyphs.java View File

@@ -604,7 +604,254 @@ public class Glyphs {
"yacute",
"thorn",
"ydieresis"};

/** The characters in WinAnsiEncoding */
public static char[] winAnsiEncoding = {
// not used until char 32
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
// 0x20
' ',
'\u0021',
'\"',
'\u0023',
'$',
'%',
'&',
'\'',
'(',
')',
'*',
'+',
',',
'\u002d',
'\u002e',
'/',
// 0x30
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
':',
';',
'<',
'=',
'>',
'?',
'@',
// 0x40
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
// 0x50
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'\u005b',
'\\',
'\u005d',
'\u005e',
'_',
// 0x60
'\u2018',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
// 0x70
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'\u007b',
'\u007c',
'\u007d',
'\u007e',
'\u2022',
// 0x80
'\u20ac',
'\u2022',
'\u201a',
'\u0192',
'\u201e',
'\u2026',
'\u2020',
'\u2021',
'\u02c6',
'\u2030',
'\u0160',
'\u2039',
'\u0152',
'\u2022',
'\u017d',
'\u2022',
// 0x90
'\u2022',
'\u2018', // quoteleft
'\u2019', // quoteright
'\u201c', // quotedblleft
'\u201d', // quotedblright
'\u2022', // bullet
'\u2013', // endash
'\u2014', // emdash
'~',
'\u2022', // bullet
'\u0161',
'\u203a',
'\u0153',
'\u2022',
'\u017e',
'\u0178',
// 0xA0
' ',
'\u00a1',
'\u00a2',
'£',
'\u00a4',
'\u00a5',
'\u00a6',
'\u00a7',
'\u00a8',
'\u00a9',
'\u00aa',
'\u00ab',
'\u00ac',
'\u00ad',
'\u00ae',
'\u00af',
// 0xb0
'\u00b0',
'\u00b1',
'\u00b2',
'\u00b3',
'\u00b4',
'\u00b5', // This is hand-coded, the rest is assumption
'\u00b6', // and *might* not be correct...
'\u00b7',
'\u00b8',
'\u00b9',
'\u00ba',
'\u00bb',
'\u00bc',
'\u00bd',
'\u00be',
'\u00bf',
// 0xc0
'\u00c0',
'\u00c1',
'\u00c2',
'\u00c3',
'\u00c4',
'\u00c5', // Aring
'\u00c6', // AE
'\u00c7',
'\u00c8',
'\u00c9',
'\u00ca',
'\u00cb',
'\u00cc',
'\u00cd',
'\u00ce',
'\u00cf',
// 0xd0
'\u00d0',
'\u00d1',
'\u00d2',
'\u00d3',
'\u00d4',
'\u00d5',
'\u00d6',
'\u00d7',
'\u00d8', // Oslash
'\u00d9',
'\u00da',
'\u00db',
'\u00dc',
'\u00dd',
'\u00de',
'\u00df',
// 0xe0
'\u00e0',
'\u00e1',
'\u00e2',
'\u00e3',
'\u00e4',
'\u00e5', // aring
'\u00e6', // ae
'\u00e7',
'\u00e8',
'\u00e9',
'\u00ea',
'\u00eb',
'\u00ec',
'\u00ed',
'\u00ee',
'\u00ef',
// 0xf0
'\u00f0',
'\u00f1',
'\u00f2',
'\u00f3',
'\u00f4',
'\u00f5',
'\u00f6',
'\u00f7',
'\u00f8',
'\u00f9',
'\u00fa',
'\u00fb',
'\u00fc',
'\u00fd',
'\u00fe',
'\u00ff'
};
static String[] unicode_glyphs={
"\u0041", "A",
"\u00C6", "AE",

+ 3
- 3
src/org/apache/fop/fonts/PFMFile.java View File

@@ -203,11 +203,11 @@ public class PFMFile {
String glyph1=Glyphs.tex8r[g1];
String glyph2=Glyphs.tex8r[g2];

Hashtable adjTab=(Hashtable)kerningTab.get(glyph1);
Hashtable adjTab=(Hashtable)kerningTab.get(new Integer(g1));
if (adjTab==null)
adjTab=new Hashtable();
adjTab.put(glyph2, new Integer(adj));
kerningTab.put(glyph1, adjTab);
adjTab.put(new Integer(g2), new Integer(adj));
kerningTab.put(new Integer(g1), adjTab);
}
}


+ 34
- 7
src/org/apache/fop/fonts/TTFCmapEntry.java View File

@@ -50,11 +50,38 @@
*/
package org.apache.fop.fonts;

class TTFCmapEntry {
int platform_id;
int encoding_id;
long offset;
TTFCmapEntry() {
}
/**
* The CMap entry contains information of a Unicode range and the
* the glyph indexes related to the range
*/
public class TTFCmapEntry {
public int unicodeStart;
public int unicodeEnd;
public int glyphStartIndex;
TTFCmapEntry() {
unicodeStart = 0;
unicodeEnd = 0;
glyphStartIndex = 0;
}

TTFCmapEntry (int unicodeStart,
int unicodeEnd,
int glyphStartIndex) {
this.unicodeStart = unicodeStart;
this.unicodeEnd = unicodeEnd;
this.glyphStartIndex = glyphStartIndex;
}

public boolean equals (Object o) {
if (o instanceof TTFCmapEntry) {
TTFCmapEntry ce = (TTFCmapEntry)o;
if (ce.unicodeStart == this.unicodeStart &&
ce.unicodeEnd == this.unicodeEnd &&
ce.glyphStartIndex == this.glyphStartIndex)
return true;
}
return false;
}
}

+ 32
- 30
src/org/apache/fop/fonts/TTFDirTabEntry.java View File

@@ -52,34 +52,36 @@ package org.apache.fop.fonts;
import java.io.*;

class TTFDirTabEntry {
byte[] tag;
int checksum;
long offset;
long length;

TTFDirTabEntry() {
tag = new byte[4];
}

/** Read Dir Tab, return tag name */
public String read(FontFileReader in) throws IOException {
tag[0]=in.readTTFByte();
tag[1]=in.readTTFByte();
tag[2]=in.readTTFByte();
tag[3]=in.readTTFByte();

in.skip(4); // Skip checksum
offset=in.readTTFULong();
length=in.readTTFULong();

System.out.println ("Read dir tab [" + tag[0]+
" "+tag[1] +
" "+tag[2] +
" "+tag[3] +
"] offset: " + offset +
" length: " + length +
" name: " + new String(tag));
return new String(tag, "ISO-8859-1");
}
byte[] tag;
int checksum;
long offset;
long length;
TTFDirTabEntry() {
tag = new byte[4];
}
/** Read Dir Tab, return tag name */
public String read(FontFileReader in) throws IOException {
tag[0]=in.readTTFByte();
tag[1]=in.readTTFByte();
tag[2]=in.readTTFByte();
tag[3]=in.readTTFByte();
in.skip(4); // Skip checksum
offset=in.readTTFULong();
length=in.readTTFULong();
/*
System.out.println ("Read dir tab [" + tag[0]+
" "+tag[1] +
" "+tag[2] +
" "+tag[3] +
"] offset: " + offset +
" length: " + length +
" name: " + new String(tag));
*/
return new String(tag, "ISO-8859-1");
}
}

+ 1018
- 456
src/org/apache/fop/fonts/TTFFile.java
File diff suppressed because it is too large
View File


+ 24
- 21
src/org/apache/fop/fonts/TTFMtxEntry.java View File

@@ -51,27 +51,30 @@
package org.apache.fop.fonts;

import java.io.*;
import java.util.Vector;

class TTFMtxEntry {
int wx;
String name;
int index;
int[] bbox;
long offset;
byte found;
TTFMtxEntry() {
name="";
found=0;
bbox=new int[4];
}

public String toString(TTFFile t) {
return new String("Glyph "+name+ " index: " + index +
" bbox [ "+t.get_ttf_funit(bbox[0])+
" " + t.get_ttf_funit(bbox[1]) +
" " + t.get_ttf_funit(bbox[2]) +
" " + t.get_ttf_funit(bbox[3]) + "]" +
"wx: "+t.get_ttf_funit(wx));
}
int wx;
String name;
int index;
Vector unicodeIndex;
int[] bbox;
long offset;
byte found;
TTFMtxEntry() {
name="";
found=0;
unicodeIndex = new Vector();
bbox=new int[4];
}
public String toString(TTFFile t) {
return new String("Glyph "+name+ " index: " + index +
" bbox [ "+t.get_ttf_funit(bbox[0])+
" " + t.get_ttf_funit(bbox[1]) +
" " + t.get_ttf_funit(bbox[2]) +
" " + t.get_ttf_funit(bbox[3]) + "]" +
"wx: "+t.get_ttf_funit(wx));
}
}

+ 76
- 154
src/org/apache/fop/fonts/apps/PFMReader.java View File

@@ -67,10 +67,6 @@ import java.util.Enumeration;
* @author jeremias.maerki@outline.ch
*/
public class PFMReader {

static private final String XSL_POSTPROCESS = "FontPostProcess.xsl";
static private final String XSL_SORT = "FontPostProcessSort.xsl";

private boolean invokedStandalone = false;

public PFMReader() {
@@ -88,13 +84,14 @@ public class PFMReader {
Vector arguments=new Vector();
for (int i=0; i < args.length; i++) {
if (args[i].startsWith("-")) {
i++;
if (i < args.length)
options.put(args[i-1], args[i]);
else
options.put(args[i-1], "");
if ((i+1) < args.length && !args[i+1].startsWith("-")) {
options.put(args[i], args[i+1]);
i++;
} else {
options.put(args[i], "");
}
} else {
arguments.addElement(args[i]);
arguments.addElement(args[i]);
}
}
@@ -107,18 +104,10 @@ public class PFMReader {
System.out.println(" java org.apache.fop.fonts.apps.PFMReader [options] metricfile.pfm xmlfile.xml\n");
System.out.println(" where options can be:\n");
System.out.println(" -fn <fontname>\n");
System.out.println(" default is to use the fontname in the .pfm file, but you can override\n");
System.out.println(" that name to make sure that the embedded font is used instead of installed\n");
System.out.println(" fonts when viewing documents with Acrobat Reader.\n");
System.out.println(" -cn <classname>\n");
System.out.println(" default is to use the fontname\n");
System.out.println(" -ef <path to the Type1 .pfb fontfile>\n");
System.out.println(" will add the possibility to embed the font. When running fop, fop will look\n");
System.out.println(" for this file to embed it\n");
System.out.println(" -er <path to Type1 fontfile relative to org/apache/fop/render/pdf/fonts>\n");
System.out.println(" you can also include the fontfile in the fop.jar file when building fop.\n");
System.out.println(" You can use both -ef and -er. The file specified in -ef will be searched first,\n");
System.out.println(" then the -er file.\n");
System.out.println(" default is to use the fontname in the .ttf file, but\n"+
" you can override that name to make sure that the\n");
System.out.println(" embedded font is used (if you're embedding fonts)\n");
System.out.println(" instead of installed fonts when viewing documents with Acrobat Reader.\n");
}
@@ -142,56 +131,54 @@ public class PFMReader {
* then the -er file.
*/
public static void main(String[] args) {
String embFile=null;
String embResource=null;
String className=null;
String fontName=null;
Hashtable options=new Hashtable();
String[] arguments=parseArguments(options, args);
PFMReader app = new PFMReader();
app.invokedStandalone = true;
System.out.println("PFM Reader v1.1");
System.out.println();

if (options.get("-ef") != null)
embFile=(String)options.get("-ef");
if (options.get("-er") != null)
embResource=(String)options.get("-er");
if (options.get("-fn") != null)
fontName=(String)options.get("-fn");
if (options.get("-cn") != null)
className=(String)options.get("-cn");

if (arguments.length != 2 ||
options.get("-h") != null ||
options.get("-help") != null ||
options.get("--help") != null)
displayUsage();
else {
PFMFile pfm = app.loadPFM(arguments[0]);
if (pfm != null) {
app.preview(pfm);

org.w3c.dom.Document doc = app.constructFontXML(pfm,
fontName,
className,
embResource,
embFile);

doc = app.postProcessXML(doc);
if (doc != null) {
String embFile=null;
String embResource=null;
String className=null;
String fontName=null;
Hashtable options=new Hashtable();
String[] arguments=parseArguments(options, args);
PFMReader app = new PFMReader();
app.invokedStandalone = true;
System.out.println("PFM Reader v1.1");
System.out.println();
if (options.get("-ef") != null)
embFile=(String)options.get("-ef");
if (options.get("-er") != null)
embResource=(String)options.get("-er");
if (options.get("-fn") != null)
fontName=(String)options.get("-fn");
if (options.get("-cn") != null)
className=(String)options.get("-cn");
if (arguments.length != 2 ||
options.get("-h") != null ||
options.get("-help") != null ||
options.get("--help") != null)
displayUsage();
else {
PFMFile pfm = app.loadPFM(arguments[0]);
if (pfm != null) {
app.preview(pfm);
org.w3c.dom.Document doc = app.constructFontXML(pfm,
fontName,
className,
embResource,
embFile);
app.writeFontXML(doc, arguments[1]);
}
}
}
}
}
}


/**
* Read a PFM file and returns it as an object.
*
@@ -286,7 +273,8 @@ public class PFMReader {
Document doc = new DocumentImpl();
Element root = doc.createElement("font-metrics");
doc.appendChild(root);

root.setAttribute("type", "TYPE1");
Element el = doc.createElement("font-name");
root.appendChild(el);
el.appendChild(doc.createTextNode(pfm.getPostscriptName()));
@@ -300,30 +288,12 @@ public class PFMReader {
s = new String(sb);
}

el = doc.createElement("class-name");
el = doc.createElement("embed");
root.appendChild(el);
if (className != null)
el.appendChild(doc.createTextNode(className));
else
el.appendChild(doc.createTextNode(s));

el = doc.createElement("embedFile");
root.appendChild(el);
if (file==null)
el.appendChild(doc.createTextNode("null"));
else
el.appendChild(doc.createTextNode("\""+escapeString(file)+"\""));
el = doc.createElement("embedResource");
root.appendChild(el);
if (resource==null)
el.appendChild(doc.createTextNode("null"));
else
el.appendChild(doc.createTextNode("\""+escapeString(resource)+"\""));
el = doc.createElement("subtype");
root.appendChild(el);
el.appendChild(doc.createTextNode("Type1"));
if (file!=null)
el.setAttribute("file", file);
if (resource!=null)
el.setAttribute("class", resource);

el = doc.createElement("encoding");
root.appendChild(el);
@@ -391,8 +361,8 @@ public class PFMReader {
for (short i = pfm.getFirstChar(); i < pfm.getLastChar(); i++) {
el = doc.createElement("char");
widths.appendChild(el);
el.setAttribute("ansichar", "0x00" + Integer.toHexString(i).toUpperCase());
el.setAttribute("width", new Integer(pfm.getCharWidth(i)).toString());
el.setAttribute("idx", Integer.toString(i));
el.setAttribute("wdt", new Integer(pfm.getCharWidth(i)).toString());
}


@@ -403,72 +373,20 @@ public class PFMReader {
el.setAttribute("kpx1", kpx1);
root.appendChild(el);
Element el2=null;
Hashtable h2=(Hashtable)pfm.getKerning().get(kpx1);
for (Enumeration enum2=h2.keys(); enum2.hasMoreElements(); ) {
String kpx2=(String)enum2.nextElement();
el2=doc.createElement("pair");
el2.setAttribute("kpx2", kpx2);
Integer val=(Integer)h2.get(kpx2);
el2.setAttribute("kern", val.toString());
el.appendChild(el2);
Integer kpx2=(Integer)enum2.nextElement();
el2=doc.createElement("pair");
el2.setAttribute("kpx2", kpx2.toString());
Integer val=(Integer)h2.get(kpx2);
el2.setAttribute("kern", val.toString());
el.appendChild(el2);
}
}
return doc;
}

/**
* Modifies the generated font metrics file. First, it processes the
* character mmappings, then it sorts them.
*
* @param doc The DOM document representing the font metrics file.
* @return A DOM document representing the processed font metrics file.
*/
public org.w3c.dom.Document postProcessXML(org.w3c.dom.Document doc) {
try {
OutputFormat format = new OutputFormat(doc); //Serialize DOM
XMLSerializer serial = new XMLSerializer(System.out, format);
serial.asDOMSerializer(); // As a DOM Serializer
serial.serialize(doc.getDocumentElement());
System.out.println("Postprocessing...");
System.out.println();


InputStream xsl = this.getClass().getResourceAsStream(XSL_POSTPROCESS);
if (xsl == null) {
throw new Exception("Resource " + XSL_POSTPROCESS + " not found");
}
Document targetDoc = new DocumentImpl();
org.apache.fop.tools.xslt.XSLTransform.transform(doc, xsl, targetDoc);

System.out.println("Sorting...");
System.out.println();

// Sort the whole thing

xsl = this.getClass().getResourceAsStream(XSL_SORT);
if (xsl == null) {
throw new Exception("Resource " + XSL_SORT + " not found");
}

org.w3c.dom.Document targetDocSorted = new DocumentImpl();

org.apache.fop.tools.xslt.XSLTransform.transform(targetDoc, xsl, targetDocSorted);

return targetDocSorted;

} catch (Exception e) {
e.printStackTrace();
return null;
}
}

private String escapeString(String str) {
StringBuffer esc=new StringBuffer();
@@ -483,3 +401,7 @@ public class PFMReader {
return esc.toString();
}
}





+ 186
- 206
src/org/apache/fop/fonts/apps/TTFReader.java View File

@@ -66,9 +66,6 @@ import java.util.Enumeration;
*/
public class TTFReader {

static private final String XSL_POSTPROCESS = "TTFPostProcess.xsl";
static private final String XSL_SORT = "TTFPostProcessSort.xsl";

private boolean invokedStandalone = false;

public TTFReader() {
@@ -86,13 +83,14 @@ public class TTFReader {
Vector arguments=new Vector();
for (int i=0; i < args.length; i++) {
if (args[i].startsWith("-")) {
i++;
if (i < args.length)
options.put(args[i-1], args[i]);
else
options.put(args[i-1], "");
if ((i+1) < args.length && !args[i+1].startsWith("-")) {
options.put(args[i], args[i+1]);
i++;
} else {
options.put(args[i], "");
}
} else {
arguments.addElement(args[i]);
arguments.addElement(args[i]);
}
}

@@ -105,19 +103,22 @@ public class TTFReader {
private final static void displayUsage() {
System.out.println(" java org.apache.fop.fonts.apps.TTFReader [options] fontfile.ttf xmlfile.xml\n");
System.out.println(" where options can be:\n");
System.out.println("-enc cid");
System.out.println(" With this option you create a CID keyed font.");
System.out.println(" If you're going to use characters outside the");
System.out.println(" pdfencoding range (almost the same as iso-8889-1)");
System.out.println(" you must add this option.");
System.out.println("-ttcname <fontname>");
System.out.println(" If you're reading data from a TrueType Collection");
System.out.println(" (.ttc file) you must specify which font from the");
System.out.println(" collection you will read metrics from. If you read");
System.out.println(" from a .ttc file without this option, the fontnames");
System.out.println(" will be listed for you.");
System.out.println(" -fn <fontname>\n");
System.out.println(" default is to use the fontname in the .ttf file, but you can override\n");
System.out.println(" that name to make sure that the embedded font is used instead of installed\n");
System.out.println(" fonts when viewing documents with Acrobat Reader.\n");
System.out.println(" -cn <classname>\n");
System.out.println(" default is to use the fontname\n");
System.out.println(" -ef <path to the truetype fontfile>\n");
System.out.println(" will add the possibility to embed the font. When running fop, fop will look\n");
System.out.println(" for this file to embed it\n");
System.out.println(" -er <path to truetype fontfile relative to org/apache/fop/render/pdf/fonts>\n");
System.out.println(" you can also include the fontfile in the fop.jar file when building fop.\n");
System.out.println(" You can use both -ef and -er. The file specified in -ef will be searched first,\n");
System.out.println(" then the -er file.\n");
System.out.println(" default is to use the fontname in the .ttf file, but\n"+
" you can override that name to make sure that the\n");
System.out.println(" embedded font is used (if you're embedding fonts)\n");
System.out.println(" instead of installed fonts when viewing documents with Acrobat Reader.\n");
}
@@ -145,6 +146,8 @@ public class TTFReader {
String embResource=null;
String className=null;
String fontName=null;
String ttcName=null;
boolean isCid=false;
Hashtable options=new Hashtable();
String[] arguments=parseArguments(options, args);
@@ -152,9 +155,18 @@ public class TTFReader {
TTFReader app = new TTFReader();
app.invokedStandalone = true;
System.out.println("TTF Reader v1.0");
System.out.println("TTF Reader v1.1");
System.out.println();

if (options.get("-enc") != null) {
String enc = (String)options.get("-enc");
if ("cid".equals(enc))
isCid=true;
}
if (options.get("-ttcname") != null)
ttcName=(String)options.get("-ttcname");
if (options.get("-ef") != null)
embFile=(String)options.get("-ef");
@@ -173,20 +185,26 @@ public class TTFReader {
options.get("--help") != null)
displayUsage();
else {
TTFFile ttf = app.loadTTF(arguments[0]);
TTFFile ttf = app.loadTTF(arguments[0], ttcName);
if (ttf != null) {
app.preview(ttf);
org.w3c.dom.Document doc = app.constructFontXML(ttf,
fontName,
className,
embResource,
embFile);
embFile,
isCid,
ttcName);
doc = app.postProcessXML(doc);
if (doc != null) {
app.writeFontXML(doc, arguments[1]);
}
if (ttf.isEmbeddable())
System.out.println("This font contains no embedding license restrictions");
else
System.out.println("** Note: This font contains license retrictions for\n"+
" embedding. This font can't be embedded.");
}
}
}
@@ -195,16 +213,16 @@ public class TTFReader {
* Read a TTF file and returns it as an object.
*
* @param filename The filename of the PFM file.
* @return The PFM as an object.
* @return The TTF as an object.
*/
public TTFFile loadTTF(String filename) {
public TTFFile loadTTF(String fileName, String fontName) {
TTFFile ttfFile=new TTFFile();
try {
System.out.println("Reading " + filename + "...");
System.out.println("Reading " + fileName + "...");
System.out.println();

FontFileReader reader = new FontFileReader(filename);
ttfFile.readFont(reader);
FontFileReader reader = new FontFileReader(fileName);
ttfFile.readFont(reader, fontName);
} catch (Exception e) {
e.printStackTrace();
return null;
@@ -212,45 +230,6 @@ public class TTFReader {
return ttfFile;
}

/**
* Displays a preview of the TTF file on the console.
*
* @param ttf The TTF file to preview.
*/
public void preview(TTFFile ttf) {
PrintStream out = System.out;

out.print("Font: ");
out.println(ttf.getWindowsName());
out.print("Name: ");
out.println(ttf.getPostscriptName());
out.print("CharSet: ");
out.println(ttf.getCharSetName());
out.print("CapHeight: ");
out.println(ttf.getCapHeight());
out.print("XHeight: ");
out.println(ttf.getXHeight());
out.print("LowerCaseAscent: ");
out.println(ttf.getLowerCaseAscent());
out.print("LowerCaseDescent: ");
out.println(ttf.getLowerCaseDescent());
out.print("Having widths for ");
out.print(ttf.getLastChar()-ttf.getFirstChar());
out.print(" characters (");
out.print(ttf.getFirstChar());
out.print("-");
out.print(ttf.getLastChar());
out.println(").");
out.print("for example: Char ");
out.print(ttf.getFirstChar());
out.print(" has a width of ");
out.println(ttf.getCharWidth(ttf.getFirstChar()));
out.println();
if (ttf.isEmbeddable())
out.println("This font might be embedded");
else
out.println("This font might not be embedded");
}

/**
* Writes the generated DOM Document to a file.
@@ -276,21 +255,26 @@ public class TTFReader {
}

/**
* Generates the font metrics file from the PFM file.
* Generates the font metrics file from the TTF/TTC file.
*
* @param pfm The PFM file to generate the font metrics from.
* @param ttf The PFM file to generate the font metrics from.
* @return The DOM document representing the font metrics file.
*/
public org.w3c.dom.Document constructFontXML(TTFFile ttf, String fontName,
String className, String resource,
String file) {
String file, boolean isCid,
String ttcName) {
System.out.println("Creating xml font file...");
System.out.println();

Document doc = new DocumentImpl();
Element root = doc.createElement("font-metrics");
doc.appendChild(root);

if (isCid)
root.setAttribute("type", "TYPE0");
else
root.setAttribute("type", "TRUETYPE");
Element el = doc.createElement("font-name");
root.appendChild(el);

@@ -298,51 +282,19 @@ public class TTFReader {
// "Perpetua-Bold", but the TrueType spec says that in the ttf file
// it should be "Perpetua,Bold".

String s = ttf.getPostscriptName();
String s = stripWhiteSpace(ttf.getPostscriptName());

if (fontName != null)
el.appendChild(doc.createTextNode(fontName));
else
el.appendChild(doc.createTextNode(s.replace('-', ',')));

int pos = s.indexOf("-");
if (pos >= 0) {
char sb[] = new char[s.length() - 1];
s.getChars(0, pos, sb, 0);
s.getChars(pos + 1, s.length(), sb, pos);
s = new String(sb);
}
el = doc.createElement("class-name");
root.appendChild(el);
if (className != null)
el.appendChild(doc.createTextNode(className));
el.appendChild(doc.createTextNode(stripWhiteSpace(fontName)));
else
el.appendChild(doc.createTextNode(s));
el.appendChild(doc.createTextNode(s));

el = doc.createElement("embedFile");
root.appendChild(el);
//if (file==null || !ttf.isEmbeddable())
if (file==null)
el.appendChild(doc.createTextNode("null"));
else
el.appendChild(doc.createTextNode("\""+escapeString(file)+"\""));
el = doc.createElement("embedResource");
el = doc.createElement("embed");
root.appendChild(el);
//if (resource==null || !ttf.isEmbeddable())
if (resource==null)
el.appendChild(doc.createTextNode("null"));
else
el.appendChild(doc.createTextNode("\""+escapeString(resource)+"\""));

el = doc.createElement("subtype");
root.appendChild(el);
el.appendChild(doc.createTextNode("TRUETYPE"));

el = doc.createElement("encoding");
root.appendChild(el);
el.appendChild(doc.createTextNode(ttf.getCharSetName()+"Encoding"));
if (file != null && ttf.isEmbeddable())
el.setAttribute("file", file);
if (resource != null && ttf.isEmbeddable())
el.setAttribute("class", resource);

el = doc.createElement("cap-height");
root.appendChild(el);
@@ -353,12 +305,12 @@ public class TTFReader {
root.appendChild(el);
value = new Integer(ttf.getXHeight());
el.appendChild(doc.createTextNode(value.toString()));
el = doc.createElement("ascender");
root.appendChild(el);
value = new Integer(ttf.getLowerCaseAscent());
el.appendChild(doc.createTextNode(value.toString()));
el = doc.createElement("descender");
root.appendChild(el);
value = new Integer(ttf.getLowerCaseDescent());
@@ -379,115 +331,143 @@ public class TTFReader {
root.appendChild(el);
value = new Integer(ttf.getFlags());
el.appendChild(doc.createTextNode(value.toString()));
el = doc.createElement("stemv");
root.appendChild(el);
value = new Integer(ttf.getStemV());
el.appendChild(doc.createTextNode(value.toString()));
el = doc.createElement("italicangle");
root.appendChild(el);
value = new Integer(ttf.getItalicAngle());
el.appendChild(doc.createTextNode(value.toString()));

el = doc.createElement("first-char");
root.appendChild(el);
value = new Integer(ttf.getFirstChar());
el.appendChild(doc.createTextNode(value.toString()));

el = doc.createElement("last-char");
root.appendChild(el);
value = new Integer(ttf.getLastChar());
el.appendChild(doc.createTextNode(value.toString()));

Element widths = doc.createElement("widths");
root.appendChild(widths);

for (short i = ttf.getFirstChar(); i < ttf.getLastChar(); i++) {
el = doc.createElement("char");
widths.appendChild(el);
//el.setAttribute("ansichar", "0x00" + Integer.toHexString(i).toUpperCase());
el.setAttribute("name", "0x00" +
Integer.toHexString(i).toUpperCase());
el.setAttribute("width",
new Integer(ttf.getCharWidth(i)).toString());
}

// Get kerning
for (Enumeration enum=ttf.getKerning().keys(); enum.hasMoreElements();) {
String kpx1=(String)enum.nextElement();
el=doc.createElement("kerning");
el.setAttribute("kpx1", kpx1);
root.appendChild(el);
Element el2=null;
Hashtable h2=(Hashtable)ttf.getKerning().get(kpx1);
for (Enumeration enum2=h2.keys(); enum2.hasMoreElements(); ) {
String kpx2=(String)enum2.nextElement();
el2=doc.createElement("pair");
el2.setAttribute("kpx2", kpx2);
Integer val=(Integer)h2.get(kpx2);
el2.setAttribute("kern", val.toString());
el.appendChild(el2);
}
if (ttcName != null) {
el = doc.createElement("ttc-name");
root.appendChild(el);
el.appendChild(doc.createTextNode(ttcName));
}
return doc;
}
el = doc.createElement("subtype");
root.appendChild(el);
// Fill in extras for CID keyed fonts
if (isCid) {
el.appendChild(doc.createTextNode("TYPE0"));

/**
* Modifies the generated font metrics file. First, it processes the
* character mmappings, then it sorts them.
*
* @param doc The DOM document representing the font metrics file.
* @return A DOM document representing the processed font metrics file.
*/
public org.w3c.dom.Document postProcessXML(org.w3c.dom.Document doc) {
if (true)
return doc;
try {
OutputFormat format = new OutputFormat(doc); //Serialize DOM
XMLSerializer serial = new XMLSerializer(System.out, format);
serial.asDOMSerializer(); // As a DOM Serializer
serial.serialize(doc.getDocumentElement());
Element mel = doc.createElement("multibyte-extras");
root.appendChild(mel);
System.out.println("Postprocessing...");
System.out.println();


InputStream xsl = this.getClass().getResourceAsStream(XSL_POSTPROCESS);
if (xsl == null) {
throw new Exception("Resource " + XSL_POSTPROCESS + " not found");
el = doc.createElement("cid-type");
mel.appendChild(el);
el.appendChild(doc.createTextNode("CIDFontType2"));

el = doc.createElement("default-width");
mel.appendChild(el);
el.appendChild(doc.createTextNode("0"));

el = doc.createElement("bfranges");
mel.appendChild(el);
for (Enumeration e=ttf.getCMaps().elements(); e.hasMoreElements();) {
TTFCmapEntry ce = (TTFCmapEntry)e.nextElement();
Element el2=doc.createElement("bf");
el.appendChild(el2);
el2.setAttribute("us", Integer.toString(ce.unicodeStart));
el2.setAttribute("ue", Integer.toString(ce.unicodeEnd));
el2.setAttribute("gi", Integer.toString(ce.glyphStartIndex));
}
Document targetDoc = new DocumentImpl();
org.apache.fop.tools.xslt.XSLTransform.transform(doc, xsl, targetDoc);

System.out.println("Sorting...");
System.out.println();

// Sort the whole thing

xsl = this.getClass().getResourceAsStream(XSL_SORT);
if (xsl == null) {
throw new Exception("Resource " + XSL_SORT + " not found");
el = doc.createElement("cid-widths");
el.setAttribute("start-index", "0");
mel.appendChild(el);

int[] wx = ttf.getWidths();
for (int i = 0; i < wx.length; i++) {
Element wxel=doc.createElement("wx");
wxel.setAttribute("w", Integer.toString(wx[i]));
el.appendChild(wxel);
}

org.w3c.dom.Document targetDocSorted = new DocumentImpl();
} else {
// Fill in extras for singlebyte fonts
el.appendChild(doc.createTextNode("TRUETYPE"));

org.apache.fop.tools.xslt.XSLTransform.transform(targetDoc, xsl, targetDocSorted);
Element sel=doc.createElement("singlebyte-extras");
root.appendChild(sel);
el = doc.createElement("encoding");
sel.appendChild(el);
el.appendChild(doc.createTextNode(ttf.getCharSetName()));

return targetDocSorted;
el = doc.createElement("first-char");
sel.appendChild(el);
value = new Integer(ttf.getFirstChar());
el.appendChild(doc.createTextNode(value.toString()));
el = doc.createElement("last-char");
sel.appendChild(el);
value = new Integer(ttf.getLastChar());
el.appendChild(doc.createTextNode(value.toString()));
Element widths = doc.createElement("widths");
sel.appendChild(widths);
for (short i = ttf.getFirstChar(); i < ttf.getLastChar(); i++) {
el = doc.createElement("char");
widths.appendChild(el);
el.setAttribute("idx", Integer.toString(i));
el.setAttribute("wdt", Integer.toString(ttf.getCharWidth(i)));
}
}
// Get kerning
Enumeration enum;
if (isCid)
enum=ttf.getKerning().keys();
else
enum=ttf.getAnsiKerning().keys();
while (enum.hasMoreElements()) {
Integer kpx1=(Integer)enum.nextElement();

} catch (Exception e) {
e.printStackTrace();
return null;
el=doc.createElement("kerning");
el.setAttribute("kpx1", kpx1.toString());
root.appendChild(el);
Element el2=null;
Hashtable h2;
if (isCid)
h2 = (Hashtable)ttf.getKerning().get(kpx1);
else
h2 = (Hashtable)ttf.getAnsiKerning().get(kpx1);
for (Enumeration enum2=h2.keys(); enum2.hasMoreElements(); ) {
Integer kpx2=(Integer)enum2.nextElement();
if (isCid || kpx2.intValue() < 256) {
el2=doc.createElement("pair");
el2.setAttribute("kpx2", kpx2.toString());
Integer val=(Integer)h2.get(kpx2);
el2.setAttribute("kern", val.toString());
el.appendChild(el2);
}
}
}
return doc;
}

private String stripWhiteSpace(String s) {
char[] ch = new char[s.length()];
s.getChars(0, s.length(), ch, 0);
StringBuffer stb = new StringBuffer();
for (int i = 0; i < ch.length; i++)
if (ch[i] != ' ' && ch[i] != '\r' &&
ch[i] != '\n' && ch[i] != '\t')
stb.append(ch[i]);

return stb.toString();
}
private String escapeString(String str) {
StringBuffer esc=new StringBuffer();

+ 12
- 5
src/org/apache/fop/layout/FontInfo.java View File

@@ -57,13 +57,14 @@ import java.util.Enumeration;
import org.apache.fop.apps.FOPException;

public class FontInfo {
Hashtable usedFonts;
Hashtable triplets; // look up a font-triplet to find a font-name
Hashtable fonts; // look up a font-name to get a font (that implements FontMetric at least)

public FontInfo() {
this.triplets = new Hashtable();
this.fonts = new Hashtable();
this.fonts = new Hashtable();
this.usedFonts = new Hashtable();
}

public void addFontProperties(String name, String family, String style, String weight) {
@@ -109,6 +110,8 @@ public class FontInfo {
}
MessageHandler.errorln("WARNING: unknown font "+family+" so defaulted font to any");
}

usedFonts.put(f, fonts.get(f));
return f;
}

@@ -116,13 +119,17 @@ public class FontInfo {
return this.fonts;
}

public Hashtable getUsedFonts() {
return this.usedFonts;
}

public FontMetric getMetricsFor(String fontName) throws FOPException {
return (FontMetric)fonts.get(fontName);
usedFonts.put(fontName, fonts.get(fontName));
return (FontMetric)fonts.get(fontName);
}

public FontMetric getMetricsFor(String family, String style, String weight) throws FOPException {
// given a family, style and weight, return the metric

return (FontMetric)fonts.get(fontLookup(family,style,weight));
return (FontMetric)fonts.get(fontLookup(family,style,weight));
}
}

+ 94
- 60
src/org/apache/fop/layout/FontState.java View File

@@ -54,17 +54,17 @@ import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.properties.FontVariant;

public class FontState {
protected FontInfo fontInfo;
private String fontName;
private int fontSize;
private String fontFamily;
private String fontStyle;
private String fontWeight;
private FontMetric metric;
private int fontVariant;
public FontState(FontInfo fontInfo, String fontFamily, String fontStyle, String fontWeight, int fontSize, int fontVariant) throws FOPException {
protected FontInfo fontInfo;
private String fontName;
private int fontSize;
private String fontFamily;
private String fontStyle;
private String fontWeight;
private FontMetric metric;
private int fontVariant;
public FontState(FontInfo fontInfo, String fontFamily, String fontStyle, String fontWeight, int fontSize, int fontVariant) throws FOPException {
this.fontInfo = fontInfo;
this.fontFamily = fontFamily;
this.fontStyle = fontStyle;
@@ -73,65 +73,99 @@ public class FontState {
this.fontName = fontInfo.fontLookup(fontFamily,fontStyle,fontWeight);
this.metric = fontInfo.getMetricsFor(fontName);
this.fontVariant = fontVariant;
}
public int getAscender() {
}
public int getAscender() {
return metric.getAscender(fontSize) / 1000;
}
public int getCapHeight() {
}
public int getCapHeight() {
return metric.getCapHeight(fontSize) / 1000;
}
public int getDescender() {
}
public int getDescender() {
return metric.getDescender(fontSize) / 1000;
}
public String getFontName() {
}
public String getFontName() {
return this.fontName;
}
public int getFontSize() {
}
public int getFontSize() {
return this.fontSize;
}
public String getFontWeight() {
}
public String getFontWeight() {
return this.fontWeight;
}
public String getFontFamily() {
}
public String getFontFamily() {
return this.fontFamily;
}
public String getFontStyle() {
}
public String getFontStyle() {
return this.fontStyle;
}
public int getFontVariant() {
}
public int getFontVariant() {
return this.fontVariant;
}
public FontInfo getFontInfo() {
}
public FontInfo getFontInfo() {
return this.fontInfo;
}
public int getXHeight() {
}
public int getXHeight() {
return metric.getXHeight(fontSize) / 1000;
}
public java.util.Hashtable getKerning() {
java.util.Hashtable ret=new java.util.Hashtable();
try {
FontMetric fm=fontInfo.getMetricsFor(fontFamily, fontStyle, fontWeight);
if (fm instanceof org.apache.fop.layout.FontDescriptor) {
org.apache.fop.layout.FontDescriptor fdes=(org.apache.fop.layout.FontDescriptor)fm;
ret=fdes.getKerningInfo();
}
} catch (Exception e) {}
return ret;
}

public int width(int charnum) {
// returns width of given character number in millipoints
}
public java.util.Hashtable getKerning() {
java.util.Hashtable ret=new java.util.Hashtable();
try {
FontMetric fm=fontInfo.getMetricsFor(fontFamily, fontStyle,
fontWeight);
if (fm instanceof org.apache.fop.layout.FontDescriptor) {
org.apache.fop.layout.FontDescriptor fdes=
(org.apache.fop.layout.FontDescriptor)fm;
ret=fdes.getKerningInfo();
}
} catch (Exception e) {}
return ret;
}
public int width(int charnum) {
// returns width of given character number in millipoints
return (metric.width(charnum, fontSize) / 1000);
}
}
/**
* Map a java character (unicode) to a font character
* Default uses CodePointMapping
*/
public char mapChar(char c) {
try {
FontMetric fm=fontInfo.getMetricsFor(fontFamily, fontStyle,
fontWeight);
if (fm instanceof org.apache.fop.render.pdf.Font) {
org.apache.fop.render.pdf.Font f=
(org.apache.fop.render.pdf.Font)fm;
return f.mapChar(c);
}
} catch (Exception e) {}

// Use default CodePointMapping
if (c > 127) {
char d = org.apache.fop.render.pdf.CodePointMapping.map[c];
if (d != 0) {
c = d;
} else {
c = '#';
}
}
return c;
}
}




+ 16
- 18
src/org/apache/fop/layout/LineArea.java View File

@@ -184,7 +184,9 @@ public class LineArea extends Area {
*/

//Space must be alloted to the page number, so currently we give it 3 spaces
int width = currentFontState.width(32) * 3;
int width = currentFontState.width(currentFontState.mapChar(' '));


PageNumberInlineArea pia =
new PageNumberInlineArea(currentFontState, this.red,
@@ -214,6 +216,10 @@ public class LineArea extends Area {
int wordStart = start;
int wordLength = 0;
int wordWidth = 0;
// With CID fonts, space isn't neccecary currentFontState.width(32)
int whitespaceWidth =
currentFontState.width(currentFontState.mapChar(' '));
char[] data = new char[odata.length];
for (int count = 0; count < odata.length; count++) {
data[count] = odata[count];
@@ -224,18 +230,10 @@ public class LineArea extends Area {
int charWidth;
/* get the character */
char c = data[i];

if (c > 127) {
/* this class shouldn't be hard coded */
char d = org.apache.fop.render.pdf.CodePointMapping.map[c];
if (d != 0) {
c = data[i] = d;
} else {
MessageHandler.error("ch" + (int) c + "?");
c = data[i] = '#';
}
}

if (!((c == ' ') || (c == '\n') || (c == '\r') ||
(c == '\t')))
c = data[i] = currentFontState.mapChar(c);
charWidth = currentFontState.width(c);

if ((c == ' ') || (c == '\n') || (c == '\r') ||
@@ -248,12 +246,12 @@ public class LineArea extends Area {
if (this.whiteSpaceCollapse ==
WhiteSpaceCollapse.FALSE) {
if (c == ' ') {
spaceWidth += currentFontState.width(32);
spaceWidth += whitespaceWidth;
} else if (c == '\n') {
// force line break
return i;
} else if (c == '\t') {
spaceWidth += 8 * currentFontState.width(32);
spaceWidth += 8 * whitespaceWidth;
}
} // else ignore it

@@ -339,7 +337,7 @@ public class LineArea extends Area {

embeddedLinkStart = 0; //reset embeddedLinkStart since a space was encountered

spaceWidth = currentFontState.width(32);
spaceWidth = whitespaceWidth;

/*
here is the place for space-treatment value 'ignore':
@@ -359,7 +357,7 @@ public class LineArea extends Area {
// force a line break
return i;
} else if (c == '\t') {
spaceWidth = currentFontState.width(32);
spaceWidth = whitespaceWidth;
}
}

@@ -370,7 +368,7 @@ public class LineArea extends Area {
if (this.whiteSpaceCollapse ==
WhiteSpaceCollapse.FALSE) {
prev = WHITESPACE;
spaceWidth = currentFontState.width(32);
spaceWidth = whitespaceWidth;
} else {
// skip over it
start++;

+ 27
- 10
src/org/apache/fop/pdf/PDFCIDFont.java View File

@@ -69,6 +69,7 @@ public class PDFCIDFont extends PDFObject {
protected PDFWArray w2;
protected PDFCIDSystemInfo systemInfo;
protected PDFCIDFontDescriptor descriptor;
protected PDFCMap cmap;
/**
* /CIDToGIDMap (only for CIDFontType2, see p 212)
* can be either "Identity" (default) or a PDFStream
@@ -79,14 +80,15 @@ public class PDFCIDFont extends PDFObject {
/**
* create the /Font object
*/
public PDFCIDFont(int number, String basefont, String cidtype,
int dw, int[] w, String registry, String ordering, int supplement,
PDFCIDFontDescriptor descriptor) {
public PDFCIDFont(int number, String basefont, byte cidtype,
int dw, int[] w,
String registry, String ordering, int supplement,
PDFCIDFontDescriptor descriptor) {

super(number);

this.basefont = basefont;
this.cidtype = cidtype;
this.cidtype = TYPE_NAMES[(int)cidtype];
this.dw = new Integer(dw);
this.w = new PDFWArray();
this.w.addEntry(0, w);
@@ -95,19 +97,20 @@ public class PDFCIDFont extends PDFObject {
this.systemInfo = new PDFCIDSystemInfo(registry, ordering, supplement);
this.descriptor = descriptor;
this.cidMap = null;
this.cmap = null;
}

/**
* create the /Font object
*/
public PDFCIDFont(int number, String basefont, String cidtype,
public PDFCIDFont(int number, String basefont, byte cidtype,
int dw, PDFWArray w, PDFCIDSystemInfo systemInfo,
PDFCIDFontDescriptor descriptor) {

super(number);

this.basefont = basefont;
this.cidtype = cidtype;
this.cidtype = TYPE_NAMES[(int)cidtype];
this.dw = new Integer(dw);
this.w = w;
this.dw2 = null;
@@ -115,6 +118,7 @@ public class PDFCIDFont extends PDFObject {
this.systemInfo = systemInfo;
this.descriptor = descriptor;
this.cidMap = null;
this.cmap = null;
}

/** set the /DW attribute */
@@ -137,6 +141,13 @@ public class PDFCIDFont extends PDFObject {
this.dw2 = new int[] {posY, displacementY};
}

/**
* Set the CMap used as /ToUnicode cmap
*/
public void setCMAP(PDFCMap cmap) {
this.cmap = cmap;
}
/** set the /W2 array */
public void setW2(PDFWArray w2) {
this.w2 = w2;
@@ -172,16 +183,20 @@ public class PDFCIDFont extends PDFObject {
p.append(cidMap.referencePDF());
}
p.append(" \n/Subtype /"); p.append(this.cidtype);
p.append("\n"); p.append(systemInfo.toPDF());
p.append("\n"); p.append(systemInfo.toPDFString());
p.append("\n/FontDescriptor ");
p.append(this.descriptor.referencePDF());

if (cmap != null) {
p.append("\n/ToUnicode ");
p.append(cmap.referencePDF());
}
if (dw != null) {
p.append("\n/DW "); p.append(this.dw);
}
if (w != null) {
p.append("\n/W ");
p.append(w.toPDF());
p.append(" \n>>\nendobj\n");
p.append(w.toPDFString());
}
if (dw2 != null) {
p.append("\n/DW2 ["); // always two values, see p 211
@@ -191,9 +206,11 @@ public class PDFCIDFont extends PDFObject {
}
if (w2 != null) {
p.append("\n/W2 ");
p.append(w2.toPDF());
p.append(w2.toPDFString());
p.append(" \n>>\nendobj\n");
}
p.append(" \n>>\nendobj\n");
return p.toString();
}
}


+ 1
- 0
src/org/apache/fop/pdf/PDFCIDFontDescriptor.java View File

@@ -92,6 +92,7 @@ public class PDFCIDFontDescriptor extends PDFFontDescriptor {
}

protected void fillInPDF(StringBuffer p) {
p.append("\n/MissingWidth 500\n");
if (lang != null) {
p.append("\n/Lang /"); p.append(lang);
}

+ 60
- 11
src/org/apache/fop/pdf/PDFCMap.java View File

@@ -150,6 +150,12 @@ public class PDFCMap extends PDFStream {
this.wMode = mode;
}

public void addContents() {
StringBuffer p=new StringBuffer();
fillInPDF(p);
add(p.toString());
}
/**
* set the base CMap
*
@@ -169,16 +175,59 @@ public class PDFCMap extends PDFStream {
}

public void fillInPDF(StringBuffer p) {
p.append(" /Type /CMap\n/CMapName /" + name);
p.append("\n"); p.append(sysInfo.toPDF());
p.append("\n/WMode "); p.append(wMode);
if (base != null) {
p.append("\n/UseCMap ");
if (base instanceof String) {
p.append("/"+base);
} else { // base instanceof PDFStream
p.append(((PDFStream)base).referencePDF());
}
}
//p.append("/Type /CMap\n");
//p.append(sysInfo.toPDFString());
//p.append("/CMapName /" + name);
//p.append("\n");
p.append("%!PS-Adobe-3.0 Resource-CMap\n");
p.append("%%DocumentNeededResources: ProcSet (CIDInit)\n");
p.append("%%IncludeResource: ProcSet (CIDInit)\n");
p.append("%%BeginResource: CMap (" + name + ")\n");
p.append("%%EndComments\n");
p.append("/CIDInit /ProcSet findresource begin\n");
p.append("12 dict begin\n");
p.append("begincmap\n");
p.append("/CIDSystemInfo 3 dict dup begin\n");
p.append(" /Registry (Adobe) def\n");
p.append(" /Ordering (Identity) def\n");
p.append(" /Supplement 0 def\n");
p.append("end def\n");

p.append("/CMapVersion 1 def\n");
p.append("/CMapType 1 def\n");
p.append("/CMapName /" + name + " def\n");

p.append("1 begincodespacerange\n");
p.append("<0000> <FFFF>\n");
p.append("endcodespacerange\n");
p.append("1 begincidrange\n");
p.append("<0000> <FFFF> 0\n");
p.append("endcidrange\n");
//p.append("1 beginbfrange\n");
//p.append("<0020> <0100> <0000>\n");
//p.append("endbfrange\n");
p.append("endcmap\n");
p.append("CMapName currentdict /CMap defineresource pop\n");
p.append("end\n");
p.append("end\n");
p.append("%%EndResource\n");
p.append("%%EOF\n");
/*
p.append(" /Type /CMap\n/CMapName /" + name);
p.append("\n");
p.append("\n/WMode "); p.append(wMode);
if (base != null) {
p.append("\n/UseCMap ");
if (base instanceof String) {
p.append("/"+base);
} else { // base instanceof PDFStream
p.append(((PDFStream)base).referencePDF());
}
}
*/
}
}

+ 100
- 38
src/org/apache/fop/pdf/PDFDocument.java View File

@@ -61,6 +61,8 @@ import org.apache.fop.image.FopImage;
import org.apache.fop.layout.LinkSet;
import org.apache.fop.datatypes.ColorSpace;

import org.apache.fop.render.pdf.CIDFont;

import org.apache.fop.datatypes.IDReferences;
import org.apache.fop.layout.Page;
import org.apache.fop.layout.FontMetric;
@@ -751,59 +753,119 @@ public class PDFDocument {
/* create a PDFFont with the next object number and add to the
list of objects */
if (descriptor == null) {
PDFFont font = new PDFFont(++this.objectcount, fontname, PDFFont.TYPE1,
basefont, encoding);
PDFFont font = new PDFFont(++this.objectcount, fontname,
PDFFont.TYPE1,
basefont, encoding);
this.objects.addElement(font);
return font;
} else {
byte subtype=PDFFont.TYPE1;
if (metrics instanceof org.apache.fop.render.pdf.Font)
subtype=((org.apache.fop.render.pdf.Font)metrics).getSubType();
PDFFontNonBase14 font = (PDFFontNonBase14)PDFFont.createFont(
byte subtype=PDFFont.TYPE1;
if (metrics instanceof org.apache.fop.render.pdf.Font)
subtype=((org.apache.fop.render.pdf.Font)metrics).getSubType();
PDFFontDescriptor pdfdesc = makeFontDescriptor(descriptor,
subtype);
PDFFontNonBase14 font = null;
if (subtype == PDFFont.TYPE0) {
PDFCMap cmap = new PDFCMap(++this.objectcount,
"fop-ucs-H",
new PDFCIDSystemInfo("Adobe",
"Identity",
0));
cmap.addContents();
this.objects.addElement(cmap);
font = (PDFFontNonBase14)PDFFont.createFont(
++this.objectcount, fontname,
subtype, basefont, cmap);
} else {
font = (PDFFontNonBase14)PDFFont.createFont(
++this.objectcount, fontname,
subtype, basefont, encoding);
}
this.objects.addElement(font);
PDFFontDescriptor pdfdesc = makeFontDescriptor(descriptor);
font.setDescriptor(pdfdesc);
font.setWidthMetrics(metrics.getFirstChar(), metrics.getLastChar(),
makeArray(metrics.getWidths(1)));
if (subtype == PDFFont.TYPE0) {
CIDFont cidMetrics = (CIDFont)metrics;
PDFCIDSystemInfo sysInfo =
new PDFCIDSystemInfo(cidMetrics.getRegistry(),
cidMetrics.getOrdering(),
cidMetrics.getSupplement());
PDFCIDFont cidFont =
new PDFCIDFont(++this.objectcount, basefont,
cidMetrics.getCidType(),
cidMetrics.getDefaultWidth(),
cidMetrics.getWidths(),
sysInfo, (PDFCIDFontDescriptor)pdfdesc);
this.objects.addElement(cidFont);
//((PDFFontType0)font).setCMAP(cmap);
((PDFFontType0)font).setDescendantFonts(cidFont);
} else {
font.setWidthMetrics(metrics.getFirstChar(),
metrics.getLastChar(),
makeArray(metrics.getWidths(1)));
}
return font;
}
}


/**
* make a /FontDescriptor object for a CID font
* make a /FontDescriptor object
*/
public PDFFontDescriptor makeFontDescriptor(FontDescriptor desc) {

/* create a PDFFontDescriptor with the next object number and add to
the list of objects */
PDFFontDescriptor font =
new PDFFontDescriptor(++this.objectcount,
desc.fontName(), desc.getAscender(), desc.getDescender(),
desc.getCapHeight(), desc.getFlags(),
new PDFRectangle(desc.getFontBBox()), desc.getStemV(),
desc.getItalicAngle());
// Check if embedding of this font is enabled in the configurationfile
// and that the font is embeddable
java.util.Vector cfgv=
org.apache.fop.configuration.Configuration.getListValue("embed-fonts", 0);
if (cfgv!=null && cfgv.contains(desc.fontName()) && desc.isEmbeddable()) {
PDFStream stream=desc.getFontFile(this.objectcount+1);
if (stream!=null) {
this.objectcount++;
font.setFontFile(desc.getSubType(), stream);
this.objects.addElement(font);
this.objects.addElement(stream);
}
} else {
this.objects.addElement(font);
}
public PDFFontDescriptor makeFontDescriptor(FontDescriptor desc,
byte subtype) {
PDFFontDescriptor font = null;
if (subtype == PDFFont.TYPE0) {
// CID Font
font =
new PDFCIDFontDescriptor(++this.objectcount,
desc.fontName(),
desc.getFontBBox(),
//desc.getAscender(),
//desc.getDescender(),
desc.getCapHeight(),
desc.getFlags(),
//new PDFRectangle(desc.getFontBBox()),
desc.getItalicAngle(),
desc.getStemV(),
null); //desc.getLang(),
//null);//desc.getPanose());
} else {
// Create normal FontDescriptor
font =
new PDFFontDescriptor(++this.objectcount,
desc.fontName(),
desc.getAscender(),
desc.getDescender(),
desc.getCapHeight(),
desc.getFlags(),
new PDFRectangle(desc.getFontBBox()),
desc.getStemV(),
desc.getItalicAngle());
}
// Check if the font is embeddable
if (desc.isEmbeddable()) {
PDFStream stream=desc.getFontFile(this.objectcount+1);
if (stream!=null) {
this.objectcount++;
font.setFontFile(desc.getSubType(), stream);
this.objects.addElement(font);
this.objects.addElement(stream);
}
} else {
this.objects.addElement(font);
}
return font;
}
}


/**

+ 6
- 4
src/org/apache/fop/pdf/PDFFont.java View File

@@ -136,10 +136,9 @@ public class PDFFont extends PDFObject {
public static PDFFont createFont(int number, String fontname,
byte subtype, String basefont, Object encoding) {
switch (subtype) {
/*
case TYPE0 :
return new PDFFontType0(number, fontname, subtype, basefont, encoding);
*/
return new PDFFontType0(number, fontname, subtype,
basefont, encoding);
case TYPE1 :
case MMTYPE1 :
return new PDFFontType1(number, fontname, subtype, basefont, encoding);
@@ -175,7 +174,10 @@ public class PDFFont extends PDFObject {
PDFFontNonBase14 font;
switch (subtype) {
case TYPE0 :
return null; // should not happend
font = new PDFFontType0(number, fontname, subtype,
basefont, encoding);
font.setDescriptor(descriptor);
return font;
case TYPE1 :
case MMTYPE1 :
font = new PDFFontType1(number, fontname, subtype, basefont, encoding);

+ 4
- 1
src/org/apache/fop/pdf/PDFFontDescriptor.java View File

@@ -180,10 +180,13 @@ public class PDFFontDescriptor extends PDFObject {
p.append("\n/FontFile ");
break;
case PDFFont.TRUETYPE:
p.append("\n/FontFile2 ");
break;
case PDFFont.TYPE0:
p.append("\n/FontFile2 ");
break;
default:
p.append("\n/FontFile3 ");
p.append("\n/FontFile2 ");
}
p.append(fontfile.referencePDF());
}

+ 16
- 8
src/org/apache/fop/pdf/PDFFontType0.java View File

@@ -49,17 +49,18 @@

*/
package org.apache.fop.pdf;

/**
* class representing a Type0 font.
*
* Type0 fonts are specified on page 208 and onwards of the PDF 1.3 spec.
*/
public class PDFFontType0 extends PDFFont {
public class PDFFontType0 extends PDFFontNonBase14 {

/** this should be an array of CIDFont but only the first one is used */
protected PDFCIDFont descendantFonts;

protected PDFCMap cmap;
/**
* create the /Font object
*
@@ -78,6 +79,7 @@ public class PDFFontType0 extends PDFFont {

/* set fields using paramaters */
this.descendantFonts = null;
cmap=null;
}

/**
@@ -111,13 +113,19 @@ public class PDFFontType0 extends PDFFont {
this.descendantFonts = descendantFonts;
}

public void setCMAP(PDFCMap cmap) {
this.cmap=cmap;
}
/**
* fill in the specifics for the font's subtype
*/
protected void fillInPDF(StringBuffer p) {
if (descendantFonts != null) {
p.append("\n/DescendantFonts [ "+ this.descendantFonts.referencePDF() + " ] ");
}

}
protected void fillInPDF(StringBuffer p) {
if (descendantFonts != null) {
p.append("\n/DescendantFonts [ " +
this.descendantFonts.referencePDF() + " ] ");
}
if (cmap != null) {
p.append("\n/ToUnicode "+cmap.referencePDF());
}
}
}

+ 1
- 1
src/org/apache/fop/pdf/PDFWArray.java View File

@@ -132,7 +132,7 @@ public class PDFWArray {
metrics = m;
}
public void fillInPDF(StringBuffer p) {
p.setLength(0);
//p.setLength(0);
p.append(start); p.append(" [");
for (int i = 0; i < metrics.length; i++) {
p.append(this.metrics[i]);

+ 29
- 0
src/org/apache/fop/render/pdf/CIDFont.java View File

@@ -0,0 +1,29 @@
package org.apache.fop.render.pdf;

import org.apache.fop.pdf.PDFWArray;

public abstract class CIDFont extends Font {

// Required
public abstract String getCidBaseFont();
public abstract byte getCidType();
public abstract String getCharEncoding();
public abstract String getRegistry();
public abstract String getOrdering();
public abstract int getSupplement();
// Optional
public int getDefaultWidth() { return 0; }
public PDFWArray getWidths() { return null; }
// public int getWinCharSet() { return 0; }

// Need For FOP

/**
*Returns CMap Object .
*<p>
*If this method does not return null , the mapping from character codes
*to a font number is performed in FOP . When the getCidType() method
*returns CIDFontType2 , this method must not return null .
*/
public CMap getCMap() { return null; }
}

+ 55
- 0
src/org/apache/fop/render/pdf/CMap.java View File

@@ -0,0 +1,55 @@
/*-- $Id$ --

============================================================================
The Apache Software License, Version 1.1
============================================================================

Copyright (C) 1999 The Apache Software Foundation. All rights reserved.

Redistribution and use in source and binary forms, with or without modifica-
tion, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. The end-user documentation included with the redistribution, if any, must
include the following acknowledgment: "This product includes software
developed by the Apache Software Foundation (http://www.apache.org/)."
Alternately, this acknowledgment may appear in the software itself, if
and wherever such third-party acknowledgments normally appear.

4. The names "Fop" and "Apache Software Foundation" must not be used to
endorse or promote products derived from this software without prior
written permission. For written permission, please contact
apache@apache.org.

5. Products derived from this software may not be called "Apache", nor may
"Apache" appear in their name, without prior written permission of the
Apache Software Foundation.

THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This software consists of voluntary contributions made by many individuals
on behalf of the Apache Software Foundation and was originally created by
James Tauber <jtauber@jtauber.com>. For more information on the Apache
Software Foundation, please see <http://www.apache.org/>.

*/
package org.apache.fop.render.pdf;

public interface CMap {
public abstract char mapping(char ch);
}

+ 28
- 12
src/org/apache/fop/render/pdf/Font.java View File

@@ -58,22 +58,38 @@ import org.apache.fop.layout.FontMetric;
*/
public abstract class Font implements FontMetric {

/**
* get the encoding of the font
*/
/**
* get the encoding of the font
*/
public abstract String encoding();

/**
* get the base font name
*/
/**
* get the base font name
*/
public abstract String fontName();
/**
* get the subtype of the font, default is TYPE1
*/
public byte getSubType() {
return org.apache.fop.pdf.PDFFont.TYPE1;
}

/**
* get the subtype of the font, default is TYPE1
*/
public byte getSubType() {
return org.apache.fop.pdf.PDFFont.TYPE1;
}
/**
* Provide a default mapping
*/
public char mapChar(char c) {
// Use default CodePointMapping
if (c > 127) {
char d = org.apache.fop.render.pdf.CodePointMapping.map[c];
if (d != 0) {
c = d;
} else {
c = '#';
}
}
return c;
}
}



+ 334
- 0
src/org/apache/fop/render/pdf/FontReader.java View File

@@ -0,0 +1,334 @@
/*-- $Id$ --

============================================================================
The Apache Software License, Version 1.1
============================================================================
Copyright (C) 1999 The Apache Software Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without modifica-
tion, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The end-user documentation included with the redistribution, if any, must
include the following acknowledgment: "This product includes software
developed by the Apache Software Foundation (http://www.apache.org/)."
Alternately, this acknowledgment may appear in the software itself, if
and wherever such third-party acknowledgments normally appear.
4. The names "Fop" and "Apache Software Foundation" must not be used to
endorse or promote products derived from this software without prior
written permission. For written permission, please contact
apache@apache.org.
5. Products derived from this software may not be called "Apache", nor may
"Apache" appear in their name, without prior written permission of the
Apache Software Foundation.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This software consists of voluntary contributions made by many individuals
on behalf of the Apache Software Foundation and was originally created by
James Tauber <jtauber@jtauber.com>. For more information on the Apache
Software Foundation, please see <http://www.apache.org/>.
*/

package org.apache.fop.render.pdf;
import org.apache.fop.render.pdf.fonts.*;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.XMLReader;
import org.xml.sax.SAXException;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.Attributes;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
import java.util.Hashtable;
import org.apache.fop.pdf.PDFWArray;
import org.apache.fop.pdf.PDFCIDFont;
import org.apache.fop.configuration.ConfigurationReader;

/**
* Class for reading a metric.xml file and creating a font object.
* Typical usage:
<pre>
FontReader reader = new FontReader(<path til metrics.xml>);
reader.setFontEmbedPath(<path to a .ttf or .pfb file or null to diable embedding>);
reader.useKerning(true);
Font f = reader.getFont();
</pre>
*/
public class FontReader extends DefaultHandler {
private Locator locator = null;
private boolean isCID = false;
private MultiByteFont multiFont = null;
private SingleByteFont singleFont = null;
private Font returnFont = null;
//private SingleByteFont singleFont = null;
private String text = null;

private Vector cidWidths = null;
private int cidWidthIndex = 0;

private Hashtable currentKerning = null;

private Vector bfranges = null;
private void createFont(String path) throws IOException {
XMLReader parser = ConfigurationReader.createParser();
if (parser == null)
throw new IOException("Unable to create SAX parser");

try {
parser.setFeature("http://xml.org/sax/features/namespace-prefixes",
false);
} catch (SAXException e) {
throw new IOException ("You need a SAX parser which supports " +
"SAX version 2");
}

parser.setContentHandler(this);

try {
parser.parse(path);
} catch (SAXException e) {
throw new IOException(e.getMessage());
}
}

/**
* Sets the path to embed a font. a null value disables font embedding
*/
public void setFontEmbedPath(String path) {
if (isCID)
multiFont.embedFileName=path;
else
singleFont.embedFileName=path;
}
/**
* Enable/disable use of kerning for the font
*/
public void useKerning(boolean kern) {
if (isCID)
multiFont.useKerning = true;
else
singleFont.useKerning = true;
}
/**
* Get the generated font object
*/
public Font getFont() {
return returnFont;
}

/**
* Construct a FontReader object from a path to a metric.xml file
* and read metric data
*/
public FontReader(String path) throws IOException {
createFont(path);
}

public void startDocument() {
}

public void setDocumentLocator(Locator locator) {
this.locator = locator;
}

public void startElement(String uri, String localName,
String qName, Attributes attributes) {
if (localName.equals("font-metrics")) {
if ("TYPE0".equals(attributes.getValue("type"))) {
multiFont = new MultiByteFont();
returnFont = multiFont;
isCID = true;
} else if ("TRUETYPE".equals(attributes.getValue("type"))) {
singleFont = new SingleByteFont();
singleFont.subType = org.apache.fop.pdf.PDFFont.TRUETYPE;
returnFont = singleFont;
isCID = false;
} else {
singleFont = new SingleByteFont();
singleFont.subType = org.apache.fop.pdf.PDFFont.TYPE1;
returnFont = singleFont;
isCID = false;
}
} else if ("embed".equals(localName)) {
if (isCID) {
// This *is* annoying... should create a common
// interface for sing/multibytefonts...
multiFont.embedFileName = attributes.getValue("file");
multiFont.embedResourceName = attributes.getValue("class");
} else {
singleFont.embedFileName = attributes.getValue("file");
singleFont.embedResourceName = attributes.getValue("class");
}
} else if ("cid-widths".equals(localName)) {
cidWidthIndex = getInt(attributes.getValue("start-index"));
cidWidths = new Vector();
} else if ("kerning".equals(localName)) {
currentKerning = new Hashtable();
if (isCID)
multiFont.kerning.put(new Integer(attributes.getValue("kpx1")),
currentKerning);
else
singleFont.kerning.put(new Integer(attributes.getValue("kpx1")),
currentKerning);
} else if ("bfranges".equals(localName)) {
bfranges = new Vector();
} else if ("bf".equals(localName)) {
BFEntry entry = new BFEntry();
entry.unicodeStart = getInt(attributes.getValue("us"));
entry.unicodeEnd = getInt(attributes.getValue("ue"));
entry.glyphStartIndex = getInt(attributes.getValue("gi"));
bfranges.addElement(entry);
} else if ("wx".equals(localName)) {
cidWidths.addElement(new Integer(attributes.getValue("w")));
} else if ("widths".equals(localName)) {
singleFont.width = new int[256];
} else if ("char".equals(localName)) {
try {
singleFont.width[Integer.parseInt(attributes.getValue("idx"))] =
Integer.parseInt(attributes.getValue("wdt"));
} catch (NumberFormatException ne) {
System.out.println("Malformed width in metric file: " +
ne.getMessage());
}
} else if ("pair".equals(localName)) {
currentKerning.put(new Integer(attributes.getValue("kpx2")),
new Integer(attributes.getValue("kern")));
}
}

private int getInt(String str) {
int ret = 0;
try {
ret = Integer.parseInt(str);
} catch (Exception e) {}
return ret;
}
public void endElement(String uri, String localName, String qName) {
if ("font-name".equals(localName))
if (isCID)
multiFont.fontName = text;
else
singleFont.fontName = text;
else if ("cap-height".equals(localName))
if (isCID)
multiFont.capHeight = getInt(text);
else
singleFont.capHeight = getInt(text);
else if ("x-height".equals(localName))
if (isCID)
multiFont.xHeight = getInt(text);
else
singleFont.xHeight = getInt(text);
else if ("ascender".equals(localName))
if (isCID)
multiFont.ascender = getInt(text);
else
singleFont.ascender = getInt(text);
else if ("descender".equals(localName))
if (isCID)
multiFont.descender = getInt(text);
else
singleFont.descender = getInt(text);
else if ("left".equals(localName))
if (isCID)
multiFont.fontBBox[0] = getInt(text);
else
singleFont.fontBBox[0] = getInt(text);
else if ("bottom".equals(localName))
if (isCID)
multiFont.fontBBox[1] = getInt(text);
else
singleFont.fontBBox[1] = getInt(text);
else if ("right".equals(localName))
if (isCID)
multiFont.fontBBox[2] = getInt(text);
else
singleFont.fontBBox[2] = getInt(text);
else if ("first-char".equals(localName))
singleFont.firstChar = getInt(text);
else if ("last-char".equals(localName))
singleFont.lastChar = getInt(text);
else if ("top".equals(localName))
if (isCID)
multiFont.fontBBox[3] = getInt(text);
else
singleFont.fontBBox[3] = getInt(text);
else if ("flags".equals(localName))
if (isCID)
multiFont.flags = getInt(text);
else
singleFont.flags = getInt(text);
else if ("stemv".equals(localName))
if (isCID)
multiFont.stemV = getInt(text);
else
singleFont.stemV = getInt(text);
else if ("italic-angle".equals(localName))
if (isCID)
multiFont.italicAngle = getInt(text);
else
singleFont.italicAngle = getInt(text);
else if ("missing-width".equals(localName))
if (isCID)
multiFont.missingWidth = getInt(text);
else
singleFont.missingWidth = getInt(text);
else if ("cid-type".equals(localName)) {
if ("CIDFontType2".equals(text))
multiFont.cidType = PDFCIDFont.CID_TYPE2;
} else if ("default-width".equals(localName)) {
multiFont.defaultWidth = getInt(text);
} else if ("cid-widths".equals(localName)) {
int[] wds = new int[cidWidths.size()];
int j = 0;
for (Enumeration e = cidWidths.elements(); e.hasMoreElements();) {
Integer i = (Integer)e.nextElement();
wds[j++] = i.intValue();
}

multiFont.warray.addEntry(cidWidthIndex, wds);
multiFont.width = wds;
} else if ("bfranges".equals(localName)) {
BFEntry[] entries = new BFEntry[bfranges.size()];
bfranges.copyInto(entries);
multiFont.bfentries = entries;
}

}

public void characters(char[] ch, int start, int length) {
char c[] = new char[length];
System.arraycopy(ch, start, c, 0, length);
text = new String(c);
}
}



+ 50
- 2
src/org/apache/fop/render/pdf/FontSetup.java View File

@@ -57,10 +57,13 @@ import org.apache.fop.layout.FontInfo;
import org.apache.fop.layout.FontDescriptor;
import org.apache.fop.pdf.PDFDocument;
import org.apache.fop.pdf.PDFResources;
import org.apache.fop.configuration.Configuration;
import org.apache.fop.configuration.FontTriplet;

// Java
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

/**
* sets up the PDF fonts.
@@ -95,7 +98,7 @@ public class FontSetup {
fontInfo.addMetrics("F12", new CourierBoldOblique());
fontInfo.addMetrics("F13", new Symbol());
fontInfo.addMetrics("F14", new ZapfDingbats());
//Custom type 1 fonts step 1/2
// fontInfo.addMetrics("F15", new OMEP());
// fontInfo.addMetrics("F16", new GaramondLightCondensed());
@@ -209,8 +212,53 @@ public class FontSetup {
"bold");
fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter",
"normal", "normal");

/* Add configured fonts */
addConfiguredFonts(fontInfo, 15);
}

/**
* Add fonts from configuration file starting with
* internalnames F<num>
*/
public static void addConfiguredFonts(FontInfo fontInfo, int num) {

String internalName=null;
FontReader reader = null;

Vector fontInfos = Configuration.getFonts();
for (Enumeration e = fontInfos.elements(); e.hasMoreElements();) {
org.apache.fop.configuration.FontInfo configFontInfo =
(org.apache.fop.configuration.FontInfo)e.nextElement();
try {
String metricsFile = configFontInfo.getMetricsFile();
if (metricsFile != null) {
internalName = "F"+num;
num++;
reader = new FontReader(metricsFile);
reader.useKerning(configFontInfo.getKerning());
reader.setFontEmbedPath(configFontInfo.getEmbedFile());
fontInfo.addMetrics(internalName, reader.getFont());
Vector triplets = configFontInfo.getFontTriplets();
for (Enumeration t = triplets.elements(); t.hasMoreElements();) {
FontTriplet triplet = (FontTriplet)t.nextElement();
fontInfo.addFontProperties(internalName,
triplet.getName(),
triplet.getStyle(),
triplet.getWeight());
}
}
} catch (Exception ex) {
MessageHandler.error("Failed to read font metrics file " +
configFontInfo.getMetricsFile() +
" : " + ex.getMessage());
}
}
}
/**
* add the fonts in the font info to the PDF document
*
@@ -218,7 +266,7 @@ public class FontSetup {
* @param fontInfo font info object to get font information from
*/
public static void addToResources(PDFDocument doc, FontInfo fontInfo) {
Hashtable fonts = fontInfo.getFonts();
Hashtable fonts = fontInfo.getUsedFonts();
Enumeration e = fonts.keys();
PDFResources resources = doc.getResources();
while (e.hasMoreElements()) {

+ 90
- 38
src/org/apache/fop/render/pdf/PDFRenderer.java View File

@@ -147,6 +147,8 @@ public class PDFRenderer implements Renderer {
/** the current colour for use in svg */
private PDFColor currentColour = new PDFColor(0, 0, 0);

private FontInfo fontInfo;
// previous values used for text-decoration drawing
int prevUnderlineXEndPos;
int prevUnderlineYEndPos;
@@ -175,8 +177,6 @@ public class PDFRenderer implements Renderer {
/** The width of the previous word. Used to calculate space between */
int prevWordWidth = 0;

boolean useKerning;
private PDFOutline rootOutline;
/**
@@ -184,10 +184,6 @@ public class PDFRenderer implements Renderer {
*/
public PDFRenderer() {
this.pdfDoc = new PDFDocument();

String cfgKern = Configuration.getStringValue("use-kerning");
useKerning = ("yes".equals(cfgKern) || "true".equals(cfgKern));

}

/**
@@ -224,6 +220,8 @@ public class PDFRenderer implements Renderer {
}
renderRootExtensions(areaTree);
FontSetup.addToResources(this.pdfDoc, fontInfo);
MessageHandler.logln("writing out PDF");
this.pdfDoc.output(stream);
}
@@ -654,16 +652,23 @@ public class PDFRenderer implements Renderer {
Hashtable kerning = null;
boolean kerningAvailable = false;
if (useKerning) {
kerning = area.getFontState().getKerning();
if (kerning != null && !kerning.isEmpty()) {
kerningAvailable = true;
}
}
kerning = area.getFontState().getKerning();
if (kerning != null && !kerning.isEmpty()) {
kerningAvailable = true;
}

String name = area.getFontState().getFontName();
int size = area.getFontState().getFontSize();

// This assumes that *all* CIDFonts use a /ToUnicode mapping
boolean useMultiByte = false;
Font f = (Font)area.getFontState().getFontInfo().getFonts().get(name);
if (f instanceof CIDFont)
useMultiByte=true;
//String startText = useMultiByte ? "<FEFF" : "(";
String startText = useMultiByte ? "<" : "(";
String endText = useMultiByte ? ">" : ")";
PDFColor theAreaColor = new PDFColor((double) area.getRed(),
(double) area.getGreen(),
(double) area.getBlue());
@@ -726,7 +731,7 @@ public class PDFRenderer implements Renderer {
closeText();
pdf.append("1 0 0 1 " +(rx / 1000f) + " " +
(bl / 1000f) + " Tm [(");
(bl / 1000f) + " Tm [" + startText);
prevWordY = bl;
textOpen = true;
}
@@ -734,7 +739,7 @@ public class PDFRenderer implements Renderer {
// express the space between words in thousandths of an em
int space = prevWordX - rx + prevWordWidth;
float emDiff = (float)space / (float)currentFontSize * 1000f;
pdf.append(emDiff + " (");
pdf.append(emDiff + " " + startText);
}
prevWordWidth = area.getContentWidth();
prevWordX = rx;
@@ -745,10 +750,10 @@ public class PDFRenderer implements Renderer {
// for every word.
pdf.append("1 0 0 1 " +(rx / 1000f) + " " + (bl / 1000f) + " Tm ");
if (kerningAvailable) {
pdf.append(" [(");
pdf.append(" [" + startText);
}
else {
pdf.append(" (");
pdf.append(" " + startText);
}
}
@@ -768,27 +773,33 @@ public class PDFRenderer implements Renderer {
char ch = s.charAt(i);
String prepend = "";
if (ch > 127) {
pdf.append("\\");
pdf.append(Integer.toOctalString((int) ch));
} else {
switch (ch) {
case '(':
case ')':
case '\\':
prepend = "\\";
break;
if (!useMultiByte) {
if(ch > 127) {
pdf.append("\\");
pdf.append(Integer.toOctalString((int) ch));
} else {
switch (ch) {
case '(':
case ')':
case '\\':
prepend = "\\";
break;
}
pdf.append(getUnicodeString(prepend+ch, useMultiByte));
}
pdf.append(prepend+ch);
}
} else {
pdf.append(getUnicodeString(prepend+ch, useMultiByte));
}

if (kerningAvailable && (i+1) < l) {
pdf.append(addKerning((new Character(ch)).toString(),
(new Character(s.charAt(i+1))).toString(),
kerning));
}
pdf.append(addKerning((new Integer((int)ch)),
(new Integer((int)s.charAt(i+1))),
kerning,
startText, endText));
}
}
pdf.append(") ");
pdf.append(endText + " ");
if (!OPTIMIZE_TEXT) {
if (kerningAvailable) {
pdf.append("] TJ\n");
@@ -807,6 +818,45 @@ public class PDFRenderer implements Renderer {
}


/**
* Convert a string to a unicode hex representation
*/
private String getUnicodeString(StringBuffer str, boolean useMultiByte) {
return getUnicodeString(str.toString(), useMultiByte);
}
/**
* Convert a string to a multibyte hex representation
*/
private String getUnicodeString(String str, boolean useMultiByte) {
if (!useMultiByte) {
return str;
} else {
StringBuffer buf = new StringBuffer(str.length()*4);
byte[] uniBytes = null;
try {
uniBytes = str.getBytes("UnicodeBigUnmarked");
} catch (Exception e) {
// This should never fail
}
for (int i = 0; i < uniBytes.length; i++) {
int b = (uniBytes[i] < 0) ? (int)(256+uniBytes[i])
: (int)uniBytes[i];
String hexString=Integer.toHexString(b);
if (hexString.length()==1)
buf=buf.append("0"+hexString);
else
buf=buf.append(hexString);
}

return buf.toString();
}
}
/** Checks to see if we have some text rendering commands open
* still and writes out the TJ command to the stream if we do
*/
@@ -886,7 +936,9 @@ public class PDFRenderer implements Renderer {
}


private StringBuffer addKerning(String ch1, String ch2, Hashtable kerning) {
private StringBuffer addKerning(Integer ch1, Integer ch2,
Hashtable kerning, String startText,
String endText) {
Hashtable h2=(Hashtable)kerning.get(ch1);
int pwdt=0;
StringBuffer buf=new StringBuffer("");
@@ -895,7 +947,7 @@ public class PDFRenderer implements Renderer {
Integer wdt=(Integer)h2.get(ch2);
if (wdt!=null) {
pwdt=-wdt.intValue();
buf=buf.append(") " + pwdt + " (");
buf=buf.append(endText + " " + pwdt + " " + startText);
}
}
return buf;
@@ -1021,8 +1073,8 @@ public class PDFRenderer implements Renderer {
* @param fontInfo font info to set up
*/
public void setupFontInfo(FontInfo fontInfo) {
this.fontInfo = fontInfo;
FontSetup.setup(fontInfo);
FontSetup.addToResources(this.pdfDoc, fontInfo);
}

/**

+ 73
- 0
src/org/apache/fop/render/pdf/fonts/BFEntry.java View File

@@ -0,0 +1,73 @@
/*-- $Id$ --

============================================================================
The Apache Software License, Version 1.1
============================================================================
Copyright (C) 1999 The Apache Software Foundation. All rights reserved.
Redistribution and use in source and binary forms, with or without modifica-
tion, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The end-user documentation included with the redistribution, if any, must
include the following acknowledgment: "This product includes software
developed by the Apache Software Foundation (http://www.apache.org/)."
Alternately, this acknowledgment may appear in the software itself, if
and wherever such third-party acknowledgments normally appear.
4. The names "Fop" and "Apache Software Foundation" must not be used to
endorse or promote products derived from this software without prior
written permission. For written permission, please contact
apache@apache.org.
5. Products derived from this software may not be called "Apache", nor may
"Apache" appear in their name, without prior written permission of the
Apache Software Foundation.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This software consists of voluntary contributions made by many individuals
on behalf of the Apache Software Foundation and was originally created by
James Tauber <jtauber@jtauber.com>. For more information on the Apache
Software Foundation, please see <http://www.apache.org/>.
*/

package org.apache.fop.render.pdf.fonts;

/**
* This is just a holder class for bfentries - not get/put methods provided
*/
public class BFEntry {
public int unicodeStart;
public int unicodeEnd;
public int glyphStartIndex;
public BFEntry() {
}

public BFEntry (int unicodeStart,
int unicodeEnd,
int glyphStartIndex) {
this.unicodeStart = unicodeStart;
this.unicodeEnd = unicodeEnd;
this.glyphStartIndex = glyphStartIndex;
}
}

+ 236
- 0
src/org/apache/fop/render/pdf/fonts/MultiByteFont.java View File

@@ -0,0 +1,236 @@


package org.apache.fop.render.pdf.fonts;

import org.apache.fop.render.pdf.Font;
import org.apache.fop.layout.FontDescriptor;
import org.apache.fop.fonts.Glyphs;
import org.apache.fop.pdf.PDFStream;
import org.apache.fop.pdf.PDFWArray;
import org.apache.fop.pdf.PDFCIDFont;
import org.apache.fop.render.pdf.CIDFont;
import org.apache.fop.render.pdf.CMap;
import org.apache.fop.pdf.PDFTTFStream;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.File;
import java.io.BufferedInputStream;
import java.util.Hashtable;

/**
* Generic MultiByte (CID) font
*/
public class MultiByteFont extends CIDFont implements FontDescriptor {
public String fontName = null;
public String encoding = "Identity-H";
public int capHeight = 0;
public int xHeight = 0;
public int ascender = 0;
public int descender = 0;
public int[] fontBBox = {0, 0, 0, 0};
public String embedFileName = null;
public String embedResourceName = null;
public PDFTTFStream embeddedFont=null;
public int flags = 4;
public int stemV = 0;
public int italicAngle = 0;
public int missingWidth = 0;
public int defaultWidth = 0;
public byte cidType = PDFCIDFont.CID_TYPE2;
public Hashtable kerning=new Hashtable();
public boolean useKerning = true;
public PDFWArray warray=new PDFWArray();
public int width[] = null;

public BFEntry[] bfentries = null;

public MultiByteFont() {}
public final boolean hasKerningInfo() {
return (useKerning & kerning.isEmpty());
}
public final java.util.Hashtable getKerningInfo() {return kerning;}

public byte getSubType() {
return org.apache.fop.pdf.PDFFont.TYPE0;
}

public String getLang() {return null;}
public String getPanose() {return null;}
public int getAvgWidth() {return -1;}
public int getMinWidth() {return -1;}
public int getMaxWidth() {return -1;}
public int getleading() {return -1;}
public int getStemH() {return 0;}
public int getMissingWidth() {return missingWidth;}
public int getDefaultWidth() {return defaultWidth;}
public String getRegistry() {return "Adobe";}
public String getOrdering() {return "UCS";}
public int getSupplement() {return 0;}
public byte getCidType() {return cidType;}
public String getCidBaseFont() {return fontName;}
public String getCharEncoding() {return "Identity-H";}

public PDFWArray getWidths() {
return warray;
}

public boolean isEmbeddable() {
return (embedFileName==null && embedResourceName==null) ? false : true;
}

public PDFStream getFontFile(int i) {
InputStream instream=null;

int iniSize = 256000;
int incSize = 128000;
// Get file first
if (embedFileName!=null)
try {
File ef = new File(embedFileName);
iniSize = (int)ef.length()+1;
incSize = (int)ef.length()/10;
instream=new FileInputStream(embedFileName);
} catch (Exception e) {
System.out.println("Failed to embed fontfile: "+embedFileName);
}
// Get resource
if (instream==null && embedResourceName!=null)
try {
instream=new BufferedInputStream(this.getClass().getResourceAsStream(embedResourceName));
} catch (Exception e) {
System.out.println("Failed to embed fontresource: "+embedResourceName);
}
if (instream==null)
return (PDFStream)null;
// Read fontdata
byte[] file = new byte[iniSize];
int fsize = 0;

try {
int l = instream.read(file, 0, iniSize);
fsize += l;
if (l==iniSize) {
// More to read - needs to extend
byte[] tmpbuf;
while (l > 0) {
tmpbuf = new byte[file.length + incSize];
System.arraycopy(file, 0, tmpbuf, 0, file.length);
l=instream.read(tmpbuf, file.length, incSize);
fsize += l;
file = tmpbuf;
if (l < incSize) // whole file read. No need to loop again
l=0;
}
}

// Only TrueType CID fonts are supported now
embeddedFont=new PDFTTFStream(i, fsize);
embeddedFont.addFilter("flate");
embeddedFont.addFilter("ascii-85");
embeddedFont.setData(file, fsize);
instream.close();
} catch (Exception e) {}

return (PDFStream) embeddedFont;
}
public String encoding() {
return encoding;
}
public String fontName() {
return fontName;
}

public int getAscender() {return ascender;}
public int getDescender() {return descender;}
public int getCapHeight() {return capHeight;}

public int getAscender(int size) {
return size * ascender;
}

public int getCapHeight(int size) {
return size * capHeight;
}

public int getDescender(int size) {
return size * descender;
}

public int getXHeight(int size) {
return size * xHeight;
}

public int getFlags() {
return flags;
}

public int[] getFontBBox() {
return fontBBox;
}

public int getItalicAngle() {
return italicAngle;
}

public int getStemV() {
return stemV;
}

public int getFirstChar() {
return 0;
}

public int getLastChar() {
return 255;
}

public int width(int i, int size) {
return size * width[i];
}

public int[] getWidths(int size) {
int[] arr = new int[width.length];
System.arraycopy(width, 0, arr, 0, width.length-1);
for( int i = 0; i < arr.length; i++) arr[i] *= size;
return arr;
}

public char mapChar(char c) {
int idx = (int)c;
int retIdx = 0;

for (int i = 0; (i < bfentries.length) && retIdx == 0; i++) {

/*
System.out.println("us: "+bfentries[i].unicodeStart +
" ue: "+bfentries[i].unicodeEnd+
" gi: "+bfentries[i].glyphStartIndex);
*/
if (bfentries[i].unicodeStart <= idx &&
bfentries[i].unicodeEnd >= idx) {
retIdx=bfentries[i].glyphStartIndex + idx -
bfentries[i].unicodeStart;
}
}

//System.out.println("Map: "+ c + " (" + idx + ") = " + retIdx);
return (char)retIdx;
}
}


+ 196
- 0
src/org/apache/fop/render/pdf/fonts/SingleByteFont.java View File

@@ -0,0 +1,196 @@


package org.apache.fop.render.pdf.fonts;

import org.apache.fop.render.pdf.Font;
import org.apache.fop.layout.FontDescriptor;
import org.apache.fop.fonts.Glyphs;
import org.apache.fop.pdf.PDFStream;
import org.apache.fop.pdf.PDFTTFStream;
import org.apache.fop.pdf.PDFT1Stream;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.util.Hashtable;

/**
* Generic SingleByte font
*/
public class SingleByteFont extends Font implements FontDescriptor {
public String fontName = null;
public String encoding = "WinAnsiEncoding";
public int capHeight = 0;
public int xHeight = 0;
public int ascender = 0;
public int descender = 0;
public int[] fontBBox = {0, 0, 0, 0};
public String embedFileName = null;
public String embedResourceName = null;
public PDFStream embeddedFont=null;
public int firstChar = 0;
public int lastChar = 255;
public int flags = 4;
public int stemV = 0;
public int italicAngle = 0;
public int missingWidth = 0;
public Hashtable kerning=new Hashtable();
public boolean useKerning = true;
public int width[] = null;
public byte subType = 0;
public final boolean hasKerningInfo() {
return (useKerning & kerning.isEmpty());
}
public final java.util.Hashtable getKerningInfo() {return kerning;}

public byte getSubType() {
return subType;
}

public int getAvgWidth() {return -1;}
public int getMinWidth() {return -1;}
public int getMaxWidth() {return -1;}
public int getleading() {return -1;}
public int getStemH() {return 0;}
public int getMissingWidth() {return missingWidth;}

public String getCharEncoding() {return encoding;}

public boolean isEmbeddable() {
return (embedFileName==null && embedResourceName==null) ? false : true;
}

public PDFStream getFontFile(int i) {
InputStream instream=null;
// Get file first
if (embedFileName!=null)
try {
instream=new FileInputStream(embedFileName);
} catch (Exception e) {
System.out.println("Failed to embed fontfile: "+embedFileName);
}
// Get resource
if (instream==null && embedResourceName!=null)
try {
instream=new BufferedInputStream(this.getClass().getResourceAsStream(embedResourceName));
} catch (Exception e) {
System.out.println("Failed to embed fontresource: "+embedResourceName);
}
if (instream==null)
return (PDFStream)null;
// Read fontdata
byte[] file = new byte[128000];
int fsize = 0;

try {
int l = instream.read(file, 0, 128000);
fsize += l;
if (l==128000) {
// More to read - needs to extend
byte[] tmpbuf;
while (l > 0) {
tmpbuf = new byte[file.length + 64000];
System.arraycopy(file, 0, tmpbuf, 0, file.length);
l=instream.read(tmpbuf, file.length, 64000);
fsize += l;
file = tmpbuf;
if (l < 64000) // whole file read. No need to loop again
l=0;
}
}

if (subType == org.apache.fop.pdf.PDFFont.TYPE1) {
embeddedFont=new PDFT1Stream(i, fsize);
((PDFT1Stream)embeddedFont).setData(file, fsize);
} else {
embeddedFont=new PDFTTFStream(i, fsize);
((PDFTTFStream)embeddedFont).setData(file, fsize);
}
embeddedFont.addFilter("flate");
embeddedFont.addFilter("ascii-85");
instream.close();
} catch (Exception e) {}

return (PDFStream) embeddedFont;
}
public String encoding() {
return encoding;
}
public String fontName() {
return fontName;
}

public int getAscender() {return ascender;}
public int getDescender() {return descender;}
public int getCapHeight() {return capHeight;}

public int getAscender(int size) {
return size * ascender;
}

public int getCapHeight(int size) {
return size * capHeight;
}

public int getDescender(int size) {
return size * descender;
}

public int getXHeight(int size) {
return size * xHeight;
}

public int getFlags() {
return flags;
}

public int[] getFontBBox() {
return fontBBox;
}

public int getItalicAngle() {
return italicAngle;
}

public int getStemV() {
return stemV;
}

public int getFirstChar() {
return 0;
//return firstChar;
}

public int getLastChar() {
return lastChar;
}

public int width(int i, int size) {
return size * width[i];
}

public int[] getWidths(int size) {
int[] arr = new int[width.length];
System.arraycopy(width, 0, arr, 0, width.length-1);
for( int i = 0; i < arr.length; i++) arr[i] *= size;
return arr;
}
}


Loading…
Cancel
Save