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-ffa450edef68tags/fop-0_18_1
@@ -50,4 +50,6 @@ | |||
<!-- <value>ascii-hex</value> --> | |||
</list> | |||
</entry> | |||
<fonts> | |||
</fonts> | |||
</configuration> |
@@ -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> | |||
@@ -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 |
@@ -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") ) { | |||
} | |||
} | |||
@@ -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"; |
@@ -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; | |||
} | |||
} | |||
@@ -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; | |||
} | |||
} | |||
@@ -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", |
@@ -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); | |||
} | |||
} | |||
@@ -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; | |||
} | |||
} |
@@ -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"); | |||
} | |||
} |
@@ -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)); | |||
} | |||
} |
@@ -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(); | |||
} | |||
} | |||
@@ -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(); | |||
@@ -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)); | |||
} | |||
} |
@@ -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; | |||
} | |||
} | |||
@@ -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++; |
@@ -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(); | |||
} | |||
} | |||
@@ -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); | |||
} |
@@ -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()); | |||
} | |||
} | |||
*/ | |||
} | |||
} |
@@ -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; | |||
} | |||
} | |||
/** |
@@ -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); |
@@ -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()); | |||
} |
@@ -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()); | |||
} | |||
} | |||
} |
@@ -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]); |
@@ -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; } | |||
} |
@@ -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); | |||
} |
@@ -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; | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
@@ -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()) { |
@@ -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); | |||
} | |||
/** |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} | |||
@@ -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; | |||
} | |||
} | |||