1 51 package org.apache.fop.render.pdf; 52 53 import java.util.List ; 54 import java.util.Map ; 55 import java.io.IOException ; 56 import java.net.URL ; 57 58 import org.apache.fop.render.pdf.fonts.*; 59 import org.apache.fop.pdf.PDFCIDFont; 60 import org.apache.fop.configuration.ConfigurationReader; 61 import org.apache.fop.configuration.Configuration; 62 import org.apache.fop.apps.FOPException; 63 import org.apache.fop.tools.URLBuilder; 64 65 import org.xml.sax.helpers.DefaultHandler ; 66 import org.xml.sax.XMLReader ; 67 import org.xml.sax.SAXException ; 68 import org.xml.sax.InputSource ; 69 import org.xml.sax.Locator ; 70 import org.xml.sax.Attributes ; 71 72 82 public class FontReader extends DefaultHandler { 83 private Locator locator = null; 84 private boolean isCID = false; 85 private MultiByteFont multiFont = null; 86 private SingleByteFont singleFont = null; 87 private Font returnFont = null; 88 private String text = null; 90 91 private List cidWidths = null; 92 private int cidWidthIndex = 0; 93 94 private Map currentKerning = null; 95 96 private List bfranges = null; 97 98 private void createFont(URL url) throws FOPException { 99 XMLReader parser = ConfigurationReader.createParser(); 100 if (parser == null) 101 throw new FOPException("Unable to create SAX parser"); 102 103 try { 104 parser.setFeature("http://xml.org/sax/features/namespace-prefixes", 105 false); 106 } catch (SAXException e) { 107 throw new FOPException("You need a SAX parser which supports SAX version 2", 108 e); 109 } 110 111 parser.setContentHandler(this); 112 113 try { 114 parser.parse(new InputSource (url.openStream())); 115 } catch (SAXException e) { 116 throw new FOPException(e); 117 } catch (IOException e) { 118 throw new FOPException(e); 119 } 120 121 } 122 123 126 public void setFontEmbedPath(URL path) { 127 if (isCID) 128 multiFont.embedFileName = path; 129 else 130 singleFont.embedFileName = path; 131 } 132 133 136 public void useKerning(boolean kern) { 137 if (isCID) 138 multiFont.useKerning = true; 139 else 140 singleFont.useKerning = true; 141 } 142 143 144 147 public Font getFont() { 148 return returnFont; 149 } 150 151 155 public FontReader(URL path) throws FOPException { 156 createFont(path); 157 } 158 159 public void startDocument() {} 160 161 public void setDocumentLocator(Locator locator) { 162 this.locator = locator; 163 } 164 165 public void startElement(String uri, String localName, String qName, 166 Attributes attributes) throws SAXException { 167 if (localName.equals("font-metrics")) { 168 if ("TYPE0".equals(attributes.getValue("type"))) { 169 multiFont = new MultiByteFont(); 170 returnFont = multiFont; 171 isCID = true; 172 } else if ("TRUETYPE".equals(attributes.getValue("type"))) { 173 singleFont = new SingleByteFont(); 174 singleFont.subType = org.apache.fop.pdf.PDFFont.TRUETYPE; 175 returnFont = singleFont; 176 isCID = false; 177 } else { 178 singleFont = new SingleByteFont(); 179 singleFont.subType = org.apache.fop.pdf.PDFFont.TYPE1; 180 returnFont = singleFont; 181 isCID = false; 182 } 183 } else if ("embed".equals(localName)) { 184 if (isCID) { 185 187 String filename = attributes.getValue("file"); 188 if (filename != null) { 189 try { 190 multiFont.embedFileName = URLBuilder.buildURL( 191 Configuration.getFontBaseURL(), filename); 192 } catch (java.net.MalformedURLException mfue) { 193 throw new SAXException (mfue); 194 } 195 } 196 multiFont.embedResourceName = attributes.getValue("class"); 197 } else { 198 String filename = attributes.getValue("file"); 199 if (filename != null) { 200 try { 201 singleFont.embedFileName = URLBuilder.buildURL( 202 Configuration.getFontBaseURL(), filename); 203 } catch (java.net.MalformedURLException mfue) { 204 throw new SAXException (mfue); 205 } 206 } 207 singleFont.embedResourceName = attributes.getValue("class"); 208 } 209 } else if ("cid-widths".equals(localName)) { 210 cidWidthIndex = getInt(attributes.getValue("start-index")); 211 cidWidths = new java.util.ArrayList (); 212 } else if ("kerning".equals(localName)) { 213 currentKerning = new java.util.HashMap (); 214 if (isCID) 215 multiFont.kerning.put(new Integer (attributes.getValue("kpx1")), 216 currentKerning); 217 else 218 singleFont.kerning.put(new Integer (attributes.getValue("kpx1")), 219 currentKerning); 220 } else if ("bfranges".equals(localName)) { 221 bfranges = new java.util.ArrayList (); 222 } else if ("bf".equals(localName)) { 223 BFEntry entry = new BFEntry(); 224 entry.unicodeStart = getInt(attributes.getValue("us")); 225 entry.unicodeEnd = getInt(attributes.getValue("ue")); 226 entry.glyphStartIndex = getInt(attributes.getValue("gi")); 227 bfranges.add(entry); 228 } else if ("wx".equals(localName)) { 229 cidWidths.add(new Integer (attributes.getValue("w"))); 230 } else if ("widths".equals(localName)) { 231 singleFont.width = new int[256]; 232 } else if ("char".equals(localName)) { 233 try { 234 singleFont.width[Integer.parseInt(attributes.getValue("idx"))] = 235 Integer.parseInt(attributes.getValue("wdt")); 236 } catch (NumberFormatException ne) { 237 System.out.println("Malformed width in metric file: " 238 + ne.getMessage()); 239 } 240 } else if ("pair".equals(localName)) { 241 currentKerning.put(new Integer (attributes.getValue("kpx2")), 242 new Integer (attributes.getValue("kern"))); 243 } 244 } 245 246 private int getInt(String str) { 247 int ret = 0; 248 try { 249 ret = Integer.parseInt(str); 250 } catch (Exception e) {} 251 return ret; 252 } 253 254 public void endElement(String uri, String localName, String qName) { 255 if ("font-name".equals(localName)) 256 if (isCID) 257 multiFont.fontName = text; 258 else 259 singleFont.fontName = text; 260 if ("ttc-name".equals(localName) && isCID) 261 multiFont.ttcName = text; 262 else if ("cap-height".equals(localName)) 263 if (isCID) 264 multiFont.capHeight = getInt(text); 265 else 266 singleFont.capHeight = getInt(text); 267 else if ("x-height".equals(localName)) 268 if (isCID) 269 multiFont.xHeight = getInt(text); 270 else 271 singleFont.xHeight = getInt(text); 272 else if ("ascender".equals(localName)) 273 if (isCID) 274 multiFont.ascender = getInt(text); 275 else 276 singleFont.ascender = getInt(text); 277 else if ("descender".equals(localName)) 278 if (isCID) 279 multiFont.descender = getInt(text); 280 else 281 singleFont.descender = getInt(text); 282 else if ("left".equals(localName)) 283 if (isCID) 284 multiFont.fontBBox[0] = getInt(text); 285 else 286 singleFont.fontBBox[0] = getInt(text); 287 else if ("bottom".equals(localName)) 288 if (isCID) 289 multiFont.fontBBox[1] = getInt(text); 290 else 291 singleFont.fontBBox[1] = getInt(text); 292 else if ("right".equals(localName)) 293 if (isCID) 294 multiFont.fontBBox[2] = getInt(text); 295 else 296 singleFont.fontBBox[2] = getInt(text); 297 else if ("first-char".equals(localName)) 298 singleFont.firstChar = getInt(text); 299 else if ("last-char".equals(localName)) 300 singleFont.lastChar = getInt(text); 301 else if ("top".equals(localName)) 302 if (isCID) 303 multiFont.fontBBox[3] = getInt(text); 304 else 305 singleFont.fontBBox[3] = getInt(text); 306 else if ("flags".equals(localName)) 307 if (isCID) 308 multiFont.flags = getInt(text); 309 else 310 singleFont.flags = getInt(text); 311 else if ("stemv".equals(localName)) 312 if (isCID) 313 multiFont.stemV = getInt(text); 314 else 315 singleFont.stemV = getInt(text); 316 else if ("italic-angle".equals(localName)) 317 if (isCID) 318 multiFont.italicAngle = getInt(text); 319 else 320 singleFont.italicAngle = getInt(text); 321 else if ("missing-width".equals(localName)) 322 if (isCID) 323 multiFont.missingWidth = getInt(text); 324 else 325 singleFont.missingWidth = getInt(text); 326 else if ("cid-type".equals(localName)) { 327 if ("CIDFontType2".equals(text)) 328 multiFont.cidType = PDFCIDFont.CID_TYPE2; 329 } else if ("default-width".equals(localName)) { 330 multiFont.defaultWidth = getInt(text); 331 } else if ("cid-widths".equals(localName)) { 332 int[] wds = new int[cidWidths.size()]; 333 for (int i = 0; i < cidWidths.size(); i++ ) { 334 wds[i] = ((Integer )cidWidths.get(i)).intValue(); 335 } 336 337 multiFont.warray.addEntry(cidWidthIndex, wds); 338 multiFont.width = wds; 339 340 } else if ("bfranges".equals(localName)) { 341 BFEntry[] entries = new BFEntry[bfranges.size()]; 342 entries = (BFEntry[])bfranges.toArray(entries); 343 multiFont.bfentries = entries; 344 } 345 346 } 347 348 public void characters(char[] ch, int start, int length) { 349 char c[] = new char[length]; 350 System.arraycopy(ch, start, c, 0, length); 351 text = new String (c); 352 } 353 354 } 355 356 357 | Popular Tags |