/* * $Id: BaseTable.java,v 1.3 2007-02-08 04:31:31 davidsch Exp $ * * Typecast - The Font Development Environment * * Copyright (c) 2004-2007 David Schweinsberg * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jogamp.graph.font.typecast.ot.table; import java.io.ByteArrayInputStream; import java.io.DataInput; import java.io.DataInputStream; import java.io.IOException; /** * Baseline Table * @version $Id: BaseTable.java,v 1.3 2007-02-08 04:31:31 davidsch Exp $ * @author <a href="mailto:davidsch@dev.java.net">David Schweinsberg</a> */ public class BaseTable implements Table { abstract class BaseCoord { abstract int getBaseCoordFormat(); abstract short getCoordinate(); } class BaseCoordFormat1 extends BaseCoord { private final short _coordinate; protected BaseCoordFormat1(final DataInput di) throws IOException { _coordinate = di.readShort(); } @Override int getBaseCoordFormat() { return 1; } @Override short getCoordinate() { return _coordinate; } } class BaseCoordFormat2 extends BaseCoord { private final short _coordinate; // private final int _referenceGlyph; // private final int _baseCoordPoint; protected BaseCoordFormat2(final DataInput di) throws IOException { _coordinate = di.readShort(); /* _referenceGlyph = */ di.readUnsignedShort(); /* _baseCoordPoint = */ di.readUnsignedShort(); } @Override int getBaseCoordFormat() { return 2; } @Override short getCoordinate() { return _coordinate; } } class BaseCoordFormat3 extends BaseCoord { private final short _coordinate; // private final int _deviceTableOffset; protected BaseCoordFormat3(final DataInput di) throws IOException { _coordinate = di.readShort(); /* _deviceTableOffset = */ di.readUnsignedShort(); } @Override int getBaseCoordFormat() { return 2; } @Override short getCoordinate() { return _coordinate; } } static class FeatMinMaxRecord { // private final int _tag; // private final int _minCoordOffset; // private final int _maxCoordOffset; protected FeatMinMaxRecord(final DataInput di) throws IOException { /* _tag = */ di.readInt(); /* _minCoordOffset = */ di.readUnsignedShort(); /* _maxCoordOffset = */ di.readUnsignedShort(); } } class MinMax { // private final int _minCoordOffset; // private final int _maxCoordOffset; private final int _featMinMaxCount; private final FeatMinMaxRecord[] _featMinMaxRecord; protected MinMax(final int minMaxOffset) throws IOException { final DataInput di = getDataInputForOffset(minMaxOffset); /* _minCoordOffset = */ di.readUnsignedShort(); /* _maxCoordOffset = */ di.readUnsignedShort(); _featMinMaxCount = di.readUnsignedShort(); _featMinMaxRecord = new FeatMinMaxRecord[_featMinMaxCount]; for (int i = 0; i < _featMinMaxCount; ++i) { _featMinMaxRecord[i] = new FeatMinMaxRecord(di); } } } class BaseValues { // private final int _defaultIndex; private final int _baseCoordCount; private final int[] _baseCoordOffset; private final BaseCoord[] _baseCoords; protected BaseValues(final int baseValuesOffset) throws IOException { final DataInput di = getDataInputForOffset(baseValuesOffset); /* _defaultIndex = */ di.readUnsignedShort(); _baseCoordCount = di.readUnsignedShort(); _baseCoordOffset = new int[_baseCoordCount]; for (int i = 0; i < _baseCoordCount; ++i) { _baseCoordOffset[i] = di.readUnsignedShort(); } _baseCoords = new BaseCoord[_baseCoordCount]; for (int i = 0; i < _baseCoordCount; ++i) { final int format = di.readUnsignedShort(); switch (format) { case 1: _baseCoords[i] = new BaseCoordFormat1(di); break; case 2: _baseCoords[i] = new BaseCoordFormat2(di); break; case 3: _baseCoords[i] = new BaseCoordFormat3(di); break; } } } } static class BaseLangSysRecord { // private final int _baseLangSysTag; private final int _minMaxOffset; protected BaseLangSysRecord(final DataInput di) throws IOException { /* _baseLangSysTag = */ di.readInt(); _minMaxOffset = di.readUnsignedShort(); } /** int getBaseLangSysTag() { return _baseLangSysTag; } */ int getMinMaxOffset() { return _minMaxOffset; } } class BaseScript { private final int _thisOffset; private final int _baseValuesOffset; private final int _defaultMinMaxOffset; private final int _baseLangSysCount; private final BaseLangSysRecord[] _baseLangSysRecord; private BaseValues _baseValues; private MinMax[] _minMax; protected BaseScript(final int baseScriptOffset) throws IOException { _thisOffset = baseScriptOffset; final DataInput di = getDataInputForOffset(baseScriptOffset); _baseValuesOffset = di.readUnsignedShort(); _defaultMinMaxOffset = di.readUnsignedShort(); _baseLangSysCount = di.readUnsignedShort(); _baseLangSysRecord = new BaseLangSysRecord[_baseLangSysCount]; for (int i = 0; i < _baseLangSysCount; ++i) { _baseLangSysRecord[i] = new BaseLangSysRecord(di); } if (_baseValuesOffset > 0) { _baseValues = new BaseValues(baseScriptOffset + _baseValuesOffset); } for (int i = 0; i < _baseLangSysCount; ++i) { _minMax[i] = new MinMax(baseScriptOffset + _baseLangSysRecord[i].getMinMaxOffset()); } } @Override public String toString() { final StringBuilder sb = new StringBuilder() .append("\nBaseScript BaseScriptT").append(Integer.toHexString(_thisOffset)) .append("\nBaseValuesT").append(Integer.toHexString(_thisOffset + _baseValuesOffset)) .append("\nMinMaxT").append(Integer.toHexString(_thisOffset + _defaultMinMaxOffset)) .append("\n").append(Integer.toHexString(_baseLangSysCount)); // for (int i = 0; i < _baseLangSysCount; ++i) { // sb.append("\n ; BaseScriptRecord[").append(i); // sb.append("]\n'").append(tagAsString(_baseScriptRecord[i].getBaseScriptTag())).append("'"); // sb.append("\nBaseScriptT").append(Integer.toHexString(_thisOffset + _baseScriptRecord[i].getBaseScriptOffset())); // } // for (int i = 0; i < _baseScriptCount; ++i) { // sb.append("\n").append(_baseScripts[i].toString()); // } if (_baseValues != null) { sb.append("\n").append(_baseValues.toString()); } return sb.toString(); } } static class BaseScriptRecord { private final int _baseScriptTag; private final int _baseScriptOffset; protected BaseScriptRecord(final DataInput di) throws IOException { _baseScriptTag = di.readInt(); _baseScriptOffset = di.readUnsignedShort(); } int getBaseScriptTag() { return _baseScriptTag; } int getBaseScriptOffset() { return _baseScriptOffset; } } class BaseScriptList { private final int _thisOffset; private final int _baseScriptCount; private final BaseScriptRecord[] _baseScriptRecord; private final BaseScript[] _baseScripts; protected BaseScriptList(final int baseScriptListOffset) throws IOException { _thisOffset = baseScriptListOffset; final DataInput di = getDataInputForOffset(baseScriptListOffset); _baseScriptCount = di.readUnsignedShort(); _baseScriptRecord = new BaseScriptRecord[_baseScriptCount]; for (int i = 0; i < _baseScriptCount; ++i) { _baseScriptRecord[i] = new BaseScriptRecord(di); } _baseScripts = new BaseScript[_baseScriptCount]; for (int i = 0; i < _baseScriptCount; ++i) { _baseScripts[i] = new BaseScript( baseScriptListOffset + _baseScriptRecord[i].getBaseScriptOffset()); } } @Override public String toString() { final StringBuilder sb = new StringBuilder() .append("\nBaseScriptList BaseScriptListT").append(Integer.toHexString(_thisOffset)) .append("\n").append(Integer.toHexString(_baseScriptCount)); for (int i = 0; i < _baseScriptCount; ++i) { sb.append("\n ; BaseScriptRecord[").append(i); sb.append("]\n'").append(tagAsString(_baseScriptRecord[i].getBaseScriptTag())).append("'"); sb.append("\nBaseScriptT").append(Integer.toHexString(_thisOffset + _baseScriptRecord[i].getBaseScriptOffset())); } for (int i = 0; i < _baseScriptCount; ++i) { sb.append("\n").append(_baseScripts[i].toString()); } return sb.toString(); } } class BaseTagList { private final int _thisOffset; private final int _baseTagCount; private final int[] _baselineTag; protected BaseTagList(final int baseTagListOffset) throws IOException { _thisOffset = baseTagListOffset; final DataInput di = getDataInputForOffset(baseTagListOffset); _baseTagCount = di.readUnsignedShort(); _baselineTag = new int[_baseTagCount]; for (int i = 0; i < _baseTagCount; ++i) { _baselineTag[i] = di.readInt(); } } @Override public String toString() { final StringBuilder sb = new StringBuilder() .append("\nBaseTagList BaseTagListT").append(Integer.toHexString(_thisOffset)) .append("\n").append(Integer.toHexString(_baseTagCount)); for (int i = 0; i < _baseTagCount; ++i) { sb.append("\n'").append(tagAsString(_baselineTag[i])).append("'"); } return sb.toString(); } } class Axis { private final int _thisOffset; private final int _baseTagListOffset; private final int _baseScriptListOffset; private BaseTagList _baseTagList; private BaseScriptList _baseScriptList; protected Axis(final int axisOffset) throws IOException { _thisOffset = axisOffset; final DataInput di = getDataInputForOffset(axisOffset); _baseTagListOffset = di.readUnsignedShort(); _baseScriptListOffset = di.readUnsignedShort(); if (_baseTagListOffset != 0) { _baseTagList = new BaseTagList(axisOffset + _baseTagListOffset); } if (_baseScriptListOffset != 0) { _baseScriptList = new BaseScriptList( axisOffset + _baseScriptListOffset); } } @Override public String toString() { return new StringBuilder() .append("\nAxis AxisT").append(Integer.toHexString(_thisOffset)) .append("\nBaseTagListT").append(Integer.toHexString(_thisOffset + _baseTagListOffset)) .append("\nBaseScriptListT").append(Integer.toHexString(_thisOffset + _baseScriptListOffset)) .append("\n").append(_baseTagList) .append("\n").append(_baseScriptList) .toString(); } } private final DirectoryEntry _de; private final int _version; private final int _horizAxisOffset; private final int _vertAxisOffset; private Axis _horizAxis; private Axis _vertAxis; private byte[] _buf; /** Creates a new instance of BaseTable */ protected BaseTable(final DirectoryEntry de, final DataInput di) throws IOException { _de = (DirectoryEntry) de.clone(); // Load entire table into a buffer, and create another input stream _buf = new byte[de.getLength()]; di.readFully(_buf); final DataInput di2 = getDataInputForOffset(0); _version = di2.readInt(); _horizAxisOffset = di2.readUnsignedShort(); _vertAxisOffset = di2.readUnsignedShort(); if (_horizAxisOffset != 0) { _horizAxis = new Axis(_horizAxisOffset); } if (_vertAxisOffset != 0) { _vertAxis = new Axis(_vertAxisOffset); } // Let go of the buffer _buf = null; } private DataInput getDataInputForOffset(final int offset) { return new DataInputStream(new ByteArrayInputStream( _buf, offset, _de.getLength() - offset)); } // private String valueAsShortHex(int value) { // return String.format("%1$4x", value); // } // // private String valueAsLongHex(int value) { // return String.format("%1$8x", value); // } static protected String tagAsString(final int tag) { final char[] c = new char[4]; c[0] = (char)((tag >> 24) & 0xff); c[1] = (char)((tag >> 16) & 0xff); c[2] = (char)((tag >> 8) & 0xff); c[3] = (char)(tag & 0xff); return String.valueOf(c); } @Override public int getType() { return BASE; } @Override public String toString() { final StringBuilder sb = new StringBuilder() .append("; 'BASE' Table - Baseline\n;-------------------------------------\n\n") .append("BASEHeader BASEHeaderT").append(Integer.toHexString(0)) .append("\n").append(Integer.toHexString(_version)) .append("\nAxisT").append(Integer.toHexString(_horizAxisOffset)) .append("\nAxisT").append(Integer.toHexString(_vertAxisOffset)); if (_horizAxis != null) { sb.append("\n").append(_horizAxis.toString()); } if (_vertAxis != null) { sb.append("\n").append(_vertAxis.toString()); } return sb.toString(); } /** * Get a directory entry for this table. This uniquely identifies the * table in collections where there may be more than one instance of a * particular table. * @return A directory entry */ @Override public DirectoryEntry getDirectoryEntry() { return _de; } }