Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

FontReader.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*-- $Id$ --
  2. *
  3. * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
  4. * For details on use and redistribution please refer to the
  5. * LICENSE file included with these sources."
  6. */
  7. package org.apache.fop.render.pdf;
  8. import org.apache.fop.render.pdf.fonts.*;
  9. import org.xml.sax.helpers.DefaultHandler;
  10. import org.xml.sax.XMLReader;
  11. import org.xml.sax.SAXException;
  12. import org.xml.sax.InputSource;
  13. import org.xml.sax.Locator;
  14. import org.xml.sax.Attributes;
  15. import java.io.IOException;
  16. import java.util.Enumeration;
  17. import java.util.Vector;
  18. import java.util.Hashtable;
  19. import org.apache.fop.pdf.PDFWArray;
  20. import org.apache.fop.pdf.PDFCIDFont;
  21. import org.apache.fop.configuration.ConfigurationReader;
  22. import org.apache.fop.apps.FOPException;
  23. /**
  24. * Class for reading a metric.xml file and creating a font object.
  25. * Typical usage:
  26. <pre>
  27. FontReader reader = new FontReader(<path til metrics.xml>);
  28. reader.setFontEmbedPath(<path to a .ttf or .pfb file or null to diable embedding>);
  29. reader.useKerning(true);
  30. Font f = reader.getFont();
  31. </pre>
  32. */
  33. public class FontReader extends DefaultHandler {
  34. private Locator locator = null;
  35. private boolean isCID = false;
  36. private MultiByteFont multiFont = null;
  37. private SingleByteFont singleFont = null;
  38. private Font returnFont = null;
  39. //private SingleByteFont singleFont = null;
  40. private String text = null;
  41. private Vector cidWidths = null;
  42. private int cidWidthIndex = 0;
  43. private Hashtable currentKerning = null;
  44. private Vector bfranges = null;
  45. private void createFont(String path) throws FOPException {
  46. XMLReader parser = ConfigurationReader.createParser();
  47. if (parser == null)
  48. throw new FOPException("Unable to create SAX parser");
  49. try {
  50. parser.setFeature("http://xml.org/sax/features/namespace-prefixes",
  51. false);
  52. } catch (SAXException e) {
  53. throw new FOPException (
  54. "You need a SAX parser which supports SAX version 2",e);
  55. }
  56. parser.setContentHandler(this);
  57. try {
  58. parser.parse(path);
  59. } catch (SAXException e) {
  60. throw new FOPException(e);
  61. }
  62. catch (IOException e) {
  63. throw new FOPException(e);
  64. }
  65. }
  66. /**
  67. * Sets the path to embed a font. a null value disables font embedding
  68. */
  69. public void setFontEmbedPath(String path) {
  70. if (isCID)
  71. multiFont.embedFileName = path;
  72. else
  73. singleFont.embedFileName = path;
  74. }
  75. /**
  76. * Enable/disable use of kerning for the font
  77. */
  78. public void useKerning(boolean kern) {
  79. if (isCID)
  80. multiFont.useKerning = true;
  81. else
  82. singleFont.useKerning = true;
  83. }
  84. /**
  85. * Get the generated font object
  86. */
  87. public Font getFont() {
  88. return returnFont;
  89. }
  90. /**
  91. * Construct a FontReader object from a path to a metric.xml file
  92. * and read metric data
  93. */
  94. public FontReader(String path) throws FOPException {
  95. createFont(path);
  96. }
  97. public void startDocument() {
  98. }
  99. public void setDocumentLocator(Locator locator) {
  100. this.locator = locator;
  101. }
  102. public void startElement(String uri, String localName,
  103. String qName, Attributes attributes) {
  104. if (localName.equals("font-metrics")) {
  105. if ("TYPE0".equals(attributes.getValue("type"))) {
  106. multiFont = new MultiByteFont();
  107. returnFont = multiFont;
  108. isCID = true;
  109. } else if ("TRUETYPE".equals(attributes.getValue("type"))) {
  110. singleFont = new SingleByteFont();
  111. singleFont.subType = org.apache.fop.pdf.PDFFont.TRUETYPE;
  112. returnFont = singleFont;
  113. isCID = false;
  114. } else {
  115. singleFont = new SingleByteFont();
  116. singleFont.subType = org.apache.fop.pdf.PDFFont.TYPE1;
  117. returnFont = singleFont;
  118. isCID = false;
  119. }
  120. } else if ("embed".equals(localName)) {
  121. if (isCID) {
  122. // This *is* annoying... should create a common
  123. // interface for sing/multibytefonts...
  124. multiFont.embedFileName = attributes.getValue("file");
  125. multiFont.embedResourceName = attributes.getValue("class");
  126. } else {
  127. singleFont.embedFileName = attributes.getValue("file");
  128. singleFont.embedResourceName = attributes.getValue("class");
  129. }
  130. } else if ("cid-widths".equals(localName)) {
  131. cidWidthIndex = getInt(attributes.getValue("start-index"));
  132. cidWidths = new Vector();
  133. } else if ("kerning".equals(localName)) {
  134. currentKerning = new Hashtable();
  135. if (isCID)
  136. multiFont.kerning.put(
  137. new Integer(attributes.getValue("kpx1")),
  138. currentKerning);
  139. else
  140. singleFont.kerning.put(
  141. new Integer(attributes.getValue("kpx1")),
  142. currentKerning);
  143. } else if ("bfranges".equals(localName)) {
  144. bfranges = new Vector();
  145. } else if ("bf".equals(localName)) {
  146. BFEntry entry = new BFEntry();
  147. entry.unicodeStart = getInt(attributes.getValue("us"));
  148. entry.unicodeEnd = getInt(attributes.getValue("ue"));
  149. entry.glyphStartIndex = getInt(attributes.getValue("gi"));
  150. bfranges.addElement(entry);
  151. } else if ("wx".equals(localName)) {
  152. cidWidths.addElement(new Integer(attributes.getValue("w")));
  153. } else if ("widths".equals(localName)) {
  154. singleFont.width = new int[256];
  155. } else if ("char".equals(localName)) {
  156. try {
  157. singleFont.width[
  158. Integer.parseInt(attributes.getValue("idx"))] =
  159. Integer.parseInt(attributes.getValue("wdt"));
  160. } catch (NumberFormatException ne) {
  161. System.out.println("Malformed width in metric file: " +
  162. ne.getMessage());
  163. }
  164. } else if ("pair".equals(localName)) {
  165. currentKerning.put( new Integer(attributes.getValue("kpx2")),
  166. new Integer(attributes.getValue("kern")));
  167. }
  168. }
  169. private int getInt(String str) {
  170. int ret = 0;
  171. try {
  172. ret = Integer.parseInt(str);
  173. } catch (Exception e) {}
  174. return ret;
  175. }
  176. public void endElement(String uri, String localName, String qName) {
  177. if ("font-name".equals(localName))
  178. if (isCID)
  179. multiFont.fontName = text;
  180. else
  181. singleFont.fontName = text;
  182. if ("ttc-name".equals(localName) && isCID)
  183. multiFont.ttcName = text;
  184. else if ("cap-height".equals(localName))
  185. if (isCID)
  186. multiFont.capHeight = getInt(text);
  187. else
  188. singleFont.capHeight = getInt(text);
  189. else if ("x-height".equals(localName))
  190. if (isCID)
  191. multiFont.xHeight = getInt(text);
  192. else
  193. singleFont.xHeight = getInt(text);
  194. else if ("ascender".equals(localName))
  195. if (isCID)
  196. multiFont.ascender = getInt(text);
  197. else
  198. singleFont.ascender = getInt(text);
  199. else if ("descender".equals(localName))
  200. if (isCID)
  201. multiFont.descender = getInt(text);
  202. else
  203. singleFont.descender = getInt(text);
  204. else if ("left".equals(localName))
  205. if (isCID)
  206. multiFont.fontBBox[0] = getInt(text);
  207. else
  208. singleFont.fontBBox[0] = getInt(text);
  209. else if ("bottom".equals(localName))
  210. if (isCID)
  211. multiFont.fontBBox[1] = getInt(text);
  212. else
  213. singleFont.fontBBox[1] = getInt(text);
  214. else if ("right".equals(localName))
  215. if (isCID)
  216. multiFont.fontBBox[2] = getInt(text);
  217. else
  218. singleFont.fontBBox[2] = getInt(text);
  219. else if ("first-char".equals(localName))
  220. singleFont.firstChar = getInt(text);
  221. else if ("last-char".equals(localName))
  222. singleFont.lastChar = getInt(text);
  223. else if ("top".equals(localName))
  224. if (isCID)
  225. multiFont.fontBBox[3] = getInt(text);
  226. else
  227. singleFont.fontBBox[3] = getInt(text);
  228. else if ("flags".equals(localName))
  229. if (isCID)
  230. multiFont.flags = getInt(text);
  231. else
  232. singleFont.flags = getInt(text);
  233. else if ("stemv".equals(localName))
  234. if (isCID)
  235. multiFont.stemV = getInt(text);
  236. else
  237. singleFont.stemV = getInt(text);
  238. else if ("italic-angle".equals(localName))
  239. if (isCID)
  240. multiFont.italicAngle = getInt(text);
  241. else
  242. singleFont.italicAngle = getInt(text);
  243. else if ("missing-width".equals(localName))
  244. if (isCID)
  245. multiFont.missingWidth = getInt(text);
  246. else
  247. singleFont.missingWidth = getInt(text);
  248. else if ("cid-type".equals(localName)) {
  249. if ("CIDFontType2".equals(text))
  250. multiFont.cidType = PDFCIDFont.CID_TYPE2;
  251. } else if ("default-width".equals(localName)) {
  252. multiFont.defaultWidth = getInt(text);
  253. } else if ("cid-widths".equals(localName)) {
  254. int[] wds = new int[cidWidths.size()];
  255. int j = 0;
  256. for (Enumeration e = cidWidths.elements();
  257. e.hasMoreElements();) {
  258. Integer i = (Integer) e.nextElement();
  259. wds[j++] = i.intValue();
  260. }
  261. multiFont.warray.addEntry(cidWidthIndex, wds);
  262. multiFont.width = wds;
  263. } else if ("bfranges".equals(localName)) {
  264. BFEntry[] entries = new BFEntry[bfranges.size()];
  265. bfranges.copyInto(entries);
  266. multiFont.bfentries = entries;
  267. }
  268. }
  269. public void characters(char[] ch, int start, int length) {
  270. char c[] = new char[length];
  271. System.arraycopy(ch, start, c, 0, length);
  272. text = new String(c);
  273. }
  274. }