1 51 package org.apache.fop.fonts.type1; 52 53 import java.io.*; 54 import java.util.Map ; 55 56 import org.apache.avalon.framework.logger.AbstractLogEnabled; 57 58 import org.apache.fop.fonts.Glyphs; 59 60 63 public class PFMFile extends AbstractLogEnabled { 64 65 private String windowsName; 67 private String postscriptName; 68 private short dfItalic; 69 private int dfWeight; 70 private short dfCharSet; 71 private short dfPitchAndFamily; 72 private int dfAvgWidth; 73 private int dfMaxWidth; 74 private int dfMinWidth; 75 private short dfFirstChar; 76 private short dfLastChar; 77 78 81 private int etmCapHeight; 83 private int etmXHeight; 84 private int etmLowerCaseAscent; 85 private int etmLowerCaseDescent; 86 87 private int[] extentTable; 89 90 private Map kerningTab = new java.util.HashMap (); 91 92 97 public void load(InputStream inStream) throws IOException { 98 InputStream bufin = new BufferedInputStream(inStream, 1024); 99 bufin.mark(1024); 100 PFMInputStream in = new PFMInputStream(bufin); 101 int version = in.readShort(); 102 long filesize = in.readInt(); 103 bufin.reset(); 104 105 byte[] buf = new byte[(int)filesize]; 106 bufin.read(buf, 0, (int)filesize); 107 108 bufin = new ByteArrayInputStream(buf); 109 in = new PFMInputStream(bufin); 110 loadHeader(in); 111 loadExtension(in); 112 } 113 114 119 private void loadHeader(PFMInputStream inStream) throws IOException { 120 inStream.skip(80); 121 dfItalic = inStream.readByte(); 122 inStream.skip(2); 123 dfWeight = inStream.readShort(); 124 dfCharSet = inStream.readByte(); 125 inStream.skip(4); 126 dfPitchAndFamily = inStream.readByte(); 127 dfAvgWidth = inStream.readShort(); 128 dfMaxWidth = inStream.readShort(); 129 dfFirstChar = inStream.readByte(); 130 dfLastChar = inStream.readByte(); 131 inStream.skip(8); 132 long faceOffset = inStream.readInt(); 133 134 inStream.reset(); 135 inStream.skip(faceOffset); 136 windowsName = inStream.readString(); 137 138 inStream.reset(); 139 inStream.skip(117); 140 } 141 142 147 private void loadExtension(PFMInputStream inStream) throws IOException { 148 int size = inStream.readShort(); 149 long extMetricsOffset = inStream.readInt(); 150 long extentTableOffset = inStream.readInt(); 151 inStream.skip(4); 152 long kernPairOffset = inStream.readInt(); 153 long kernTrackOffset = inStream.readInt(); 154 long driverInfoOffset = inStream.readInt(); 155 156 if (kernPairOffset > 0) { 157 inStream.reset(); 158 inStream.skip(kernPairOffset); 159 loadKernPairs(inStream); 160 } 161 162 inStream.reset(); 163 inStream.skip(driverInfoOffset); 164 postscriptName = inStream.readString(); 165 166 if (extMetricsOffset != 0) { 167 inStream.reset(); 168 inStream.skip(extMetricsOffset); 169 loadExtMetrics(inStream); 170 } 171 if (extentTableOffset != 0) { 172 inStream.reset(); 173 inStream.skip(extentTableOffset); 174 loadExtentTable(inStream); 175 } 176 177 } 178 179 184 private void loadKernPairs(PFMInputStream inStream) throws IOException { 185 int i = inStream.readShort(); 186 187 getLogger().info(i + " kerning pairs"); 188 while (i > 0) { 189 int g1 = (int)inStream.readByte(); 190 i--; 191 int g2 = (int)inStream.readByte(); 192 getLogger().debug("Char no: (" + g1 + ", " + g2 + ") kern"); 193 194 int adj = inStream.readShort(); 195 if (adj > 0x8000) { 196 adj = -(0x10000 - adj); 197 getLogger().debug("adjust: " + adj); 198 } 199 200 if (getLogger().isDebugEnabled()) { 201 String glyph1 = Glyphs.tex8r[g1]; 202 String glyph2 = Glyphs.tex8r[g2]; 203 getLogger().debug("glyphs: " + glyph1 + ", " + glyph2); 204 } 205 206 Map adjTab = (Map )kerningTab.get(new Integer (g1)); 207 if (adjTab == null) { 208 adjTab = new java.util.HashMap (); 209 } 210 adjTab.put(new Integer (g2), new Integer (adj)); 211 kerningTab.put(new Integer (g1), adjTab); 212 } 213 } 214 215 220 private void loadExtMetrics(PFMInputStream inStream) throws IOException { 221 int size = inStream.readShort(); 222 inStream.skip(12); 223 etmCapHeight = inStream.readShort(); 224 etmXHeight = inStream.readShort(); 225 etmLowerCaseAscent = inStream.readShort(); 226 etmLowerCaseDescent = inStream.readShort(); 227 } 228 229 234 private void loadExtentTable(PFMInputStream inStream) throws IOException { 235 extentTable = new int[dfLastChar - dfFirstChar + 1]; 236 dfMinWidth = dfMaxWidth; 237 for (short i = dfFirstChar; i <= dfLastChar; i++) { 238 extentTable[i - dfFirstChar] = inStream.readShort(); 239 if (extentTable[i - dfFirstChar] < dfMinWidth) { 240 dfMinWidth = extentTable[i - dfFirstChar]; 241 } 242 } 243 } 244 245 250 public String getWindowsName() { 251 return windowsName; 252 } 253 254 259 public Map getKerning() { 260 return kerningTab; 261 } 262 263 268 public String getPostscriptName() { 269 return postscriptName; 270 } 271 272 277 public short getCharSet() { 278 return dfCharSet; 279 } 280 281 286 public String getCharSetName() { 287 switch (dfCharSet) { 288 case 0: 289 return "WinAnsi"; 290 case 128: 291 return "Shift-JIS (Japanese)"; 292 default: 293 return "Unknown"; 294 } 295 } 296 297 303 public short getFirstChar() { 304 return dfFirstChar; 305 } 306 307 313 public short getLastChar() { 314 return dfLastChar; 315 } 316 317 322 public int getCapHeight() { 323 return etmCapHeight; 324 } 325 326 331 public int getXHeight() { 332 return etmXHeight; 333 } 334 335 340 public int getLowerCaseAscent() { 341 return etmLowerCaseAscent; 342 } 343 344 349 public int getLowerCaseDescent() { 350 return etmLowerCaseDescent; 351 } 352 353 358 public boolean getIsProportional() { 359 return ((dfPitchAndFamily & 1) == 1); 360 } 361 362 369 public int[] getFontBBox() { 370 int[] bbox = new int[4]; 371 372 if (!getIsProportional() && (dfAvgWidth == dfMaxWidth)) { 374 bbox[0] = -20; 375 } else { 376 bbox[0] = -100; 377 } 378 bbox[1] = -(getLowerCaseDescent() + 5); 379 bbox[2] = dfMaxWidth + 10; 380 bbox[3] = getLowerCaseAscent() + 5; 381 return bbox; 382 } 383 384 390 public int getFlags() { 391 int flags = 0; 392 if (!getIsProportional()) { 393 flags |= 1; 394 } 395 if ((dfPitchAndFamily & 16) == 16) { 396 flags |= 2; 397 } 398 if ((dfPitchAndFamily & 64) == 64) { 399 flags |= 4; 400 } 401 if (dfCharSet == 0) { 402 flags |= 6; 403 } 404 if (dfItalic != 0) { 405 flags |= 7; 406 } 407 return flags; 408 } 409 410 417 public int getStemV() { 418 if (dfItalic != 0) { 420 return (int)Math.round(dfMinWidth * 0.25); 421 } else { 422 return (int)Math.round(dfMinWidth * 0.6); 423 } 424 } 425 426 433 public int getItalicAngle() { 434 if (dfItalic != 0) { 435 return -16; } else { 437 return 0; 438 } 439 } 440 441 447 public int getCharWidth(short which) { 448 return extentTable[which - dfFirstChar]; 449 } 450 451 } 452 | Popular Tags |