001 /**
002 * ===========================================
003 * LibFonts : a free Java font reading library
004 * ===========================================
005 *
006 * Project Info: http://reporting.pentaho.org/libfonts/
007 *
008 * (C) Copyright 2006-2007, by Pentaho Corporation and Contributors.
009 *
010 * This library is free software; you can redistribute it and/or modify it under the terms
011 * of the GNU Lesser General Public License as published by the Free Software Foundation;
012 * either version 2.1 of the License, or (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016 * See the GNU Lesser General Public License for more details.
017 *
018 * You should have received a copy of the GNU Lesser General Public License along with this
019 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020 * Boston, MA 02111-1307, USA.
021 *
022 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023 * in the United States and other countries.]
024 *
025 * ------------
026 * $Id: ByteAccessUtilities.java 3523 2007-10-16 11:03:09Z tmorgner $
027 * ------------
028 * (C) Copyright 2006-2007, by Pentaho Corporation.
029 */
030 package org.jfree.fonts;
031
032 import org.jfree.fonts.encoding.ByteBuffer;
033 import org.jfree.fonts.encoding.CodePointBuffer;
034 import org.jfree.fonts.encoding.Encoding;
035 import org.jfree.fonts.encoding.EncodingException;
036 import org.jfree.fonts.encoding.EncodingRegistry;
037 import org.jfree.fonts.encoding.manual.Utf16LE;
038
039 /**
040 * Reads byte-data using a Big-Endian access schema. Big-Endian is used for TrueType fonts.
041 *
042 * @author Thomas Morgner
043 */
044 public class ByteAccessUtilities
045 {
046 private ByteAccessUtilities()
047 {
048 }
049
050 public static int readUShort (final byte[] data, final int pos)
051 {
052 return ((data[pos] & 0xff) << 8) | (data[pos + 1] & 0xff);
053 }
054
055 public static long readULong (final byte[] data, final int pos)
056 {
057 final int c1 = (data[pos] & 0xff);
058 final int c2 = (data[pos + 1] & 0xff);
059 final int c3 = (data[pos + 2] & 0xff);
060 final int c4 = (data[pos + 3] & 0xff);
061
062 long retval = ((long) c1 << 24);
063 retval |= (long)c2 << 16;
064 retval |= (long)c3 << 8;
065 retval |= (long)c4;
066 return retval;
067 }
068
069 public static float readFixed (final byte[] data, final int pos)
070 {
071 final short mantissa = readShort(data, pos);
072 final int fraction = readUShort(data, pos + 2);
073 if (fraction == 0 || mantissa == 0)
074 {
075 return 0;
076 }
077 return (float) mantissa / (fraction / 16384.0f);
078 }
079
080 public static long readLongDateTime (final byte[] data, final int pos)
081 {
082 final int c1 = (data[pos] & 0xff);
083 final int c2 = (data[pos + 1] & 0xff);
084 final int c3 = (data[pos + 2] & 0xff);
085 final int c4 = (data[pos + 3] & 0xff);
086 final int c5 = (data[pos + 4] & 0xff);
087 final int c6 = (data[pos + 5] & 0xff);
088 final int c7 = (data[pos + 6] & 0xff);
089 final int c8 = (data[pos + 7] & 0xff);
090
091 long retval = ((long) c1 << 56);
092 retval |= (long)c2 << 48;
093 retval |= (long)c3 << 40;
094 retval |= (long)c4 << 32;
095 retval |= (long)c5 << 24;
096 retval |= (long)c6 << 16;
097 retval |= (long)c7 << 8;
098 retval |= (long)c8;
099 return retval;
100 }
101
102 public static byte[] readBytes (final byte[] data,
103 final int pos, final int length)
104 {
105 final byte[] retval = new byte[length];
106 System.arraycopy(data, pos, retval, 0, length);
107 return retval;
108 }
109
110 public static short readShort (final byte[] data, final int pos)
111 {
112 return (short) ((data[pos] & 0xff) << 8 | (data[pos + 1] & 0xff));
113 }
114
115 public static int readLong (final byte[] data, final int pos)
116 {
117 int retval = 0;
118 retval |= (long)(data[pos] & 0xff) << 24;
119 retval |= (long)(data[pos + 1] & 0xff) << 16;
120 retval |= (long)(data[pos + 2] & 0xff) << 8;
121 retval |= (long)(data[pos + 3] & 0xff);
122 return retval;
123 }
124
125 public static int readZStringOffset (final byte[] data, final int pos, final int maxLength)
126 {
127 final int lastPos = Math.min (pos + maxLength, pos + data.length);
128 for (int i = pos; i < lastPos; i++)
129 {
130 if (data[i] == 0)
131 {
132 return i;
133 }
134 }
135
136 return lastPos;
137 }
138
139 public static String readZString (final byte[] data, final int pos, final int maxLength, final String encoding)
140 throws EncodingException
141 {
142 final int lastPos = Math.min (pos + maxLength, pos + data.length);
143 for (int i = pos; i < lastPos; i++)
144 {
145 if (data[i] == 0)
146 {
147 return readString(data, pos, i - pos, encoding);
148 }
149 }
150
151 return readString(data, pos, lastPos, encoding);
152 }
153
154 public static String readString (final byte[] data, final int pos,
155 final int length, final String encoding)
156 throws EncodingException
157 {
158 final Encoding enc;
159 if ("UTF-16".equals(encoding))
160 {
161 enc = EncodingRegistry.getInstance().getEncoding("UTF-16LE");
162 }
163 else
164 {
165 enc = EncodingRegistry.getInstance().getEncoding(encoding);
166 }
167 final ByteBuffer byteBuffer = new ByteBuffer(data, pos, length);
168 final CodePointBuffer cp = enc.decode(byteBuffer, null);
169 return Utf16LE.getInstance().encodeString(cp);
170 }
171 }