Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

XMLFontMetricsReader.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.fonts;
  19. //Java
  20. import java.io.IOException;
  21. import java.net.URI;
  22. import java.net.URISyntaxException;
  23. import java.util.ArrayList;
  24. import java.util.HashMap;
  25. import java.util.HashSet;
  26. import java.util.List;
  27. import java.util.Map;
  28. import java.util.Set;
  29. import javax.xml.parsers.SAXParserFactory;
  30. import org.xml.sax.Attributes;
  31. import org.xml.sax.InputSource;
  32. import org.xml.sax.SAXException;
  33. import org.xml.sax.XMLReader;
  34. import org.xml.sax.helpers.DefaultHandler;
  35. import org.apache.fop.apps.FOPException;
  36. import org.apache.fop.apps.io.InternalResourceResolver;
  37. import org.apache.fop.fonts.apps.TTFReader;
  38. /**
  39. * <p>Class for reading a metric.xml file and creating a font object.
  40. * Typical usage:</p>
  41. * <pre>
  42. * XMLFontMetricsReader reader = new XMLFontMetricsReader(&lt;path til metrics.xml&gt;);
  43. * reader.setFontEmbedPath(&lt;path to a .ttf or .pfb file or null to diable embedding&gt;);
  44. * reader.useKerning(true);
  45. * Font f = reader.getFont();
  46. * </pre>
  47. * <p><strong>N.B. This is deprecated functionality and is expected to be
  48. * removed from a future version of FOP. New applications using FOP should
  49. * not make direct or implied use of this mechanism.</strong></p>
  50. */
  51. @Deprecated
  52. public class XMLFontMetricsReader extends DefaultHandler {
  53. private boolean isCID;
  54. private CustomFont returnFont;
  55. private MultiByteFont multiFont;
  56. private SingleByteFont singleFont;
  57. private final InternalResourceResolver resourceResolver;
  58. private StringBuffer text = new StringBuffer();
  59. private List<Integer> cidWidths;
  60. //private int cidWidthIndex;
  61. private Map<Integer, Integer> currentKerning;
  62. private List<CMapSegment> bfranges;
  63. /**
  64. * Construct a XMLFontMetricsReader object from a path to a metric.xml file
  65. * and read metric data
  66. * @param source Source of the font metric file
  67. * @throws FOPException if loading the font fails
  68. */
  69. public XMLFontMetricsReader(InputSource source, InternalResourceResolver resourceResolver) throws FOPException {
  70. this.resourceResolver = resourceResolver;
  71. createFont(source);
  72. }
  73. private void createFont(InputSource source) throws FOPException {
  74. XMLReader parser = null;
  75. try {
  76. final SAXParserFactory factory = javax.xml.parsers.SAXParserFactory.newInstance();
  77. factory.setNamespaceAware(true);
  78. parser = factory.newSAXParser().getXMLReader();
  79. } catch (Exception e) {
  80. throw new FOPException(e);
  81. }
  82. if (parser == null) {
  83. throw new FOPException("Unable to create SAX parser");
  84. }
  85. try {
  86. parser.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
  87. } catch (SAXException e) {
  88. throw new FOPException("You need a SAX parser which supports SAX version 2", e);
  89. }
  90. parser.setContentHandler(this);
  91. try {
  92. parser.parse(source);
  93. } catch (SAXException e) {
  94. throw new FOPException(e);
  95. } catch (IOException e) {
  96. throw new FOPException(e);
  97. }
  98. }
  99. /**
  100. * Sets the path to embed a font. A null value disables font embedding.
  101. * @param path URI for the embeddable file
  102. */
  103. public void setFontEmbedURI(URI path) {
  104. returnFont.setEmbedURI(path);
  105. }
  106. /**
  107. * Enable/disable use of kerning for the font
  108. * @param enabled true to enable kerning, false to disable
  109. */
  110. public void setKerningEnabled(boolean enabled) {
  111. returnFont.setKerningEnabled(enabled);
  112. }
  113. /**
  114. * Enable/disable use of advanced typographic features for the font
  115. * @param enabled true to enable, false to disable
  116. */
  117. public void setAdvancedEnabled(boolean enabled) {
  118. returnFont.setAdvancedEnabled(enabled);
  119. }
  120. /**
  121. * Get the generated font object
  122. * @return the font
  123. */
  124. public Typeface getFont() {
  125. return returnFont;
  126. }
  127. /**
  128. * {@inheritDoc}
  129. */
  130. @Override
  131. public void startDocument() {
  132. }
  133. /**
  134. * {@inheritDoc}
  135. */
  136. public void startElement(String uri, String localName, String qName, Attributes attributes)
  137. throws SAXException {
  138. if (localName.equals("font-metrics")) {
  139. if ("TYPE0".equals(attributes.getValue("type"))) {
  140. multiFont = new MultiByteFont(resourceResolver, EmbeddingMode.AUTO);
  141. returnFont = multiFont;
  142. isCID = true;
  143. TTFReader.checkMetricsVersion(attributes);
  144. } else if ("TRUETYPE".equals(attributes.getValue("type"))) {
  145. singleFont = new SingleByteFont(resourceResolver, EmbeddingMode.AUTO);
  146. singleFont.setFontType(FontType.TRUETYPE);
  147. returnFont = singleFont;
  148. isCID = false;
  149. TTFReader.checkMetricsVersion(attributes);
  150. } else {
  151. singleFont = new SingleByteFont(resourceResolver, EmbeddingMode.AUTO);
  152. singleFont.setFontType(FontType.TYPE1);
  153. returnFont = singleFont;
  154. isCID = false;
  155. }
  156. } else if ("embed".equals(localName)) {
  157. try {
  158. returnFont.setEmbedURI(InternalResourceResolver.cleanURI(attributes.getValue("file")));
  159. } catch (URISyntaxException e) {
  160. throw new SAXException("URI syntax error in metrics file: " + e.getMessage(), e);
  161. }
  162. returnFont.setEmbedResourceName(attributes.getValue("class"));
  163. } else if ("cid-widths".equals(localName)) {
  164. // This is unused
  165. // cidWidthIndex = getInt(attributes.getValue("start-index"));
  166. cidWidths = new ArrayList<Integer>();
  167. } else if ("kerning".equals(localName)) {
  168. currentKerning = new HashMap<Integer, Integer>();
  169. returnFont.putKerningEntry(getInt(attributes.getValue("kpx1")),
  170. currentKerning);
  171. } else if ("bfranges".equals(localName)) {
  172. bfranges = new ArrayList<CMapSegment>();
  173. } else if ("bf".equals(localName)) {
  174. CMapSegment entry = new CMapSegment(getInt(attributes.getValue("us")),
  175. getInt(attributes.getValue("ue")),
  176. getInt(attributes.getValue("gi")));
  177. bfranges.add(entry);
  178. } else if ("wx".equals(localName)) {
  179. cidWidths.add(getInt(attributes.getValue("w")));
  180. // } else if ("widths".equals(localName)) {
  181. // singleFont.width = new int[256];
  182. } else if ("char".equals(localName)) {
  183. try {
  184. singleFont.setWidth(getInt(attributes.getValue("idx")),
  185. getInt(attributes.getValue("wdt")));
  186. } catch (NumberFormatException ne) {
  187. throw new SAXException("Malformed width in metric file: " + ne.getMessage(), ne);
  188. }
  189. } else if ("pair".equals(localName)) {
  190. currentKerning.put(getInt(attributes.getValue("kpx2")),
  191. getInt(attributes.getValue("kern")));
  192. }
  193. }
  194. private int getInt(String str) throws SAXException {
  195. int ret = 0;
  196. try {
  197. ret = Integer.parseInt(str);
  198. } catch (Exception e) {
  199. throw new SAXException("Error while parsing integer value: " + str, e);
  200. }
  201. return ret;
  202. }
  203. /**
  204. * {@inheritDoc}
  205. */
  206. @Override
  207. public void endElement(String uri, String localName, String qName) throws SAXException {
  208. String content = text.toString().trim();
  209. if ("font-name".equals(localName)) {
  210. returnFont.setFontName(content);
  211. } else if ("full-name".equals(localName)) {
  212. returnFont.setFullName(content);
  213. } else if ("family-name".equals(localName)) {
  214. Set<String> s = new HashSet<String>();
  215. s.add(content);
  216. returnFont.setFamilyNames(s);
  217. } else if ("ttc-name".equals(localName) && isCID) {
  218. multiFont.setTTCName(content);
  219. } else if ("encoding".equals(localName)) {
  220. if (singleFont != null && singleFont.getFontType() == FontType.TYPE1) {
  221. singleFont.setEncoding(content);
  222. }
  223. } else if ("cap-height".equals(localName)) {
  224. returnFont.setCapHeight(getInt(content));
  225. } else if ("x-height".equals(localName)) {
  226. returnFont.setXHeight(getInt(content));
  227. } else if ("ascender".equals(localName)) {
  228. returnFont.setAscender(getInt(content));
  229. } else if ("descender".equals(localName)) {
  230. returnFont.setDescender(getInt(content));
  231. } else if ("left".equals(localName)) {
  232. int[] bbox = returnFont.getFontBBox();
  233. bbox[0] = getInt(content);
  234. returnFont.setFontBBox(bbox);
  235. } else if ("bottom".equals(localName)) {
  236. int[] bbox = returnFont.getFontBBox();
  237. bbox[1] = getInt(content);
  238. returnFont.setFontBBox(bbox);
  239. } else if ("right".equals(localName)) {
  240. int[] bbox = returnFont.getFontBBox();
  241. bbox[2] = getInt(content);
  242. returnFont.setFontBBox(bbox);
  243. } else if ("top".equals(localName)) {
  244. int[] bbox = returnFont.getFontBBox();
  245. bbox[3] = getInt(content);
  246. returnFont.setFontBBox(bbox);
  247. } else if ("first-char".equals(localName)) {
  248. returnFont.setFirstChar(getInt(content));
  249. } else if ("last-char".equals(localName)) {
  250. returnFont.setLastChar(getInt(content));
  251. } else if ("flags".equals(localName)) {
  252. returnFont.setFlags(getInt(content));
  253. } else if ("stemv".equals(localName)) {
  254. returnFont.setStemV(getInt(content));
  255. } else if ("italic-angle".equals(localName)) {
  256. returnFont.setItalicAngle(getInt(content));
  257. } else if ("missing-width".equals(localName)) {
  258. returnFont.setMissingWidth(getInt(content));
  259. } else if ("cid-type".equals(localName)) {
  260. multiFont.setCIDType(CIDFontType.byName(content));
  261. } else if ("default-width".equals(localName)) {
  262. multiFont.setDefaultWidth(getInt(content));
  263. } else if ("cid-widths".equals(localName)) {
  264. int[] wds = new int[cidWidths.size()];
  265. int j = 0;
  266. for (Integer cidWidth : cidWidths) {
  267. wds[j++] = cidWidth;
  268. }
  269. //multiFont.addCIDWidthEntry(cidWidthIndex, wds);
  270. multiFont.setWidthArray(wds);
  271. } else if ("bfranges".equals(localName)) {
  272. multiFont.setCMap(bfranges.toArray(new CMapSegment[bfranges.size()]));
  273. }
  274. text.setLength(0); //Reset text buffer (see characters())
  275. }
  276. /**
  277. * {@inheritDoc}
  278. */
  279. @Override
  280. public void characters(char[] ch, int start, int length) {
  281. text.append(ch, start, length);
  282. }
  283. }