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 package org.apache.fontbox.pfb; 18 19 import java.io.BufferedInputStream; 20 import java.io.ByteArrayInputStream; 21 import java.io.ByteArrayOutputStream; 22 import java.io.EOFException; 23 import java.io.FileInputStream; 24 import java.io.IOException; 25 import java.io.InputStream; 26 27 /** 28 * Parser for a pfb-file. 29 * 30 * @author Ben Litchfield (ben@benlitchfield.com) 31 * @author <a href="mailto:m.g.n@gmx.de">Michael Niedermair</a> 32 * @version $Revision: 1.1 $ 33 */ 34 public class PfbParser 35 { 36 /** 37 * the pdf header length. 38 * (start-marker (1 byte), ascii-/binary-marker (1 byte), size (4 byte)) 39 * 3*6 == 18 40 */ 41 private static final int PFB_HEADER_LENGTH = 18; 42 43 /** 44 * the start marker. 45 */ 46 private static final int START_MARKER = 0x80; 47 48 /** 49 * the ascii marker. 50 */ 51 private static final int ASCII_MARKER = 0x01; 52 53 /** 54 * the binary marker. 55 */ 56 private static final int BINARY_MARKER = 0x02; 57 58 /** 59 * The record types in the pfb-file. 60 */ 61 private static final int[] PFB_RECORDS = {ASCII_MARKER, BINARY_MARKER, 62 ASCII_MARKER}; 63 64 /** 65 * buffersize. 66 */ 67 private static final int BUFFER_SIZE = 0xffff; 68 69 /** 70 * the parsed pfb-data. 71 */ 72 private byte[] pfbdata; 73 74 /** 75 * the lengths of the records. 76 */ 77 private int[] lengths; 78 79 // sample (pfb-file) 80 // 00000000 80 01 8b 15 00 00 25 21 50 53 2d 41 64 6f 62 65 81 // ......%!PS-Adobe 82 83 84 /** 85 * Create a new object. 86 * @param filename the file name 87 * @throws IOException if an IO-error occurs. 88 */ 89 public PfbParser(final String filename) throws IOException 90 { 91 this( new BufferedInputStream(new FileInputStream(filename),BUFFER_SIZE) ); 92 } 93 94 /** 95 * Create a new object. 96 * @param in The input. 97 * @throws IOException if an IO-error occurs. 98 */ 99 public PfbParser(final InputStream in) throws IOException 100 { 101 byte[] pfb = readPfbInput(in); 102 parsePfb(pfb); 103 } 104 105 /** 106 * Parse the pfb-array. 107 * @param pfb The pfb-Array 108 * @throws IOException in an IO-error occurs. 109 */ 110 private void parsePfb(final byte[] pfb) throws IOException 111 { 112 113 ByteArrayInputStream in = new ByteArrayInputStream(pfb); 114 pfbdata = new byte[pfb.length - PFB_HEADER_LENGTH]; 115 lengths = new int[PFB_RECORDS.length]; 116 int pointer = 0; 117 for (int records = 0; records < PFB_RECORDS.length; records++) 118 { 119 if (in.read() != START_MARKER) 120 { 121 throw new IOException("Start marker missing"); 122 } 123 124 if (in.read() != PFB_RECORDS[records]) 125 { 126 throw new IOException("Incorrect record type"); 127 } 128 129 int size = in.read(); 130 size += in.read() << 8; 131 size += in.read() << 16; 132 size += in.read() << 24; 133 lengths[records] = size; 134 int got = in.read(pfbdata, pointer, size); 135 if (got < 0) 136 { 137 throw new EOFException(); 138 } 139 pointer += got; 140 } 141 } 142 143 /** 144 * Read the pdf input. 145 * @param in The input. 146 * @return Returns the pdf-array. 147 * @throws IOException if an IO-error occurs. 148 */ 149 private byte[] readPfbInput(final InputStream in) throws IOException 150 { 151 // copy into an array 152 ByteArrayOutputStream out = new ByteArrayOutputStream(); 153 byte[] tmpbuf = new byte[BUFFER_SIZE]; 154 int amountRead = -1; 155 while ((amountRead = in.read(tmpbuf)) != -1) 156 { 157 out.write(tmpbuf, 0, amountRead); 158 } 159 return out.toByteArray(); 160 } 161 162 /** 163 * Returns the lengths. 164 * @return Returns the lengths. 165 */ 166 public int[] getLengths() 167 { 168 return lengths; 169 } 170 171 /** 172 * Returns the pfbdata. 173 * @return Returns the pfbdata. 174 */ 175 public byte[] getPfbdata() 176 { 177 return pfbdata; 178 } 179 180 /** 181 * Returns the pfb data as stream. 182 * @return Returns the pfb data as stream. 183 */ 184 public InputStream getInputStream() 185 { 186 return new ByteArrayInputStream(pfbdata); 187 } 188 189 /** 190 * Returns the size of the pfb-data. 191 * @return Returns the size of the pfb-data. 192 */ 193 public int size() 194 { 195 return pfbdata.length; 196 } 197 }