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.ttf; 18 19 import java.io.EOFException; 20 import java.io.IOException; 21 import java.io.InputStream; 22 23 import java.util.Calendar; 24 import java.util.GregorianCalendar; 25 26 /** 27 * An interface into a data stream. 28 * 29 * @author Ben Litchfield (ben@benlitchfield.com) 30 * @version $Revision: 1.1 $ 31 */ 32 public abstract class TTFDataStream 33 { 34 35 /** 36 * Read a 16.16 fixed value, where the first 16 bits are the decimal and the last 37 * 16 bits are the fraction. 38 * @return A 32 bit value. 39 * @throws IOException If there is an error reading the data. 40 */ 41 public float read32Fixed() throws IOException 42 { 43 float retval = 0; 44 retval = readSignedShort(); 45 retval += (readUnsignedShort()/65536); 46 return retval; 47 } 48 49 /** 50 * Read a fixed length ascii string. 51 * @param length The length of the string to read. 52 * @return A string of the desired length. 53 * @throws IOException If there is an error reading the data. 54 */ 55 public String readString( int length ) throws IOException 56 { 57 return readString( length, "ISO-8859-1" ); 58 } 59 60 /** 61 * Read a fixed length ascii string. 62 * @param length The length of the string to read in bytes. 63 * @param charset The expected character set of the string. 64 * @return A string of the desired length. 65 * @throws IOException If there is an error reading the data. 66 */ 67 public String readString( int length, String charset ) throws IOException 68 { 69 byte[] buffer = read( length ); 70 return new String(buffer, charset); 71 } 72 73 /** 74 * Read an unsigned byte. 75 * @return An unsigned byte. 76 * @throws IOException If there is an error reading the data. 77 */ 78 public abstract int read() throws IOException; 79 80 /** 81 * Read an unsigned byte. 82 * @return An unsigned byte. 83 * @throws IOException If there is an error reading the data. 84 */ 85 public abstract long readLong() throws IOException; 86 87 88 /** 89 * Read a signed byte. 90 * @return A signed byte. 91 * @throws IOException If there is an error reading the data. 92 */ 93 public int readSignedByte() throws IOException 94 { 95 int signedByte = read(); 96 return signedByte < 127 ? signedByte : signedByte-256; 97 } 98 99 /** 100 * Read an unsigned integer. 101 * @return An unsiged integer. 102 * @throws IOException If there is an error reading the data. 103 */ 104 public long readUnsignedInt() throws IOException 105 { 106 long byte1 = read(); 107 long byte2 = read(); 108 long byte3 = read(); 109 long byte4 = read(); 110 if( byte4 < 0 ) 111 { 112 throw new EOFException(); 113 } 114 return (byte1 << 24) + (byte2 << 16) + (byte3 << 8) + (byte4 << 0); 115 } 116 117 /** 118 * Read an unsigned short. 119 * 120 * @return An unsigned short. 121 * @throws IOException If there is an error reading the data. 122 */ 123 public abstract int readUnsignedShort() throws IOException; 124 125 /** 126 * Read an unsigned short array. 127 * 128 * @param length The length of the array to read. 129 * @return An unsigned short array. 130 * @throws IOException If there is an error reading the data. 131 */ 132 public int[] readUnsignedShortArray( int length ) throws IOException 133 { 134 int[] array = new int[ length ]; 135 for( int i=0; i<length; i++ ) 136 { 137 array[i] = readUnsignedShort(); 138 } 139 return array; 140 } 141 142 /** 143 * Read an signed short. 144 * 145 * @return An signed short. 146 * @throws IOException If there is an error reading the data. 147 */ 148 public abstract short readSignedShort() throws IOException; 149 150 /** 151 * Read an eight byte international date. 152 * 153 * @return An signed short. 154 * @throws IOException If there is an error reading the data. 155 */ 156 public Calendar readInternationalDate() throws IOException 157 { 158 long secondsSince1904 = readLong(); 159 GregorianCalendar cal = new GregorianCalendar( 1904, 0, 1 ); 160 long millisFor1904 = cal.getTimeInMillis(); 161 millisFor1904 += (secondsSince1904*1000); 162 cal.setTimeInMillis( millisFor1904 ); 163 return cal; 164 } 165 166 /** 167 * Close the underlying resources. 168 * 169 * @throws IOException If there is an error closing the resources. 170 */ 171 public abstract void close() throws IOException; 172 173 /** 174 * Seek into the datasource. 175 * 176 * @param pos The position to seek to. 177 * @throws IOException If there is an error seeking to that position. 178 */ 179 public abstract void seek(long pos) throws IOException; 180 181 /** 182 * Read a specific number of bytes from the stream. 183 * @param numberOfBytes The number of bytes to read. 184 * @return The byte buffer. 185 * @throws IOException If there is an error while reading. 186 */ 187 public byte[] read( int numberOfBytes ) throws IOException 188 { 189 byte[] data = new byte[ numberOfBytes ]; 190 int amountRead = 0; 191 int totalAmountRead = 0; 192 while( (amountRead = read( data, totalAmountRead, numberOfBytes-totalAmountRead ) ) != -1 && 193 totalAmountRead < numberOfBytes ) 194 { 195 totalAmountRead += amountRead; 196 //read at most numberOfBytes bytes from the stream. 197 } 198 return data; 199 } 200 201 /** 202 * @see java.io.InputStream#read( byte[], int, int ) 203 * 204 * @param b The buffer to write to. 205 * @param off The offset into the buffer. 206 * @param len The length into the buffer. 207 * 208 * @return The number of bytes read. 209 * 210 * @throws IOException If there is an error reading from the stream. 211 */ 212 public abstract int read(byte[] b, 213 int off, 214 int len) 215 throws IOException; 216 217 /** 218 * Get the current position in the stream. 219 * @return The current position in the stream. 220 * @throws IOException If an error occurs while reading the stream. 221 */ 222 public abstract long getCurrentPosition() throws IOException; 223 224 /** 225 * This will get the original data file that was used for this 226 * stream. 227 * 228 * @return The data that was read from. 229 * @throws IOException If there is an issue reading the data. 230 */ 231 public abstract InputStream getOriginalData() throws IOException; 232 233 }