git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@776424 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_5_BETA6
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,10 +14,8 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.RecordFormatException; | |||
package org.apache.poi.ddf; | |||
import java.lang.reflect.Constructor; | |||
import java.util.HashMap; | |||
@@ -32,21 +29,19 @@ import java.util.Map; | |||
* | |||
* @see EscherRecordFactory | |||
*/ | |||
public class DefaultEscherRecordFactory | |||
implements EscherRecordFactory | |||
{ | |||
private static Class[] escherRecordClasses = { | |||
public class DefaultEscherRecordFactory implements EscherRecordFactory { | |||
private static Class<?>[] escherRecordClasses = { | |||
EscherBSERecord.class, EscherOptRecord.class, EscherClientAnchorRecord.class, EscherDgRecord.class, | |||
EscherSpgrRecord.class, EscherSpRecord.class, EscherClientDataRecord.class, EscherDggRecord.class, | |||
EscherSplitMenuColorsRecord.class, EscherChildAnchorRecord.class, EscherTextboxRecord.class | |||
}; | |||
private static Map recordsMap = recordsToMap( escherRecordClasses ); | |||
private static Map<Short, Constructor<? extends EscherRecord>> recordsMap = recordsToMap( escherRecordClasses ); | |||
/** | |||
* Creates an instance of the escher record factory | |||
*/ | |||
public DefaultEscherRecordFactory() | |||
{ | |||
public DefaultEscherRecordFactory() { | |||
// no instance initialisation | |||
} | |||
/** | |||
@@ -57,14 +52,13 @@ public class DefaultEscherRecordFactory | |||
* @param offset The starting offset into the byte array | |||
* @return The generated escher record | |||
*/ | |||
public EscherRecord createRecord( byte[] data, int offset ) | |||
{ | |||
public EscherRecord createRecord(byte[] data, int offset) { | |||
EscherRecord.EscherRecordHeader header = EscherRecord.EscherRecordHeader.readHeader( data, offset ); | |||
// Options of 0x000F means container record | |||
// However, EscherTextboxRecord are containers of records for the | |||
// host application, not of other Escher records, so treat them | |||
// differently | |||
// Options of 0x000F means container record | |||
// However, EscherTextboxRecord are containers of records for the | |||
// host application, not of other Escher records, so treat them | |||
// differently | |||
if ( ( header.getOptions() & (short) 0x000F ) == (short) 0x000F | |||
&& header.getRecordId() != EscherTextboxRecord.RECORD_ID ) { | |||
EscherContainerRecord r = new EscherContainerRecord(); | |||
@@ -72,8 +66,9 @@ public class DefaultEscherRecordFactory | |||
r.setOptions( header.getOptions() ); | |||
return r; | |||
} | |||
else if ( header.getRecordId() >= EscherBlipRecord.RECORD_ID_START && header.getRecordId() <= EscherBlipRecord.RECORD_ID_END ) | |||
{ | |||
if (header.getRecordId() >= EscherBlipRecord.RECORD_ID_START | |||
&& header.getRecordId() <= EscherBlipRecord.RECORD_ID_END) { | |||
EscherBlipRecord r; | |||
if (header.getRecordId() == EscherBitmapBlip.RECORD_ID_DIB || | |||
header.getRecordId() == EscherBitmapBlip.RECORD_ID_JPEG || | |||
@@ -86,70 +81,62 @@ public class DefaultEscherRecordFactory | |||
header.getRecordId() == EscherMetafileBlip.RECORD_ID_PICT) | |||
{ | |||
r = new EscherMetafileBlip(); | |||
} | |||
else | |||
{ | |||
} else { | |||
r = new EscherBlipRecord(); | |||
} | |||
r.setRecordId( header.getRecordId() ); | |||
r.setOptions( header.getOptions() ); | |||
return r; | |||
} | |||
else | |||
{ | |||
Constructor recordConstructor = (Constructor) recordsMap.get( new Short( header.getRecordId() ) ); | |||
EscherRecord escherRecord = null; | |||
if ( recordConstructor != null ) | |||
{ | |||
try | |||
{ | |||
escherRecord = (EscherRecord) recordConstructor.newInstance( new Object[]{} ); | |||
escherRecord.setRecordId( header.getRecordId() ); | |||
escherRecord.setOptions( header.getOptions() ); | |||
} | |||
catch ( Exception e ) | |||
{ | |||
escherRecord = null; | |||
} | |||
} | |||
return escherRecord == null ? new UnknownEscherRecord() : escherRecord; | |||
Constructor<? extends EscherRecord> recordConstructor = recordsMap.get(new Short(header.getRecordId())); | |||
EscherRecord escherRecord = null; | |||
if (recordConstructor == null) { | |||
return new UnknownEscherRecord(); | |||
} | |||
try { | |||
escherRecord = recordConstructor.newInstance(new Object[] {}); | |||
} catch (Exception e) { | |||
return new UnknownEscherRecord(); | |||
} | |||
escherRecord.setRecordId(header.getRecordId()); | |||
escherRecord.setOptions(header.getOptions()); | |||
return escherRecord; | |||
} | |||
/** | |||
* Converts from a list of classes into a map that contains the record id as the key and | |||
* the Constructor in the value part of the map. It does this by using reflection to look up | |||
* the RECORD_ID field then using reflection again to find a reference to the constructor. | |||
* | |||
* @param records The records to convert | |||
* | |||
* @param recClasses The records to convert | |||
* @return The map containing the id/constructor pairs. | |||
*/ | |||
private static Map recordsToMap( Class[] records ) | |||
{ | |||
Map result = new HashMap(); | |||
Constructor constructor; | |||
for ( int i = 0; i < records.length; i++ ) | |||
{ | |||
Class record = null; | |||
short sid = 0; | |||
private static Map<Short, Constructor<? extends EscherRecord>> recordsToMap(Class<?>[] recClasses) { | |||
Map<Short, Constructor<? extends EscherRecord>> result = new HashMap<Short, Constructor<? extends EscherRecord>>(); | |||
final Class<?>[] EMPTY_CLASS_ARRAY = new Class[0]; | |||
record = records[i]; | |||
try | |||
{ | |||
sid = record.getField( "RECORD_ID" ).getShort( null ); | |||
constructor = record.getConstructor( new Class[] | |||
{ | |||
} ); | |||
for (int i = 0; i < recClasses.length; i++) { | |||
@SuppressWarnings("unchecked") | |||
Class<? extends EscherRecord> recCls = (Class<? extends EscherRecord>) recClasses[i]; | |||
short sid; | |||
try { | |||
sid = recCls.getField("RECORD_ID").getShort(null); | |||
} catch (IllegalArgumentException e) { | |||
throw new RuntimeException(e); | |||
} catch (IllegalAccessException e) { | |||
throw new RuntimeException(e); | |||
} catch (NoSuchFieldException e) { | |||
throw new RuntimeException(e); | |||
} | |||
catch ( Exception illegalArgumentException ) | |||
{ | |||
throw new RecordFormatException( | |||
"Unable to determine record types" ); | |||
Constructor<? extends EscherRecord> constructor; | |||
try { | |||
constructor = recCls.getConstructor( EMPTY_CLASS_ARRAY ); | |||
} catch (NoSuchMethodException e) { | |||
throw new RuntimeException(e); | |||
} | |||
result.put( new Short( sid ), constructor ); | |||
result.put(new Short(sid), constructor); | |||
} | |||
return result; | |||
} | |||
} |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,7 +14,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.LittleEndian; | |||
@@ -27,13 +26,11 @@ import org.apache.poi.util.HexDump; | |||
* | |||
* @author Glen Stampoultzis (glens at superlinksoftware.com) | |||
*/ | |||
public class EscherArrayProperty | |||
extends EscherComplexProperty | |||
{ | |||
/** | |||
* The size of the header that goes at the | |||
* start of the array, before the data | |||
*/ | |||
public final class EscherArrayProperty extends EscherComplexProperty { | |||
/** | |||
* The size of the header that goes at the | |||
* start of the array, before the data | |||
*/ | |||
private static final int FIXED_SIZE = 3 * 2; | |||
/** | |||
* Normally, the size recorded in the simple data (for the complex | |||
@@ -47,112 +44,95 @@ public class EscherArrayProperty | |||
*/ | |||
private boolean emptyComplexPart = false; | |||
public EscherArrayProperty( short id, byte[] complexData ) | |||
{ | |||
super( id, checkComplexData(complexData) ); | |||
public EscherArrayProperty(short id, byte[] complexData) { | |||
super(id, checkComplexData(complexData)); | |||
emptyComplexPart = complexData.length == 0; | |||
} | |||
public EscherArrayProperty( short propertyNumber, boolean isBlipId, byte[] complexData ) | |||
{ | |||
super( propertyNumber, isBlipId, checkComplexData(complexData) ); | |||
public EscherArrayProperty(short propertyNumber, boolean isBlipId, byte[] complexData) { | |||
super(propertyNumber, isBlipId, checkComplexData(complexData)); | |||
} | |||
private static byte[] checkComplexData( byte[] complexData ) | |||
{ | |||
if (complexData == null || complexData.length == 0) | |||
complexData = new byte[6]; | |||
private static byte[] checkComplexData(byte[] complexData) { | |||
if (complexData == null || complexData.length == 0) { | |||
return new byte[6]; | |||
} | |||
return complexData; | |||
} | |||
public int getNumberOfElementsInArray() | |||
{ | |||
return LittleEndian.getUShort( complexData, 0 ); | |||
public int getNumberOfElementsInArray() { | |||
return LittleEndian.getUShort(_complexData, 0); | |||
} | |||
public void setNumberOfElementsInArray( int numberOfElements ) | |||
{ | |||
public void setNumberOfElementsInArray(int numberOfElements) { | |||
int expectedArraySize = numberOfElements * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE; | |||
if ( expectedArraySize != complexData.length ) | |||
{ | |||
if (expectedArraySize != _complexData.length) { | |||
byte[] newArray = new byte[expectedArraySize]; | |||
System.arraycopy( complexData, 0, newArray, 0, complexData.length ); | |||
complexData = newArray; | |||
System.arraycopy(_complexData, 0, newArray, 0, _complexData.length); | |||
_complexData = newArray; | |||
} | |||
LittleEndian.putShort( complexData, 0, (short) numberOfElements ); | |||
LittleEndian.putShort(_complexData, 0, (short) numberOfElements); | |||
} | |||
public int getNumberOfElementsInMemory() | |||
{ | |||
return LittleEndian.getUShort( complexData, 2 ); | |||
public int getNumberOfElementsInMemory() { | |||
return LittleEndian.getUShort(_complexData, 2); | |||
} | |||
public void setNumberOfElementsInMemory( int numberOfElements ) | |||
{ | |||
public void setNumberOfElementsInMemory(int numberOfElements) { | |||
int expectedArraySize = numberOfElements * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE; | |||
if ( expectedArraySize != complexData.length ) | |||
{ | |||
if (expectedArraySize != _complexData.length) { | |||
byte[] newArray = new byte[expectedArraySize]; | |||
System.arraycopy( complexData, 0, newArray, 0, expectedArraySize ); | |||
complexData = newArray; | |||
System.arraycopy(_complexData, 0, newArray, 0, expectedArraySize); | |||
_complexData = newArray; | |||
} | |||
LittleEndian.putShort( complexData, 2, (short) numberOfElements ); | |||
LittleEndian.putShort(_complexData, 2, (short) numberOfElements); | |||
} | |||
public short getSizeOfElements() | |||
{ | |||
return LittleEndian.getShort( complexData, 4 ); | |||
public short getSizeOfElements() { | |||
return LittleEndian.getShort( _complexData, 4 ); | |||
} | |||
public void setSizeOfElements( int sizeOfElements ) | |||
{ | |||
LittleEndian.putShort( complexData, 4, (short) sizeOfElements ); | |||
public void setSizeOfElements(int sizeOfElements) { | |||
LittleEndian.putShort( _complexData, 4, (short) sizeOfElements ); | |||
int expectedArraySize = getNumberOfElementsInArray() * getActualSizeOfElements(getSizeOfElements()) + FIXED_SIZE; | |||
if ( expectedArraySize != complexData.length ) | |||
{ | |||
if (expectedArraySize != _complexData.length) { | |||
// Keep just the first 6 bytes. The rest is no good to us anyway. | |||
byte[] newArray = new byte[expectedArraySize]; | |||
System.arraycopy( complexData, 0, newArray, 0, 6 ); | |||
complexData = newArray; | |||
System.arraycopy( _complexData, 0, newArray, 0, 6 ); | |||
_complexData = newArray; | |||
} | |||
} | |||
public byte[] getElement( int index ) | |||
{ | |||
public byte[] getElement(int index) { | |||
int actualSize = getActualSizeOfElements(getSizeOfElements()); | |||
byte[] result = new byte[actualSize]; | |||
System.arraycopy(complexData, FIXED_SIZE + index * actualSize, result, 0, result.length ); | |||
System.arraycopy(_complexData, FIXED_SIZE + index * actualSize, result, 0, result.length ); | |||
return result; | |||
} | |||
public void setElement( int index, byte[] element ) | |||
{ | |||
public void setElement(int index, byte[] element) { | |||
int actualSize = getActualSizeOfElements(getSizeOfElements()); | |||
System.arraycopy( element, 0, complexData, FIXED_SIZE + index * actualSize, actualSize); | |||
System.arraycopy( element, 0, _complexData, FIXED_SIZE + index * actualSize, actualSize); | |||
} | |||
public String toString() | |||
{ | |||
String nl = System.getProperty("line.separator"); | |||
public String toString() { | |||
StringBuffer results = new StringBuffer(); | |||
results.append(" {EscherArrayProperty:" + nl); | |||
results.append(" Num Elements: " + getNumberOfElementsInArray() + nl); | |||
results.append(" Num Elements In Memory: " + getNumberOfElementsInMemory() + nl); | |||
results.append(" Size of elements: " + getSizeOfElements() + nl); | |||
for (int i = 0; i < getNumberOfElementsInArray(); i++) | |||
{ | |||
results.append(" Element " + i + ": " + HexDump.toHex(getElement(i)) + nl); | |||
results.append(" {EscherArrayProperty:" + '\n'); | |||
results.append(" Num Elements: " + getNumberOfElementsInArray() + '\n'); | |||
results.append(" Num Elements In Memory: " + getNumberOfElementsInMemory() + '\n'); | |||
results.append(" Size of elements: " + getSizeOfElements() + '\n'); | |||
for (int i = 0; i < getNumberOfElementsInArray(); i++) { | |||
results.append(" Element " + i + ": " + HexDump.toHex(getElement(i)) + '\n'); | |||
} | |||
results.append("}" + nl); | |||
results.append("}" + '\n'); | |||
return "propNum: " + getPropertyNumber() | |||
+ ", propName: " + EscherProperties.getPropertyName( getPropertyNumber() ) | |||
+ ", complex: " + isComplex() | |||
+ ", blipId: " + isBlipId() | |||
+ ", data: " + nl + results.toString(); | |||
+ ", data: " + '\n' + results.toString(); | |||
} | |||
/** | |||
@@ -165,38 +145,36 @@ public class EscherArrayProperty | |||
* @param offset The offset into the array to start reading from. | |||
* @return the number of bytes used by this complex property. | |||
*/ | |||
public int setArrayData( byte[] data, int offset ) | |||
{ | |||
public int setArrayData(byte[] data, int offset) { | |||
if (emptyComplexPart){ | |||
complexData = new byte[0]; | |||
_complexData = new byte[0]; | |||
} else { | |||
short numElements = LittleEndian.getShort(data, offset); | |||
short numReserved = LittleEndian.getShort(data, offset + 2); | |||
LittleEndian.getShort(data, offset + 2); // numReserved | |||
short sizeOfElements = LittleEndian.getShort(data, offset + 4); | |||
int arraySize = getActualSizeOfElements(sizeOfElements) * numElements; | |||
if (arraySize == complexData.length) { | |||
if (arraySize == _complexData.length) { | |||
// The stored data size in the simple block excludes the header size | |||
complexData = new byte[arraySize + 6]; | |||
_complexData = new byte[arraySize + 6]; | |||
sizeIncludesHeaderSize = false; | |||
} | |||
System.arraycopy(data, offset, complexData, 0, complexData.length ); | |||
System.arraycopy(data, offset, _complexData, 0, _complexData.length ); | |||
} | |||
return complexData.length; | |||
return _complexData.length; | |||
} | |||
/** | |||
* Serializes the simple part of this property. ie the first 6 bytes. | |||
* | |||
* Needs special code to handle the case when the size doesn't | |||
* | |||
* Needs special code to handle the case when the size doesn't | |||
* include the size of the header block | |||
*/ | |||
public int serializeSimplePart( byte[] data, int pos ) | |||
{ | |||
public int serializeSimplePart(byte[] data, int pos) { | |||
LittleEndian.putShort(data, pos, getId()); | |||
int recordSize = complexData.length; | |||
int recordSize = _complexData.length; | |||
if(!sizeIncludesHeaderSize) { | |||
recordSize -= 6; | |||
recordSize -= 6; | |||
} | |||
LittleEndian.putInt(data, pos + 2, recordSize); | |||
return 6; | |||
@@ -206,12 +184,10 @@ public class EscherArrayProperty | |||
* Sometimes the element size is stored as a negative number. We | |||
* negate it and shift it to get the real value. | |||
*/ | |||
public static int getActualSizeOfElements(short sizeOfElements) | |||
{ | |||
if (sizeOfElements < 0) | |||
public static int getActualSizeOfElements(short sizeOfElements) { | |||
if (sizeOfElements < 0) { | |||
return (short) ( ( -sizeOfElements ) >> 2 ); | |||
else | |||
return sizeOfElements; | |||
} | |||
return sizeOfElements; | |||
} | |||
} |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,14 +14,12 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndian; | |||
import java.io.ByteArrayOutputStream; | |||
/** | |||
* The BSE record is related closely to the <code>EscherBlipRecord</code> and stores | |||
* extra information about the blip. A blip record is actually stored inside | |||
@@ -31,9 +28,7 @@ import java.io.ByteArrayOutputStream; | |||
* @author Glen Stampoultzis | |||
* @see EscherBlipRecord | |||
*/ | |||
public class EscherBSERecord | |||
extends EscherRecord | |||
{ | |||
public final class EscherBSERecord extends EscherRecord { | |||
public static final short RECORD_ID = (short) 0xF007; | |||
public static final String RECORD_DESCRIPTION = "MsofbtBSE"; | |||
@@ -59,20 +54,9 @@ public class EscherBSERecord | |||
private byte field_11_unused3; | |||
private EscherBlipRecord field_12_blipRecord; | |||
private byte[] remainingData; | |||
private byte[] _remainingData; | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, | |||
EscherRecordFactory recordFactory | |||
) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
field_1_blipTypeWin32 = data[pos]; | |||
@@ -87,53 +71,33 @@ public class EscherBSERecord | |||
field_10_unused2 = data[pos + 34]; | |||
field_11_unused3 = data[pos + 35]; | |||
bytesRemaining -= 36; | |||
int bytesRead = 0; | |||
if (bytesRemaining > 0) { | |||
// Some older escher formats skip this last record | |||
// Some older escher formats skip this last record | |||
field_12_blipRecord = (EscherBlipRecord) recordFactory.createRecord( data, pos + 36 ); | |||
bytesRead = field_12_blipRecord.fillFields( data, pos + 36, recordFactory ); | |||
} | |||
pos += 36 + bytesRead; | |||
bytesRemaining -= bytesRead; | |||
// if (field_1_blipTypeWin32 == BT_PNG) | |||
// { | |||
// byte[] uid = new byte[16]; | |||
// System.arraycopy( data, pos + 36, uid, 0, 16 ); | |||
// byte[] puid = new byte[16]; | |||
// System.arraycopy( data, pos + 52, puid, 0, 16 ); | |||
// byte tag = data[pos+68]; | |||
// System.out.println( HexDump.dump( data, 0, 0 ) ); | |||
// byte[] pngBytes = EscherBlipRecord.decompress( data, pos+69, bytesRemaining); | |||
// } | |||
remainingData = new byte[bytesRemaining]; | |||
System.arraycopy( data, pos, remainingData, 0, bytesRemaining ); | |||
_remainingData = new byte[bytesRemaining]; | |||
System.arraycopy( data, pos, _remainingData, 0, bytesRemaining ); | |||
return bytesRemaining + 8 + 36 + (field_12_blipRecord == null ? 0 : field_12_blipRecord.getRecordSize()) ; | |||
} | |||
/** | |||
* This method serializes this escher record into a byte array. | |||
* | |||
* @param offset The offset into <code>data</code> to start writing the record data to. | |||
* @param data The byte array to serialize to. | |||
* @param listener A listener to retrieve start and end callbacks. Use a <code>NullEscherSerailizationListener</code> to ignore these events. | |||
* @return The number of bytes written. | |||
* @see NullEscherSerializationListener | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
if (remainingData == null) | |||
remainingData = new byte[0]; | |||
if (_remainingData == null) | |||
_remainingData = new byte[0]; | |||
LittleEndian.putShort( data, offset, getOptions() ); | |||
LittleEndian.putShort( data, offset + 2, getRecordId() ); | |||
if (remainingData == null) remainingData = new byte[0]; | |||
if (_remainingData == null) _remainingData = new byte[0]; | |||
int blipSize = field_12_blipRecord == null ? 0 : field_12_blipRecord.getRecordSize(); | |||
int remainingBytes = remainingData.length + 36 + blipSize; | |||
int remainingBytes = _remainingData.length + 36 + blipSize; | |||
LittleEndian.putInt( data, offset + 4, remainingBytes ); | |||
data[offset + 8] = field_1_blipTypeWin32; | |||
@@ -153,39 +117,29 @@ public class EscherBSERecord | |||
{ | |||
bytesWritten = field_12_blipRecord.serialize( offset + 44, data, new NullEscherSerializationListener() ); | |||
} | |||
if (remainingData == null) | |||
remainingData = new byte[0]; | |||
System.arraycopy( remainingData, 0, data, offset + 44 + bytesWritten, remainingData.length ); | |||
int pos = offset + 8 + 36 + remainingData.length + bytesWritten; | |||
if (_remainingData == null) | |||
_remainingData = new byte[0]; | |||
System.arraycopy( _remainingData, 0, data, offset + 44 + bytesWritten, _remainingData.length ); | |||
int pos = offset + 8 + 36 + _remainingData.length + bytesWritten; | |||
listener.afterRecordSerialize(pos, getRecordId(), pos - offset, this); | |||
return pos - offset; | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
int field_12_size = 0; | |||
if(field_12_blipRecord != null) { | |||
field_12_size = field_12_blipRecord.getRecordSize(); | |||
} | |||
int remaining_size = 0; | |||
if(remainingData != null) { | |||
remaining_size = remainingData.length; | |||
} | |||
public int getRecordSize() { | |||
int field_12_size = 0; | |||
if(field_12_blipRecord != null) { | |||
field_12_size = field_12_blipRecord.getRecordSize(); | |||
} | |||
int remaining_size = 0; | |||
if(_remainingData != null) { | |||
remaining_size = _remainingData.length; | |||
} | |||
return 8 + 1 + 1 + 16 + 2 + 4 + 4 + 4 + 1 + 1 + | |||
1 + 1 + field_12_size + remaining_size; | |||
} | |||
/** | |||
* The short name for this record | |||
*/ | |||
public String getRecordName() | |||
{ | |||
public String getRecordName() { | |||
return "BSE"; | |||
} | |||
@@ -193,260 +147,205 @@ public class EscherBSERecord | |||
* The expected blip type under windows (failure to match this blip type will result in | |||
* Excel converting to this format). | |||
*/ | |||
public byte getBlipTypeWin32() | |||
{ | |||
public byte getBlipTypeWin32() { | |||
return field_1_blipTypeWin32; | |||
} | |||
/** | |||
* Set the expected win32 blip type | |||
*/ | |||
public void setBlipTypeWin32( byte blipTypeWin32 ) | |||
{ | |||
this.field_1_blipTypeWin32 = blipTypeWin32; | |||
public void setBlipTypeWin32(byte blipTypeWin32) { | |||
field_1_blipTypeWin32 = blipTypeWin32; | |||
} | |||
/** | |||
* The expected blip type under MacOS (failure to match this blip type will result in | |||
* Excel converting to this format). | |||
*/ | |||
public byte getBlipTypeMacOS() | |||
{ | |||
public byte getBlipTypeMacOS() { | |||
return field_2_blipTypeMacOS; | |||
} | |||
/** | |||
* Set the expected MacOS blip type | |||
*/ | |||
public void setBlipTypeMacOS( byte blipTypeMacOS ) | |||
{ | |||
this.field_2_blipTypeMacOS = blipTypeMacOS; | |||
public void setBlipTypeMacOS(byte blipTypeMacOS) { | |||
field_2_blipTypeMacOS = blipTypeMacOS; | |||
} | |||
/** | |||
* 16 byte MD4 checksum. | |||
*/ | |||
public byte[] getUid() | |||
{ | |||
public byte[] getUid() { | |||
return field_3_uid; | |||
} | |||
/** | |||
* 16 byte MD4 checksum. | |||
*/ | |||
public void setUid( byte[] uid ) | |||
{ | |||
this.field_3_uid = uid; | |||
public void setUid(byte[] uid) { | |||
field_3_uid = uid; | |||
} | |||
/** | |||
* unused | |||
*/ | |||
public short getTag() | |||
{ | |||
public short getTag() { | |||
return field_4_tag; | |||
} | |||
/** | |||
* unused | |||
*/ | |||
public void setTag( short tag ) | |||
{ | |||
this.field_4_tag = tag; | |||
public void setTag(short tag) { | |||
field_4_tag = tag; | |||
} | |||
/** | |||
* Blip size in stream. | |||
*/ | |||
public int getSize() | |||
{ | |||
public int getSize() { | |||
return field_5_size; | |||
} | |||
/** | |||
* Blip size in stream. | |||
*/ | |||
public void setSize( int size ) | |||
{ | |||
this.field_5_size = size; | |||
public void setSize(int size) { | |||
field_5_size = size; | |||
} | |||
/** | |||
* The reference count of this blip. | |||
*/ | |||
public int getRef() | |||
{ | |||
public int getRef() { | |||
return field_6_ref; | |||
} | |||
/** | |||
* The reference count of this blip. | |||
*/ | |||
public void setRef( int ref ) | |||
{ | |||
this.field_6_ref = ref; | |||
public void setRef(int ref) { | |||
field_6_ref = ref; | |||
} | |||
/** | |||
* File offset in the delay stream. | |||
*/ | |||
public int getOffset() | |||
{ | |||
public int getOffset() { | |||
return field_7_offset; | |||
} | |||
/** | |||
* File offset in the delay stream. | |||
*/ | |||
public void setOffset( int offset ) | |||
{ | |||
this.field_7_offset = offset; | |||
public void setOffset(int offset) { | |||
field_7_offset = offset; | |||
} | |||
/** | |||
* Defines the way this blip is used. | |||
*/ | |||
public byte getUsage() | |||
{ | |||
public byte getUsage() { | |||
return field_8_usage; | |||
} | |||
/** | |||
* Defines the way this blip is used. | |||
*/ | |||
public void setUsage( byte usage ) | |||
{ | |||
this.field_8_usage = usage; | |||
public void setUsage(byte usage) { | |||
field_8_usage = usage; | |||
} | |||
/** | |||
* The length in characters of the blip name. | |||
*/ | |||
public byte getName() | |||
{ | |||
public byte getName() { | |||
return field_9_name; | |||
} | |||
/** | |||
* The length in characters of the blip name. | |||
*/ | |||
public void setName( byte name ) | |||
{ | |||
this.field_9_name = name; | |||
public void setName(byte name) { | |||
field_9_name = name; | |||
} | |||
public byte getUnused2() | |||
{ | |||
public byte getUnused2() { | |||
return field_10_unused2; | |||
} | |||
public void setUnused2( byte unused2 ) | |||
{ | |||
this.field_10_unused2 = unused2; | |||
public void setUnused2(byte unused2) { | |||
field_10_unused2 = unused2; | |||
} | |||
public byte getUnused3() | |||
{ | |||
public byte getUnused3() { | |||
return field_11_unused3; | |||
} | |||
public void setUnused3( byte unused3 ) | |||
{ | |||
this.field_11_unused3 = unused3; | |||
public void setUnused3(byte unused3) { | |||
field_11_unused3 = unused3; | |||
} | |||
public EscherBlipRecord getBlipRecord() | |||
{ | |||
public EscherBlipRecord getBlipRecord() { | |||
return field_12_blipRecord; | |||
} | |||
public void setBlipRecord( EscherBlipRecord field_12_blipRecord ) | |||
{ | |||
this.field_12_blipRecord = field_12_blipRecord; | |||
public void setBlipRecord(EscherBlipRecord blipRecord) { | |||
field_12_blipRecord = blipRecord; | |||
} | |||
/** | |||
* Any remaining data in this record. | |||
*/ | |||
public byte[] getRemainingData() | |||
{ | |||
return remainingData; | |||
public byte[] getRemainingData() { | |||
return _remainingData; | |||
} | |||
/** | |||
* Any remaining data in this record. | |||
*/ | |||
public void setRemainingData( byte[] remainingData ) | |||
{ | |||
this.remainingData = remainingData; | |||
} | |||
/** | |||
* Calculate the string representation of this object | |||
*/ | |||
public String toString() | |||
{ | |||
String nl = System.getProperty( "line.separator" ); | |||
String extraData; | |||
ByteArrayOutputStream b = new ByteArrayOutputStream(); | |||
try | |||
{ | |||
HexDump.dump( this.remainingData, 0, b, 0 ); | |||
extraData = b.toString(); | |||
} | |||
catch ( Exception e ) | |||
{ | |||
extraData = e.toString(); | |||
} | |||
return getClass().getName() + ":" + nl + | |||
" RecordId: 0x" + HexDump.toHex( RECORD_ID ) + nl + | |||
" Options: 0x" + HexDump.toHex( getOptions() ) + nl + | |||
" BlipTypeWin32: " + field_1_blipTypeWin32 + nl + | |||
" BlipTypeMacOS: " + field_2_blipTypeMacOS + nl + | |||
" SUID: " + HexDump.toHex(field_3_uid) + nl + | |||
" Tag: " + field_4_tag + nl + | |||
" Size: " + field_5_size + nl + | |||
" Ref: " + field_6_ref + nl + | |||
" Offset: " + field_7_offset + nl + | |||
" Usage: " + field_8_usage + nl + | |||
" Name: " + field_9_name + nl + | |||
" Unused2: " + field_10_unused2 + nl + | |||
" Unused3: " + field_11_unused3 + nl + | |||
" blipRecord: " + field_12_blipRecord + nl + | |||
" Extra Data:" + nl + extraData; | |||
public void setRemainingData(byte[] remainingData) { | |||
_remainingData = remainingData; | |||
} | |||
public String toString() { | |||
String extraData = HexDump.toHex(_remainingData, 32); | |||
return getClass().getName() + ":" + '\n' + | |||
" RecordId: 0x" + HexDump.toHex( RECORD_ID ) + '\n' + | |||
" Options: 0x" + HexDump.toHex( getOptions() ) + '\n' + | |||
" BlipTypeWin32: " + field_1_blipTypeWin32 + '\n' + | |||
" BlipTypeMacOS: " + field_2_blipTypeMacOS + '\n' + | |||
" SUID: " + HexDump.toHex(field_3_uid) + '\n' + | |||
" Tag: " + field_4_tag + '\n' + | |||
" Size: " + field_5_size + '\n' + | |||
" Ref: " + field_6_ref + '\n' + | |||
" Offset: " + field_7_offset + '\n' + | |||
" Usage: " + field_8_usage + '\n' + | |||
" Name: " + field_9_name + '\n' + | |||
" Unused2: " + field_10_unused2 + '\n' + | |||
" Unused3: " + field_11_unused3 + '\n' + | |||
" blipRecord: " + field_12_blipRecord + '\n' + | |||
" Extra Data:" + '\n' + extraData; | |||
} | |||
/** | |||
* Retrieve the string representation given a blip id. | |||
*/ | |||
public String getBlipType( byte b ) | |||
{ | |||
switch ( b ) | |||
{ | |||
case BT_ERROR: | |||
return " ERROR"; | |||
case BT_UNKNOWN: | |||
return " UNKNOWN"; | |||
case BT_EMF: | |||
return " EMF"; | |||
case BT_WMF: | |||
return " WMF"; | |||
case BT_PICT: | |||
return " PICT"; | |||
case BT_JPEG: | |||
return " JPEG"; | |||
case BT_PNG: | |||
return " PNG"; | |||
case BT_DIB: | |||
return " DIB"; | |||
default: | |||
if ( b < 32 ) | |||
return " NotKnown"; | |||
else | |||
return " Client"; | |||
public static String getBlipType(byte b) { | |||
switch (b) { | |||
case BT_ERROR: return " ERROR"; | |||
case BT_UNKNOWN: return " UNKNOWN"; | |||
case BT_EMF: return " EMF"; | |||
case BT_WMF: return " WMF"; | |||
case BT_PICT: return " PICT"; | |||
case BT_JPEG: return " JPEG"; | |||
case BT_PNG: return " PNG"; | |||
case BT_DIB: return " DIB"; | |||
} | |||
if ( b < 32 ) { | |||
return " NotKnown"; | |||
} | |||
return " Client"; | |||
} | |||
} |
@@ -25,9 +25,7 @@ import java.io.ByteArrayOutputStream; | |||
* @author Glen Stampoultzis | |||
* @version $Id$ | |||
*/ | |||
public class EscherBitmapBlip | |||
extends EscherBlipRecord | |||
{ | |||
public class EscherBitmapBlip extends EscherBlipRecord { | |||
public static final short RECORD_ID_JPEG = (short) 0xF018 + 5; | |||
public static final short RECORD_ID_PNG = (short) 0xF018 + 6; | |||
public static final short RECORD_ID_DIB = (short) 0xF018 + 7; | |||
@@ -37,17 +35,7 @@ public class EscherBitmapBlip | |||
private byte[] field_1_UID; | |||
private byte field_2_marker = (byte) 0xFF; | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesAfterHeader = readHeader( data, offset ); | |||
int pos = offset + HEADER_SIZE; | |||
@@ -61,17 +49,6 @@ public class EscherBitmapBlip | |||
return bytesAfterHeader + HEADER_SIZE; | |||
} | |||
/** | |||
* Serializes the record to an existing byte array. | |||
* | |||
* @param offset the offset within the byte array | |||
* @param data the data array to serialize to | |||
* @param listener a listener for begin and end serialization events. This | |||
* is useful because the serialization is | |||
* hierarchical/recursive and sometimes you need to be able | |||
* break into that. | |||
* @return the number of bytes written. | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
listener.beforeRecordSerialize(offset, getRecordId(), this); | |||
@@ -89,11 +66,6 @@ public class EscherBitmapBlip | |||
return HEADER_SIZE + 16 + 1 + field_pictureData.length; | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
return 8 + 16 + 1 + field_pictureData.length; | |||
@@ -141,5 +113,4 @@ public class EscherBitmapBlip | |||
" Marker: 0x" + HexDump.toHex( field_2_marker ) + nl + | |||
" Extra Data:" + nl + extraData; | |||
} | |||
} |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,21 +14,16 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.HexDump; | |||
import java.io.ByteArrayOutputStream; | |||
/** | |||
* @author Glen Stampoultzis | |||
* @version $Id$ | |||
*/ | |||
public class EscherBlipRecord | |||
extends EscherRecord | |||
{ | |||
public class EscherBlipRecord extends EscherRecord { // TODO - instantiable superclass | |||
public static final short RECORD_ID_START = (short) 0xF018; | |||
public static final short RECORD_ID_END = (short) 0xF117; | |||
public static final String RECORD_DESCRIPTION = "msofbtBlip"; | |||
@@ -38,20 +32,10 @@ public class EscherBlipRecord | |||
protected byte[] field_pictureData; | |||
public EscherBlipRecord() | |||
{ | |||
public EscherBlipRecord() { | |||
} | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesAfterHeader = readHeader( data, offset ); | |||
int pos = offset + HEADER_SIZE; | |||
@@ -61,19 +45,7 @@ public class EscherBlipRecord | |||
return bytesAfterHeader + 8; | |||
} | |||
/** | |||
* Serializes the record to an existing byte array. | |||
* | |||
* @param offset the offset within the byte array | |||
* @param data the data array to serialize to | |||
* @param listener a listener for begin and end serialization events. This | |||
* is useful because the serialization is | |||
* hierarchical/recursive and sometimes you need to be able | |||
* break into that. | |||
* @return the number of bytes written. | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize(offset, getRecordId(), this); | |||
LittleEndian.putShort( data, offset, getOptions() ); | |||
@@ -85,53 +57,27 @@ public class EscherBlipRecord | |||
return field_pictureData.length + 4; | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
public int getRecordSize() { | |||
return field_pictureData.length + HEADER_SIZE; | |||
} | |||
/** | |||
* The short name for this record | |||
*/ | |||
public String getRecordName() | |||
{ | |||
public String getRecordName() { | |||
return "Blip"; | |||
} | |||
public byte[] getPicturedata() | |||
{ | |||
public byte[] getPicturedata() { | |||
return field_pictureData; | |||
} | |||
public void setPictureData(byte[] pictureData) | |||
{ | |||
public void setPictureData(byte[] pictureData) { | |||
field_pictureData = pictureData; | |||
} | |||
public String toString() | |||
{ | |||
String nl = System.getProperty( "line.separator" ); | |||
String extraData; | |||
ByteArrayOutputStream b = new ByteArrayOutputStream(); | |||
try | |||
{ | |||
HexDump.dump( this.field_pictureData, 0, b, 0 ); | |||
extraData = b.toString(); | |||
} | |||
catch ( Exception e ) | |||
{ | |||
extraData = e.toString(); | |||
} | |||
return getClass().getName() + ":" + nl + | |||
" RecordId: 0x" + HexDump.toHex( getRecordId() ) + nl + | |||
" Options: 0x" + HexDump.toHex( getOptions() ) + nl + | |||
" Extra Data:" + nl + extraData; | |||
public String toString() { | |||
String extraData = HexDump.toHex(field_pictureData, 32); | |||
return getClass().getName() + ":" + '\n' + | |||
" RecordId: 0x" + HexDump.toHex( getRecordId() ) + '\n' + | |||
" Options: 0x" + HexDump.toHex( getOptions() ) + '\n' + | |||
" Extra Data:" + '\n' + extraData; | |||
} | |||
} |
@@ -15,7 +15,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.HexDump; | |||
@@ -58,19 +58,7 @@ public class EscherBlipWMFRecord | |||
private byte field_11_filter; | |||
private byte[] field_12_data; | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, | |||
EscherRecordFactory recordFactory | |||
) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesAfterHeader = readHeader( data, offset ); | |||
int pos = offset + HEADER_SIZE; | |||
@@ -96,17 +84,6 @@ public class EscherBlipWMFRecord | |||
return HEADER_SIZE + size; | |||
} | |||
/** | |||
* This method serializes this escher record into a byte array. | |||
* | |||
* @param offset The offset into <code>data</code> to start writing the record data to. | |||
* @param data The byte array to serialize to. | |||
* @param listener A listener to retrieve start and end callbacks. Use a <code>NullEscherSerailizationListener</code> to ignore these events. | |||
* @return The number of bytes written. | |||
* | |||
* @see NullEscherSerializationListener | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
listener.beforeRecordSerialize(offset, getRecordId(), this); | |||
@@ -134,21 +111,12 @@ public class EscherBlipWMFRecord | |||
return pos - offset; | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
return 58 + field_12_data.length; | |||
} | |||
/** | |||
* The short name for this record | |||
*/ | |||
public String getRecordName() | |||
{ | |||
public String getRecordName() { | |||
return "Blip"; | |||
} | |||
@@ -15,7 +15,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
/** |
@@ -15,7 +15,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.HexDump; | |||
@@ -39,16 +39,7 @@ public class EscherChildAnchorRecord | |||
private int field_3_dx2; | |||
private int field_4_dy2; | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
int size = 0; | |||
@@ -59,17 +50,7 @@ public class EscherChildAnchorRecord | |||
return 8 + size; | |||
} | |||
/** | |||
* This method serializes this escher record into a byte array. | |||
* | |||
* @param offset The offset into <code>data</code> to start writing the record data to. | |||
* @param data The byte array to serialize to. | |||
* @param listener A listener to retrieve start and end callbacks. Use a <code>NullEscherSerailizationListener</code> to ignore these events. | |||
* @return The number of bytes written. | |||
* @see NullEscherSerializationListener | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
int pos = offset; | |||
LittleEndian.putShort( data, pos, getOptions() ); pos += 2; | |||
@@ -84,32 +65,20 @@ public class EscherChildAnchorRecord | |||
return pos - offset; | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
return 8 + 4 * 4; | |||
} | |||
/** | |||
* The record id for the EscherChildAnchorRecord. | |||
*/ | |||
public short getRecordId() | |||
{ | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
/** | |||
* The short name for this record | |||
*/ | |||
public String getRecordName() | |||
{ | |||
public String getRecordName() { | |||
return "ChildAnchor"; | |||
} | |||
/** | |||
* The string representation of this record | |||
*/ |
@@ -15,7 +15,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.HexDump; | |||
@@ -50,16 +50,7 @@ public class EscherClientAnchorRecord | |||
private byte[] remainingData; | |||
private boolean shortRecord = false; | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
int size = 0; | |||
@@ -92,15 +83,6 @@ public class EscherClientAnchorRecord | |||
return 8 + size + bytesRemaining; | |||
} | |||
/** | |||
* This method serializes this escher record into a byte array. | |||
* | |||
* @param offset The offset into <code>data</code> to start writing the record data to. | |||
* @param data The byte array to serialize to. | |||
* @param listener A listener to retrieve start and end callbacks. Use a <code>NullEscherSerailizationListener</code> to ignore these events. | |||
* @return The number of bytes written. | |||
* @see NullEscherSerializationListener | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -128,29 +110,16 @@ public class EscherClientAnchorRecord | |||
return pos - offset; | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
return 8 + (shortRecord ? 8 : 18) + (remainingData == null ? 0 : remainingData.length); | |||
} | |||
/** | |||
* The record id for this record. | |||
*/ | |||
public short getRecordId() | |||
{ | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
/** | |||
* The short name for this record | |||
*/ | |||
public String getRecordName() | |||
{ | |||
public String getRecordName() { | |||
return "ClientAnchor"; | |||
} | |||
@@ -15,7 +15,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.HexDump; | |||
@@ -37,16 +37,7 @@ public class EscherClientDataRecord | |||
private byte[] remainingData; | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
remainingData = new byte[bytesRemaining]; | |||
@@ -54,17 +45,7 @@ public class EscherClientDataRecord | |||
return 8 + bytesRemaining; | |||
} | |||
/** | |||
* This method serializes this escher record into a byte array. | |||
* | |||
* @param offset The offset into <code>data</code> to start writing the record data to. | |||
* @param data The byte array to serialize to. | |||
* @param listener A listener to retrieve start and end callbacks. Use a <code>NullEscherSerailizationListener</code> to ignore these events. | |||
* @return The number of bytes written. | |||
* @see NullEscherSerializationListener | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
if (remainingData == null) remainingData = new byte[0]; | |||
@@ -78,29 +59,16 @@ public class EscherClientDataRecord | |||
return pos - offset; | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
return 8 + (remainingData == null ? 0 : remainingData.length); | |||
} | |||
/** | |||
* Returns the identifier of this record. | |||
*/ | |||
public short getRecordId() | |||
{ | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
/** | |||
* The short name for this record | |||
*/ | |||
public String getRecordName() | |||
{ | |||
public String getRecordName() { | |||
return "ClientData"; | |||
} | |||
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,15 +14,13 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.HexDump; | |||
package org.apache.poi.ddf; | |||
import java.util.Arrays; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndian; | |||
/** | |||
* A complex property differs from a simple property in that the data can not fit inside a 32 bit | |||
@@ -32,10 +29,9 @@ import java.io.IOException; | |||
* | |||
* @author Glen Stampoultzis | |||
*/ | |||
public class EscherComplexProperty | |||
extends EscherProperty | |||
{ | |||
byte[] complexData = new byte[0]; | |||
public class EscherComplexProperty extends EscherProperty { | |||
// TODO - make private and final | |||
protected byte[] _complexData; | |||
/** | |||
* Create a complex property using the property id and a byte array containing the complex | |||
@@ -45,10 +41,9 @@ public class EscherComplexProperty | |||
* indicating that this is a complex property. | |||
* @param complexData The value of this property. | |||
*/ | |||
public EscherComplexProperty( short id, byte[] complexData ) | |||
{ | |||
super( id ); | |||
this.complexData = complexData; | |||
public EscherComplexProperty(short id, byte[] complexData) { | |||
super(id); | |||
_complexData = complexData; | |||
} | |||
/** | |||
@@ -59,19 +54,17 @@ public class EscherComplexProperty | |||
* @param isBlipId Whether this is a blip id. Should be false. | |||
* @param complexData The value of this complex property. | |||
*/ | |||
public EscherComplexProperty( short propertyNumber, boolean isBlipId, byte[] complexData ) | |||
{ | |||
super( propertyNumber, true, isBlipId ); | |||
this.complexData = complexData; | |||
public EscherComplexProperty(short propertyNumber, boolean isBlipId, byte[] complexData) { | |||
super(propertyNumber, true, isBlipId); | |||
_complexData = complexData; | |||
} | |||
/** | |||
* Serializes the simple part of this property. ie the first 6 bytes. | |||
* Serializes the simple part of this property. i.e. the first 6 bytes. | |||
*/ | |||
public int serializeSimplePart( byte[] data, int pos ) | |||
{ | |||
public int serializeSimplePart(byte[] data, int pos) { | |||
LittleEndian.putShort(data, pos, getId()); | |||
LittleEndian.putInt(data, pos + 2, complexData.length); | |||
LittleEndian.putInt(data, pos + 2, _complexData.length); | |||
return 6; | |||
} | |||
@@ -82,18 +75,16 @@ public class EscherComplexProperty | |||
* @param pos The offset within data to start serializing to. | |||
* @return The number of bytes serialized. | |||
*/ | |||
public int serializeComplexPart( byte[] data, int pos ) | |||
{ | |||
System.arraycopy(complexData, 0, data, pos, complexData.length); | |||
return complexData.length; | |||
public int serializeComplexPart(byte[] data, int pos) { | |||
System.arraycopy(_complexData, 0, data, pos, _complexData.length); | |||
return _complexData.length; | |||
} | |||
/** | |||
* Get the complex data value. | |||
*/ | |||
public byte[] getComplexData() | |||
{ | |||
return complexData; | |||
public byte[] getComplexData() { | |||
return _complexData; | |||
} | |||
/** | |||
@@ -102,63 +93,39 @@ public class EscherComplexProperty | |||
* @param o The object to compare to. | |||
* @return True if the objects are equal. | |||
*/ | |||
public boolean equals( Object o ) | |||
{ | |||
if ( this == o ) return true; | |||
if ( !( o instanceof EscherComplexProperty ) ) return false; | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (!(o instanceof EscherComplexProperty)) { | |||
return false; | |||
} | |||
final EscherComplexProperty escherComplexProperty = (EscherComplexProperty) o; | |||
EscherComplexProperty escherComplexProperty = (EscherComplexProperty) o; | |||
if ( !Arrays.equals( complexData, escherComplexProperty.complexData ) ) return false; | |||
if ( !Arrays.equals( _complexData, escherComplexProperty._complexData ) ) return false; | |||
return true; | |||
} | |||
/** | |||
* Caclulates the number of bytes required to serialize this property. | |||
* Calculates the number of bytes required to serialize this property. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getPropertySize() | |||
{ | |||
return 6 + complexData.length; | |||
public int getPropertySize() { | |||
return 6 + _complexData.length; | |||
} | |||
/** | |||
* Calculates a hashcode for this property. | |||
*/ | |||
public int hashCode() | |||
{ | |||
public int hashCode() { | |||
return getId() * 11; | |||
} | |||
/** | |||
* Retrieves the string representation for this property. | |||
*/ | |||
public String toString() | |||
{ | |||
String dataStr; | |||
ByteArrayOutputStream b = new ByteArrayOutputStream(); | |||
try | |||
{ | |||
HexDump.dump( this.complexData, 0, b, 0 ); | |||
dataStr = b.toString(); | |||
} | |||
catch ( Exception e ) | |||
{ | |||
dataStr = e.toString(); | |||
} | |||
finally | |||
{ | |||
try | |||
{ | |||
b.close(); | |||
} | |||
catch ( IOException e ) | |||
{ | |||
e.printStackTrace(); | |||
} | |||
} | |||
public String toString() { | |||
String dataStr = HexDump.toHex( _complexData, 32); | |||
return "propNum: " + getPropertyNumber() | |||
+ ", propName: " + EscherProperties.getPropertyName( getPropertyNumber() ) |
@@ -15,7 +15,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.HexDump; | |||
@@ -36,16 +36,7 @@ public class EscherDgRecord | |||
private int field_1_numShapes; | |||
private int field_2_lastMSOSPID; | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
int size = 0; | |||
@@ -57,15 +48,6 @@ public class EscherDgRecord | |||
return getRecordSize(); | |||
} | |||
/** | |||
* This method serializes this escher record into a byte array. | |||
* | |||
* @param offset The offset into <code>data</code> to start writing the record data to. | |||
* @param data The byte array to serialize to. | |||
* @param listener A listener to retrieve start and end callbacks. Use a <code>NullEscherSerailizationListener</code> to ignore these events. | |||
* @return The number of bytes written. | |||
* @see NullEscherSerializationListener | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -92,42 +74,23 @@ public class EscherDgRecord | |||
return 8 + 8; | |||
} | |||
public short getRecordId() | |||
{ | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
/** | |||
* The short name for this record | |||
*/ | |||
public String getRecordName() | |||
{ | |||
public String getRecordName() { | |||
return "Dg"; | |||
} | |||
/** | |||
* Returns the string representation of this record. | |||
*/ | |||
public String toString() | |||
{ | |||
String nl = System.getProperty("line.separator"); | |||
// String extraData; | |||
// ByteArrayOutputStream b = new ByteArrayOutputStream(); | |||
// try | |||
// { | |||
// HexDump.dump(this.remainingData, 0, b, 0); | |||
// extraData = b.toString(); | |||
// } | |||
// catch ( Exception e ) | |||
// { | |||
// extraData = "error"; | |||
// } | |||
return getClass().getName() + ":" + nl + | |||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + nl + | |||
" Options: 0x" + HexDump.toHex(getOptions()) + nl + | |||
" NumShapes: " + field_1_numShapes + nl + | |||
" LastMSOSPID: " + field_2_lastMSOSPID + nl; | |||
public String toString() { | |||
return getClass().getName() + ":" + '\n' + | |||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + '\n' + | |||
" Options: 0x" + HexDump.toHex(getOptions()) + '\n' + | |||
" NumShapes: " + field_1_numShapes + '\n' + | |||
" LastMSOSPID: " + field_2_lastMSOSPID + '\n'; | |||
} | |||
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,7 +14,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.HexDump; | |||
@@ -27,9 +26,7 @@ import java.util.*; | |||
/** | |||
* This record defines the drawing groups used for a particular sheet. | |||
*/ | |||
public class EscherDggRecord | |||
extends EscherRecord | |||
{ | |||
public final class EscherDggRecord extends EscherRecord { | |||
public static final short RECORD_ID = (short) 0xF006; | |||
public static final String RECORD_DESCRIPTION = "MsofbtDgg"; | |||
@@ -67,21 +64,12 @@ public class EscherDggRecord | |||
} | |||
} | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
int size = 0; | |||
field_1_shapeIdMax = LittleEndian.getInt( data, pos + size );size+=4; | |||
int field_2_numIdClusters = LittleEndian.getInt( data, pos + size );size+=4; | |||
LittleEndian.getInt( data, pos + size );size+=4; // field_2_numIdClusters | |||
field_3_numShapesSaved = LittleEndian.getInt( data, pos + size );size+=4; | |||
field_4_drawingsSaved = LittleEndian.getInt( data, pos + size );size+=4; | |||
field_5_fileIdClusters = new FileIdCluster[(bytesRemaining-size) / 8]; // Can't rely on field_2_numIdClusters | |||
@@ -97,18 +85,7 @@ public class EscherDggRecord | |||
return 8 + size + bytesRemaining; | |||
} | |||
/** | |||
* This method serializes this escher record into a byte array. | |||
* | |||
* @param offset The offset into <code>data</code> to start writing the record data to. | |||
* @param data The byte array to serialize to. | |||
* @param listener A listener to retrieve start and end callbacks. Use a <code>NullEscherSerailizationListener</code> to ignore these events. | |||
* @return The number of bytes written. | |||
* | |||
* @see NullEscherSerializationListener | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
int pos = offset; | |||
@@ -121,8 +98,7 @@ public class EscherDggRecord | |||
LittleEndian.putInt( data, pos, getNumIdClusters() ); pos += 4; | |||
LittleEndian.putInt( data, pos, field_3_numShapesSaved ); pos += 4; | |||
LittleEndian.putInt( data, pos, field_4_drawingsSaved ); pos += 4; | |||
for ( int i = 0; i < field_5_fileIdClusters.length; i++ ) | |||
{ | |||
for (int i = 0; i < field_5_fileIdClusters.length; i++) { | |||
LittleEndian.putInt( data, pos, field_5_fileIdClusters[i].field_1_drawingGroupId ); pos += 4; | |||
LittleEndian.putInt( data, pos, field_5_fileIdClusters[i].field_2_numShapeIdsUsed ); pos += 4; | |||
} | |||
@@ -131,129 +107,94 @@ public class EscherDggRecord | |||
return getRecordSize(); | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
public int getRecordSize() { | |||
return 8 + 16 + (8 * field_5_fileIdClusters.length); | |||
} | |||
public short getRecordId() | |||
{ | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
/** | |||
* The short name for this record | |||
*/ | |||
public String getRecordName() | |||
{ | |||
public String getRecordName() { | |||
return "Dgg"; | |||
} | |||
public String toString() | |||
{ | |||
String nl = System.getProperty("line.separator"); | |||
// String extraData; | |||
// ByteArrayOutputStream b = new ByteArrayOutputStream(); | |||
// try | |||
// { | |||
// HexDump.dump(this.remainingData, 0, b, 0); | |||
// extraData = b.toString(); | |||
// } | |||
// catch ( Exception e ) | |||
// { | |||
// extraData = "error"; | |||
// } | |||
public String toString() { | |||
StringBuffer field_5_string = new StringBuffer(); | |||
for ( int i = 0; i < field_5_fileIdClusters.length; i++ ) | |||
{ | |||
for (int i = 0; i < field_5_fileIdClusters.length; i++) { | |||
field_5_string.append(" DrawingGroupId").append(i+1).append(": "); | |||
field_5_string.append(field_5_fileIdClusters[i].field_1_drawingGroupId); | |||
field_5_string.append(nl); | |||
field_5_string.append('\n'); | |||
field_5_string.append(" NumShapeIdsUsed").append(i+1).append(": "); | |||
field_5_string.append(field_5_fileIdClusters[i].field_2_numShapeIdsUsed); | |||
field_5_string.append(nl); | |||
field_5_string.append('\n'); | |||
} | |||
return getClass().getName() + ":" + nl + | |||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + nl + | |||
" Options: 0x" + HexDump.toHex(getOptions()) + nl + | |||
" ShapeIdMax: " + field_1_shapeIdMax + nl + | |||
" NumIdClusters: " + getNumIdClusters() + nl + | |||
" NumShapesSaved: " + field_3_numShapesSaved + nl + | |||
" DrawingsSaved: " + field_4_drawingsSaved + nl + | |||
return getClass().getName() + ":" + '\n' + | |||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + '\n' + | |||
" Options: 0x" + HexDump.toHex(getOptions()) + '\n' + | |||
" ShapeIdMax: " + field_1_shapeIdMax + '\n' + | |||
" NumIdClusters: " + getNumIdClusters() + '\n' + | |||
" NumShapesSaved: " + field_3_numShapesSaved + '\n' + | |||
" DrawingsSaved: " + field_4_drawingsSaved + '\n' + | |||
"" + field_5_string.toString(); | |||
} | |||
public int getShapeIdMax() | |||
{ | |||
public int getShapeIdMax() { | |||
return field_1_shapeIdMax; | |||
} | |||
/** | |||
* The maximum is actually the next available. shape id. | |||
*/ | |||
public void setShapeIdMax( int field_1_shapeIdMax ) | |||
{ | |||
this.field_1_shapeIdMax = field_1_shapeIdMax; | |||
public void setShapeIdMax(int shapeIdMax) { | |||
this.field_1_shapeIdMax = shapeIdMax; | |||
} | |||
/** | |||
* Number of id clusters + 1 | |||
*/ | |||
public int getNumIdClusters() | |||
{ | |||
*/ | |||
public int getNumIdClusters() { | |||
return field_5_fileIdClusters.length + 1; | |||
} | |||
public int getNumShapesSaved() | |||
{ | |||
public int getNumShapesSaved() { | |||
return field_3_numShapesSaved; | |||
} | |||
public void setNumShapesSaved( int field_3_numShapesSaved ) | |||
{ | |||
this.field_3_numShapesSaved = field_3_numShapesSaved; | |||
public void setNumShapesSaved(int numShapesSaved) { | |||
this.field_3_numShapesSaved = numShapesSaved; | |||
} | |||
public int getDrawingsSaved() | |||
{ | |||
public int getDrawingsSaved() { | |||
return field_4_drawingsSaved; | |||
} | |||
public void setDrawingsSaved( int field_4_drawingsSaved ) | |||
{ | |||
this.field_4_drawingsSaved = field_4_drawingsSaved; | |||
public void setDrawingsSaved(int drawingsSaved) { | |||
this.field_4_drawingsSaved = drawingsSaved; | |||
} | |||
/** | |||
* @return The maximum drawing group ID | |||
*/ | |||
public int getMaxDrawingGroupId(){ | |||
public int getMaxDrawingGroupId() { | |||
return maxDgId; | |||
} | |||
public void setMaxDrawingGroupId(int id){ | |||
public void setMaxDrawingGroupId(int id) { | |||
maxDgId = id; | |||
} | |||
public FileIdCluster[] getFileIdClusters() | |||
{ | |||
public FileIdCluster[] getFileIdClusters() { | |||
return field_5_fileIdClusters; | |||
} | |||
public void setFileIdClusters( FileIdCluster[] field_5_fileIdClusters ) | |||
{ | |||
this.field_5_fileIdClusters = field_5_fileIdClusters; | |||
public void setFileIdClusters(FileIdCluster[] fileIdClusters) { | |||
this.field_5_fileIdClusters = fileIdClusters; | |||
} | |||
public void addCluster( int dgId, int numShapedUsed ) | |||
{ | |||
public void addCluster(int dgId, int numShapedUsed) { | |||
addCluster(dgId, numShapedUsed, true); | |||
} | |||
@@ -265,25 +206,23 @@ public class EscherDggRecord | |||
* @param sort if true then sort clusters by drawing group id.( | |||
* In Excel the clusters are sorted but in PPT they are not) | |||
*/ | |||
public void addCluster( int dgId, int numShapedUsed, boolean sort ) | |||
{ | |||
List clusters = new ArrayList(Arrays.asList(field_5_fileIdClusters)); | |||
public void addCluster( int dgId, int numShapedUsed, boolean sort ) { | |||
List<FileIdCluster> clusters = new ArrayList<FileIdCluster>(Arrays.asList(field_5_fileIdClusters)); | |||
clusters.add(new FileIdCluster(dgId, numShapedUsed)); | |||
if(sort) Collections.sort(clusters, new Comparator() | |||
{ | |||
public int compare( Object o1, Object o2 ) | |||
{ | |||
FileIdCluster f1 = (FileIdCluster) o1; | |||
FileIdCluster f2 = (FileIdCluster) o2; | |||
if (f1.getDrawingGroupId() == f2.getDrawingGroupId()) | |||
return 0; | |||
if (f1.getDrawingGroupId() < f2.getDrawingGroupId()) | |||
return -1; | |||
else | |||
return +1; | |||
} | |||
} ); | |||
if(sort) Collections.sort(clusters, MY_COMP ); | |||
maxDgId = Math.min(maxDgId, dgId); | |||
field_5_fileIdClusters = (FileIdCluster[]) clusters.toArray( new FileIdCluster[clusters.size()] ); | |||
field_5_fileIdClusters = clusters.toArray( new FileIdCluster[clusters.size()] ); | |||
} | |||
private static final Comparator<FileIdCluster> MY_COMP = new Comparator<FileIdCluster>() { | |||
public int compare(FileIdCluster f1, FileIdCluster f2) { | |||
if (f1.getDrawingGroupId() == f2.getDrawingGroupId()) { | |||
return 0; | |||
} | |||
if (f1.getDrawingGroupId() < f2.getDrawingGroupId()) { | |||
return -1; | |||
} | |||
return +1; | |||
} | |||
}; | |||
} |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,7 +14,6 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
@@ -34,11 +32,10 @@ import java.util.zip.InflaterInputStream; | |||
* | |||
* @author Glen Stampoultzis (glens at apache.org) | |||
*/ | |||
public class EscherDump | |||
{ | |||
public final class EscherDump { | |||
public EscherDump() | |||
{ | |||
public EscherDump() { | |||
// | |||
} | |||
/** | |||
@@ -51,15 +48,14 @@ public class EscherDump | |||
* @param out The output stream to write the results to. | |||
* | |||
*/ | |||
public void dump( byte[] data, int offset, int size, PrintStream out ) throws IOException, LittleEndian.BufferUnderrunException | |||
{ | |||
public void dump(byte[] data, int offset, int size, PrintStream out) { | |||
EscherRecordFactory recordFactory = new DefaultEscherRecordFactory(); | |||
int pos = offset; | |||
while ( pos < offset + size ) | |||
{ | |||
EscherRecord r = recordFactory.createRecord(data, pos); | |||
int bytesRead = r.fillFields(data, pos, recordFactory ); | |||
System.out.println( r.toString() ); | |||
out.println( r.toString() ); | |||
pos += bytesRead; | |||
} | |||
} | |||
@@ -71,8 +67,8 @@ public class EscherDump | |||
* @param in An input stream to read from. | |||
* @param out An output stream to write to. | |||
*/ | |||
public void dumpOld( long maxLength, InputStream in, PrintStream out ) throws IOException, LittleEndian.BufferUnderrunException | |||
{ | |||
public void dumpOld(long maxLength, InputStream in, PrintStream out) | |||
throws IOException, LittleEndian.BufferUnderrunException { | |||
long remainingBytes = maxLength; | |||
short options; // 4 bits for the version and 12 bits for the instance | |||
short recordId; | |||
@@ -83,8 +79,7 @@ public class EscherDump | |||
boolean atEOF = false; | |||
while ( !atEOF && ( remainingBytes > 0 ) ) | |||
{ | |||
while (!atEOF && (remainingBytes > 0)) { | |||
stringBuf = new StringBuffer(); | |||
options = LittleEndian.readShort( in ); | |||
recordId = LittleEndian.readShort( in ); | |||
@@ -435,17 +430,14 @@ public class EscherDump | |||
* @param propertyId The property number for the name | |||
* @return A descriptive name. | |||
*/ | |||
private String propName( short propertyId ) | |||
{ | |||
class PropName { | |||
public PropName( int id, String name ) | |||
{ | |||
this.id = id; | |||
this.name = name; | |||
private String propName(short propertyId) { | |||
final class PropName { | |||
final int _id; | |||
final String _name; | |||
public PropName(int id, String name) { | |||
_id = id; | |||
_name = name; | |||
} | |||
int id; | |||
String name; | |||
} | |||
final PropName[] props = new PropName[] { | |||
@@ -725,11 +717,9 @@ public class EscherDump | |||
new PropName(959, "groupshape.print"), | |||
}; | |||
for ( int i = 0; i < props.length; i++ ) | |||
{ | |||
if (props[i].id == propertyId) | |||
{ | |||
return props[i].name; | |||
for (int i = 0; i < props.length; i++) { | |||
if (props[i]._id == propertyId) { | |||
return props[i]._name; | |||
} | |||
} | |||
@@ -742,32 +732,8 @@ public class EscherDump | |||
* @param b blip id | |||
* @return A description. | |||
*/ | |||
private String getBlipType( byte b ) | |||
{ | |||
switch ( b ) | |||
{ | |||
case 0: | |||
return " ERROR"; | |||
case 1: | |||
return " UNKNOWN"; | |||
case 2: | |||
return " EMF"; | |||
case 3: | |||
return " WMF"; | |||
case 4: | |||
return " PICT"; | |||
case 5: | |||
return " JPEG"; | |||
case 6: | |||
return " PNG"; | |||
case 7: | |||
return " DIB"; | |||
default: | |||
if ( b < 32 ) | |||
return " NotKnown"; | |||
else | |||
return " Client"; | |||
} | |||
private static String getBlipType(byte b) { | |||
return EscherBSERecord.getBlipType(b); | |||
} | |||
/** | |||
@@ -810,8 +776,7 @@ public class EscherDump | |||
/** | |||
* A simple test stub. | |||
*/ | |||
public static void main( String[] args ) throws IOException | |||
{ | |||
public static void main( String[] args ) { | |||
String dump = | |||
"0F 00 00 F0 89 07 00 00 00 00 06 F0 18 00 00 00 " + | |||
"05 04 00 00 02 00 00 00 05 00 00 00 01 00 00 00 " + | |||
@@ -937,7 +902,7 @@ public class EscherDump | |||
"10 "; | |||
// Decode the stream to bytes | |||
byte[] bytes = HexRead.readData( new ByteArrayInputStream( dump.getBytes() ), -1 ); | |||
byte[] bytes = HexRead.readFromString(dump); | |||
// Create a new instance of the escher dumper | |||
EscherDump dumper = new EscherDump(); | |||
// Dump the contents of scher to screen. | |||
@@ -946,10 +911,7 @@ public class EscherDump | |||
} | |||
public void dump( int recordSize, byte[] data, PrintStream out ) throws IOException, LittleEndian.BufferUnderrunException | |||
{ | |||
// ByteArrayInputStream is = new ByteArrayInputStream( data ); | |||
// dump( recordSize, is, out ); | |||
dump( data, 0, recordSize, System.out ); | |||
public void dump( int recordSize, byte[] data, PrintStream out ) { | |||
dump( data, 0, recordSize, out ); | |||
} | |||
} |
@@ -1,19 +1,20 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You 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. | |||
*/ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You 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 org.apache.poi.ddf; | |||
import org.apache.poi.util.HexDump; | |||
@@ -30,11 +31,8 @@ import java.util.zip.InflaterInputStream; | |||
/** | |||
* @author Daniel Noll | |||
* @version $Id$ | |||
*/ | |||
public class EscherMetafileBlip | |||
extends EscherBlipRecord | |||
{ | |||
public final class EscherMetafileBlip extends EscherBlipRecord { | |||
private static final POILogger log = POILogFactory.getLogger(EscherMetafileBlip.class); | |||
public static final short RECORD_ID_EMF = (short) 0xF018 + 2; | |||
@@ -68,16 +66,7 @@ public class EscherMetafileBlip | |||
private byte[] raw_pictureData; | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesAfterHeader = readHeader( data, offset ); | |||
int pos = offset + HEADER_SIZE; | |||
@@ -105,31 +94,16 @@ public class EscherMetafileBlip | |||
// 0 means DEFLATE compression | |||
// 0xFE means no compression | |||
if (field_6_fCompression == 0) | |||
{ | |||
if (field_6_fCompression == 0) { | |||
field_pictureData = inflatePictureData(raw_pictureData); | |||
} | |||
else | |||
{ | |||
} else { | |||
field_pictureData = raw_pictureData; | |||
} | |||
return bytesAfterHeader + HEADER_SIZE; | |||
} | |||
/** | |||
* Serializes the record to an existing byte array. | |||
* | |||
* @param offset the offset within the byte array | |||
* @param data the data array to serialize to | |||
* @param listener a listener for begin and end serialization events. This | |||
* is useful because the serialization is | |||
* hierarchical/recursive and sometimes you need to be able | |||
* break into that. | |||
* @return the number of bytes written. | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize(offset, getRecordId(), this); | |||
int pos = offset; | |||
@@ -138,7 +112,7 @@ public class EscherMetafileBlip | |||
LittleEndian.putInt( data, pos, getRecordSize() - HEADER_SIZE ); pos += 4; | |||
System.arraycopy( field_1_UID, 0, data, pos, field_1_UID.length ); pos += field_1_UID.length; | |||
if((getOptions() ^ getSignature()) == 0x10){ | |||
if ((getOptions() ^ getSignature()) == 0x10) { | |||
System.arraycopy( field_2_UID, 0, data, pos, field_2_UID.length ); pos += field_2_UID.length; | |||
} | |||
LittleEndian.putInt( data, pos, field_2_cb ); pos += 4; | |||
@@ -164,35 +138,24 @@ public class EscherMetafileBlip | |||
* @param data the deflated picture data. | |||
* @return the inflated picture data. | |||
*/ | |||
private static byte[] inflatePictureData(byte[] data) | |||
{ | |||
try | |||
{ | |||
private static byte[] inflatePictureData(byte[] data) { | |||
try { | |||
InflaterInputStream in = new InflaterInputStream( | |||
new ByteArrayInputStream( data ) ); | |||
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||
byte[] buf = new byte[4096]; | |||
int readBytes; | |||
while ((readBytes = in.read(buf)) > 0) | |||
{ | |||
while ((readBytes = in.read(buf)) > 0) { | |||
out.write(buf, 0, readBytes); | |||
} | |||
return out.toByteArray(); | |||
} | |||
catch ( IOException e ) | |||
{ | |||
} catch (IOException e) { | |||
log.log(POILogger.WARN, "Possibly corrupt compression or non-compressed data", e); | |||
return data; | |||
} | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
public int getRecordSize() { | |||
int size = 8 + 50 + raw_pictureData.length; | |||
if((getOptions() ^ getSignature()) == 0x10){ | |||
size += field_2_UID.length; | |||
@@ -200,14 +163,12 @@ public class EscherMetafileBlip | |||
return size; | |||
} | |||
public byte[] getUID() | |||
{ | |||
public byte[] getUID() { | |||
return field_1_UID; | |||
} | |||
public void setUID( byte[] field_1_UID ) | |||
{ | |||
this.field_1_UID = field_1_UID; | |||
public void setUID(byte[] uid) { | |||
field_1_UID = uid; | |||
} | |||
public byte[] getPrimaryUID() | |||
@@ -215,97 +176,73 @@ public class EscherMetafileBlip | |||
return field_2_UID; | |||
} | |||
public void setPrimaryUID( byte[] field_2_UID ) | |||
{ | |||
this.field_2_UID = field_2_UID; | |||
public void setPrimaryUID(byte[] primaryUID) { | |||
field_2_UID = primaryUID; | |||
} | |||
public int getUncompressedSize() | |||
{ | |||
public int getUncompressedSize() { | |||
return field_2_cb; | |||
} | |||
public void setUncompressedSize(int uncompressedSize) | |||
{ | |||
public void setUncompressedSize(int uncompressedSize) { | |||
field_2_cb = uncompressedSize; | |||
} | |||
public Rectangle getBounds() | |||
{ | |||
public Rectangle getBounds() { | |||
return new Rectangle(field_3_rcBounds_x1, | |||
field_3_rcBounds_y1, | |||
field_3_rcBounds_x2 - field_3_rcBounds_x1, | |||
field_3_rcBounds_y2 - field_3_rcBounds_y1); | |||
} | |||
public void setBounds(Rectangle bounds) | |||
{ | |||
public void setBounds(Rectangle bounds) { | |||
field_3_rcBounds_x1 = bounds.x; | |||
field_3_rcBounds_y1 = bounds.y; | |||
field_3_rcBounds_x2 = bounds.x + bounds.width; | |||
field_3_rcBounds_y2 = bounds.y + bounds.height; | |||
} | |||
public Dimension getSizeEMU() | |||
{ | |||
public Dimension getSizeEMU() { | |||
return new Dimension(field_4_ptSize_w, field_4_ptSize_h); | |||
} | |||
public void setSizeEMU(Dimension sizeEMU) | |||
{ | |||
public void setSizeEMU(Dimension sizeEMU) { | |||
field_4_ptSize_w = sizeEMU.width; | |||
field_4_ptSize_h = sizeEMU.height; | |||
} | |||
public int getCompressedSize() | |||
{ | |||
public int getCompressedSize() { | |||
return field_5_cbSave; | |||
} | |||
public void setCompressedSize(int compressedSize) | |||
{ | |||
public void setCompressedSize(int compressedSize) { | |||
field_5_cbSave = compressedSize; | |||
} | |||
public boolean isCompressed() | |||
{ | |||
public boolean isCompressed() { | |||
return (field_6_fCompression == 0); | |||
} | |||
public void setCompressed(boolean compressed) | |||
{ | |||
public void setCompressed(boolean compressed) { | |||
field_6_fCompression = compressed ? 0 : (byte)0xFE; | |||
} | |||
// filtering is always 254 according to available docs, so no point giving it a setter method. | |||
public String toString() | |||
{ | |||
String nl = System.getProperty( "line.separator" ); | |||
String extraData; | |||
ByteArrayOutputStream b = new ByteArrayOutputStream(); | |||
try | |||
{ | |||
HexDump.dump( this.field_pictureData, 0, b, 0 ); | |||
extraData = b.toString(); | |||
} | |||
catch ( Exception e ) | |||
{ | |||
extraData = e.toString(); | |||
} | |||
return getClass().getName() + ":" + nl + | |||
" RecordId: 0x" + HexDump.toHex( getRecordId() ) + nl + | |||
" Options: 0x" + HexDump.toHex( getOptions() ) + nl + | |||
" UID: 0x" + HexDump.toHex( field_1_UID ) + nl + | |||
(field_2_UID == null ? "" : (" UID2: 0x" + HexDump.toHex( field_2_UID ) + nl)) + | |||
" Uncompressed Size: " + HexDump.toHex( field_2_cb ) + nl + | |||
" Bounds: " + getBounds() + nl + | |||
" Size in EMU: " + getSizeEMU() + nl + | |||
" Compressed Size: " + HexDump.toHex( field_5_cbSave ) + nl + | |||
" Compression: " + HexDump.toHex( field_6_fCompression ) + nl + | |||
" Filter: " + HexDump.toHex( field_7_fFilter ) + nl + | |||
" Extra Data:" + nl + extraData; | |||
public String toString() { | |||
String extraData = HexDump.toHex(field_pictureData, 32); | |||
return getClass().getName() + ":" + '\n' + | |||
" RecordId: 0x" + HexDump.toHex( getRecordId() ) + '\n' + | |||
" Options: 0x" + HexDump.toHex( getOptions() ) + '\n' + | |||
" UID: 0x" + HexDump.toHex( field_1_UID ) + '\n' + | |||
(field_2_UID == null ? "" : (" UID2: 0x" + HexDump.toHex( field_2_UID ) + '\n')) + | |||
" Uncompressed Size: " + HexDump.toHex( field_2_cb ) + '\n' + | |||
" Bounds: " + getBounds() + '\n' + | |||
" Size in EMU: " + getSizeEMU() + '\n' + | |||
" Compressed Size: " + HexDump.toHex( field_5_cbSave ) + '\n' + | |||
" Compression: " + HexDump.toHex( field_6_fCompression ) + '\n' + | |||
" Filter: " + HexDump.toHex( field_7_fFilter ) + '\n' + | |||
" Extra Data:" + '\n' + extraData; | |||
} | |||
/** | |||
@@ -313,14 +250,13 @@ public class EscherMetafileBlip | |||
* | |||
* @return the blip signature | |||
*/ | |||
public short getSignature(){ | |||
short sig = 0; | |||
switch(getRecordId()){ | |||
case RECORD_ID_EMF: sig = SIGNATURE_EMF; break; | |||
case RECORD_ID_WMF: sig = SIGNATURE_WMF; break; | |||
case RECORD_ID_PICT: sig = SIGNATURE_PICT; break; | |||
default: log.log(POILogger.WARN, "Unknown metafile: " + getRecordId()); break; | |||
public short getSignature() { | |||
switch (getRecordId()) { | |||
case RECORD_ID_EMF: return SIGNATURE_EMF; | |||
case RECORD_ID_WMF: return SIGNATURE_WMF; | |||
case RECORD_ID_PICT: return SIGNATURE_PICT; | |||
} | |||
return sig; | |||
log.log(POILogger.WARN, "Unknown metafile: " + getRecordId()); | |||
return 0; | |||
} | |||
} |
@@ -15,7 +15,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import java.util.ArrayList; | |||
@@ -42,16 +42,7 @@ public class EscherOptRecord | |||
private List properties = new ArrayList(); | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
@@ -60,16 +51,6 @@ public class EscherOptRecord | |||
return bytesRemaining + 8; | |||
} | |||
/** | |||
* This method serializes this escher record into a byte array. | |||
* | |||
* @param offset The offset into <code>data</code> to start writing the record data to. | |||
* @param data The byte array to serialize to. | |||
* @param listener A listener to retrieve start and end callbacks. Use a <code>NullEscherSerailizationListener</code> to ignore these events. | |||
* | |||
* @return The number of bytes written. | |||
* @see NullEscherSerializationListener | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -92,11 +73,6 @@ public class EscherOptRecord | |||
return pos - offset; | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
return 8 + getPropertiesSize(); | |||
@@ -111,11 +87,7 @@ public class EscherOptRecord | |||
return super.getOptions(); | |||
} | |||
/** | |||
* The short name for this record | |||
*/ | |||
public String getRecordName() | |||
{ | |||
public String getRecordName() { | |||
return "Opt"; | |||
} | |||
@@ -1,19 +1,20 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You 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. | |||
*/ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
this work for additional information regarding copyright ownership. | |||
The ASF licenses this file to You 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 org.apache.poi.ddf; | |||
import org.apache.poi.util.HexDump; | |||
@@ -30,11 +31,8 @@ import java.util.zip.InflaterInputStream; | |||
/** | |||
* @author Daniel Noll | |||
* @version $Id$ | |||
*/ | |||
public class EscherPictBlip | |||
extends EscherBlipRecord | |||
{ | |||
public final class EscherPictBlip extends EscherBlipRecord { | |||
private static final POILogger log = POILogFactory.getLogger(EscherPictBlip.class); | |||
public static final short RECORD_ID_EMF = (short) 0xF018 + 2; | |||
@@ -57,17 +55,8 @@ public class EscherPictBlip | |||
private byte[] raw_pictureData; | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) | |||
{ | |||
int bytesAfterHeader = readHeader( data, offset ); | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesAfterHeader = readHeader(data, offset); | |||
int pos = offset + HEADER_SIZE; | |||
field_1_UID = new byte[16]; | |||
@@ -100,19 +89,7 @@ public class EscherPictBlip | |||
return bytesAfterHeader + HEADER_SIZE; | |||
} | |||
/** | |||
* Serializes the record to an existing byte array. | |||
* | |||
* @param offset the offset within the byte array | |||
* @param data the data array to serialize to | |||
* @param listener a listener for begin and end serialization events. This | |||
* is useful because the serialization is | |||
* hierarchical/recursive and sometimes you need to be able | |||
* break into that. | |||
* @return the number of bytes written. | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize(offset, getRecordId(), this); | |||
int pos = offset; | |||
@@ -144,133 +121,95 @@ public class EscherPictBlip | |||
* @param data the deflated picture data. | |||
* @return the inflated picture data. | |||
*/ | |||
private static byte[] inflatePictureData(byte[] data) | |||
{ | |||
try | |||
{ | |||
InflaterInputStream in = new InflaterInputStream( | |||
new ByteArrayInputStream( data ) ); | |||
private static byte[] inflatePictureData(byte[] data) { | |||
try { | |||
InflaterInputStream in = new InflaterInputStream(new ByteArrayInputStream(data)); | |||
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||
byte[] buf = new byte[4096]; | |||
int readBytes; | |||
while ((readBytes = in.read(buf)) > 0) | |||
{ | |||
while ((readBytes = in.read(buf)) > 0) { | |||
out.write(buf, 0, readBytes); | |||
} | |||
return out.toByteArray(); | |||
} | |||
catch ( IOException e ) | |||
{ | |||
} catch (IOException e) { | |||
log.log(POILogger.INFO, "Possibly corrupt compression or non-compressed data", e); | |||
return data; | |||
} | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
public int getRecordSize() { | |||
return 8 + 50 + raw_pictureData.length; | |||
} | |||
public byte[] getUID() | |||
{ | |||
public byte[] getUID() { | |||
return field_1_UID; | |||
} | |||
public void setUID( byte[] field_1_UID ) | |||
{ | |||
this.field_1_UID = field_1_UID; | |||
public void setUID(byte[] uid) { | |||
this.field_1_UID = uid; | |||
} | |||
public int getUncompressedSize() | |||
{ | |||
public int getUncompressedSize() { | |||
return field_2_cb; | |||
} | |||
public void setUncompressedSize(int uncompressedSize) | |||
{ | |||
public void setUncompressedSize(int uncompressedSize) { | |||
field_2_cb = uncompressedSize; | |||
} | |||
public Rectangle getBounds() | |||
{ | |||
public Rectangle getBounds() { | |||
return new Rectangle(field_3_rcBounds_x1, | |||
field_3_rcBounds_y1, | |||
field_3_rcBounds_x2 - field_3_rcBounds_x1, | |||
field_3_rcBounds_y2 - field_3_rcBounds_y1); | |||
} | |||
public void setBounds(Rectangle bounds) | |||
{ | |||
public void setBounds(Rectangle bounds) { | |||
field_3_rcBounds_x1 = bounds.x; | |||
field_3_rcBounds_y1 = bounds.y; | |||
field_3_rcBounds_x2 = bounds.x + bounds.width; | |||
field_3_rcBounds_y2 = bounds.y + bounds.height; | |||
} | |||
public Dimension getSizeEMU() | |||
{ | |||
public Dimension getSizeEMU() { | |||
return new Dimension(field_4_ptSize_w, field_4_ptSize_h); | |||
} | |||
public void setSizeEMU(Dimension sizeEMU) | |||
{ | |||
public void setSizeEMU(Dimension sizeEMU) { | |||
field_4_ptSize_w = sizeEMU.width; | |||
field_4_ptSize_h = sizeEMU.height; | |||
} | |||
public int getCompressedSize() | |||
{ | |||
public int getCompressedSize() { | |||
return field_5_cbSave; | |||
} | |||
public void setCompressedSize(int compressedSize) | |||
{ | |||
public void setCompressedSize(int compressedSize) { | |||
field_5_cbSave = compressedSize; | |||
} | |||
public boolean isCompressed() | |||
{ | |||
public boolean isCompressed() { | |||
return (field_6_fCompression == 0); | |||
} | |||
public void setCompressed(boolean compressed) | |||
{ | |||
public void setCompressed(boolean compressed) { | |||
field_6_fCompression = compressed ? 0 : (byte)0xFE; | |||
} | |||
// filtering is always 254 according to available docs, so no point giving it a setter method. | |||
public String toString() | |||
{ | |||
String nl = System.getProperty( "line.separator" ); | |||
String extraData; | |||
ByteArrayOutputStream b = new ByteArrayOutputStream(); | |||
try | |||
{ | |||
HexDump.dump( this.field_pictureData, 0, b, 0 ); | |||
extraData = b.toString(); | |||
} | |||
catch ( Exception e ) | |||
{ | |||
extraData = e.toString(); | |||
} | |||
return getClass().getName() + ":" + nl + | |||
" RecordId: 0x" + HexDump.toHex( getRecordId() ) + nl + | |||
" Options: 0x" + HexDump.toHex( getOptions() ) + nl + | |||
" UID: 0x" + HexDump.toHex( field_1_UID ) + nl + | |||
" Uncompressed Size: " + HexDump.toHex( field_2_cb ) + nl + | |||
" Bounds: " + getBounds() + nl + | |||
" Size in EMU: " + getSizeEMU() + nl + | |||
" Compressed Size: " + HexDump.toHex( field_5_cbSave ) + nl + | |||
" Compression: " + HexDump.toHex( field_6_fCompression ) + nl + | |||
" Filter: " + HexDump.toHex( field_7_fFilter ) + nl + | |||
" Extra Data:" + nl + extraData; | |||
public String toString() { | |||
String extraData = HexDump.toHex(field_pictureData, 32); | |||
return getClass().getName() + ":" + '\n' + | |||
" RecordId: 0x" + HexDump.toHex( getRecordId() ) + '\n' + | |||
" Options: 0x" + HexDump.toHex( getOptions() ) + '\n' + | |||
" UID: 0x" + HexDump.toHex( field_1_UID ) + '\n' + | |||
" Uncompressed Size: " + HexDump.toHex( field_2_cb ) + '\n' + | |||
" Bounds: " + getBounds() + '\n' + | |||
" Size in EMU: " + getSizeEMU() + '\n' + | |||
" Compressed Size: " + HexDump.toHex( field_5_cbSave ) + '\n' + | |||
" Compression: " + HexDump.toHex( field_6_fCompression ) + '\n' + | |||
" Filter: " + HexDump.toHex( field_7_fFilter ) + '\n' + | |||
" Extra Data:" + '\n' + extraData; | |||
} | |||
} |
@@ -15,7 +15,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import java.util.HashMap; |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,7 +14,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
/** | |||
@@ -25,61 +24,52 @@ package org.apache.poi.ddf; | |||
* | |||
* @author Glen Stampoultzis (glens at apache.org) | |||
*/ | |||
abstract public class EscherProperty | |||
{ | |||
protected short id; | |||
public abstract class EscherProperty { | |||
private short _id; | |||
/** | |||
* The id is distinct from the actual property number. The id includes the property number the blip id | |||
* flag and an indicator whether the property is complex or not. | |||
*/ | |||
public EscherProperty( short id ) | |||
{ | |||
this.id = id; | |||
public EscherProperty(short id) { | |||
_id = id; | |||
} | |||
/** | |||
* Constructs a new escher property. The three parameters are combined to form a property | |||
* id. | |||
*/ | |||
public EscherProperty( short propertyNumber, boolean isComplex, boolean isBlipId ) | |||
{ | |||
this.id = (short)(propertyNumber + | |||
public EscherProperty(short propertyNumber, boolean isComplex, boolean isBlipId) { | |||
_id = (short)(propertyNumber + | |||
(isComplex ? 0x8000 : 0x0) + | |||
(isBlipId ? 0x4000 : 0x0)); | |||
} | |||
public short getId() | |||
{ | |||
return id; | |||
public short getId() { | |||
return _id; | |||
} | |||
public short getPropertyNumber() | |||
{ | |||
return (short) ( id & (short) 0x3FFF ); | |||
public short getPropertyNumber() { | |||
return (short) (_id & (short) 0x3FFF); | |||
} | |||
public boolean isComplex() | |||
{ | |||
return ( id & (short) 0x8000 ) != 0; | |||
public boolean isComplex() { | |||
return (_id & (short) 0x8000) != 0; | |||
} | |||
public boolean isBlipId() | |||
{ | |||
return ( id & (short) 0x4000 ) != 0; | |||
public boolean isBlipId() { | |||
return (_id & (short) 0x4000) != 0; | |||
} | |||
public String getName() | |||
{ | |||
return EscherProperties.getPropertyName(id); | |||
public String getName() { | |||
return EscherProperties.getPropertyName(_id); | |||
} | |||
/** | |||
* Most properties are just 6 bytes in length. Override this if we're | |||
* dealing with complex properties. | |||
*/ | |||
public int getPropertySize() | |||
{ | |||
public int getPropertySize() { | |||
return 6; | |||
} | |||
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,7 +14,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.LittleEndian; | |||
@@ -29,8 +28,7 @@ import java.util.List; | |||
* | |||
* @author Glen Stampoultzis | |||
*/ | |||
public class EscherPropertyFactory | |||
{ | |||
public final class EscherPropertyFactory { | |||
/** | |||
* Create new properties from a byte array. | |||
* | |||
@@ -38,15 +36,13 @@ public class EscherPropertyFactory | |||
* @param offset The starting offset into the byte array | |||
* @return The new properties | |||
*/ | |||
public List createProperties( byte[] data, int offset, short numProperties ) | |||
{ | |||
List results = new ArrayList(); | |||
public List<EscherProperty> createProperties(byte[] data, int offset, short numProperties) { | |||
List<EscherProperty> results = new ArrayList<EscherProperty>(); | |||
int pos = offset; | |||
// while ( bytesRemaining >= 6 ) | |||
for (int i = 0; i < numProperties; i++) | |||
{ | |||
for (int i = 0; i < numProperties; i++) { | |||
short propId; | |||
int propData; | |||
propId = LittleEndian.getShort( data, pos ); | |||
@@ -55,7 +51,7 @@ public class EscherPropertyFactory | |||
boolean isComplex = ( propId & (short) 0x8000 ) != 0; | |||
boolean isBlipId = ( propId & (short) 0x4000 ) != 0; | |||
byte propertyType = EscherProperties.getPropertyType( (short) propNumber ); | |||
byte propertyType = EscherProperties.getPropertyType(propNumber); | |||
if ( propertyType == EscherPropertyMetaData.TYPE_BOOLEAN ) | |||
results.add( new EscherBoolProperty( propId, propData ) ); | |||
else if ( propertyType == EscherPropertyMetaData.TYPE_RGB ) | |||
@@ -72,7 +68,6 @@ public class EscherPropertyFactory | |||
results.add( new EscherArrayProperty( propId, new byte[propData]) ); | |||
else | |||
results.add( new EscherComplexProperty( propId, new byte[propData]) ); | |||
} | |||
} | |||
pos += 6; | |||
@@ -80,26 +75,18 @@ public class EscherPropertyFactory | |||
} | |||
// Get complex data | |||
for ( Iterator iterator = results.iterator(); iterator.hasNext(); ) | |||
{ | |||
EscherProperty p = (EscherProperty) iterator.next(); | |||
if (p instanceof EscherComplexProperty) | |||
{ | |||
if (p instanceof EscherArrayProperty) | |||
{ | |||
for (Iterator<EscherProperty> iterator = results.iterator(); iterator.hasNext();) { | |||
EscherProperty p = iterator.next(); | |||
if (p instanceof EscherComplexProperty) { | |||
if (p instanceof EscherArrayProperty) { | |||
pos += ((EscherArrayProperty)p).setArrayData(data, pos); | |||
} | |||
else | |||
{ | |||
} else { | |||
byte[] complexData = ((EscherComplexProperty)p).getComplexData(); | |||
System.arraycopy(data, pos, complexData, 0, complexData.length); | |||
pos += complexData.length; | |||
} | |||
} | |||
} | |||
return results; | |||
} | |||
} |
@@ -15,7 +15,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
/** |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,7 +14,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
/** |
@@ -15,7 +15,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.LittleEndian; |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,7 +14,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
/** | |||
@@ -24,8 +23,7 @@ package org.apache.poi.ddf; | |||
* | |||
* @author Glen Stampoultzis (glens at apache.org) | |||
*/ | |||
public interface EscherRecordFactory | |||
{ | |||
public interface EscherRecordFactory { | |||
/** | |||
* Create a new escher record from the data provided. Does not attempt | |||
* to fill the contents of the record however. |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,7 +14,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
/** |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,7 +14,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
/** | |||
@@ -23,9 +22,7 @@ package org.apache.poi.ddf; | |||
* | |||
* @author Glen Stampoultzis (glens at apache.org) | |||
*/ | |||
public class EscherShapePathProperty | |||
extends EscherSimpleProperty | |||
{ | |||
public class EscherShapePathProperty extends EscherSimpleProperty { | |||
public static final int LINE_OF_STRAIGHT_SEGMENTS = 0; | |||
public static final int CLOSED_POLYGON = 1; | |||
@@ -37,7 +34,4 @@ public class EscherShapePathProperty | |||
{ | |||
super( propertyNumber, false, false, shapePath ); | |||
} | |||
} |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,7 +14,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.LittleEndian; |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,7 +14,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.HexDump; | |||
@@ -49,16 +48,7 @@ public class EscherSpRecord | |||
private int field_1_shapeId; | |||
private int field_2_flags; | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
int size = 0; | |||
@@ -95,32 +85,20 @@ public class EscherSpRecord | |||
return 8 + 8; | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
return 8 + 8; | |||
} | |||
/** | |||
* @return the 16 bit identifier for this record. | |||
*/ | |||
public short getRecordId() | |||
{ | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
/** | |||
* The short name for this record | |||
*/ | |||
public String getRecordName() | |||
{ | |||
public String getRecordName() { | |||
return "Sp"; | |||
} | |||
/** | |||
* @return the string representing this shape. | |||
*/ |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,7 +14,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.HexDump; | |||
@@ -39,16 +38,7 @@ public class EscherSpgrRecord | |||
private int field_3_rectX2; | |||
private int field_4_rectY2; | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
int size = 0; | |||
@@ -63,16 +53,6 @@ public class EscherSpgrRecord | |||
return 8 + size + bytesRemaining; | |||
} | |||
/** | |||
* This method serializes this escher record into a byte array. | |||
* | |||
* @param offset The offset into <code>data</code> to start writing the record data to. | |||
* @param data The byte array to serialize to. | |||
* @param listener A listener to retrieve start and end callbacks. Use a <code>NullEscherSerailizationListener</code> to ignore these events. | |||
* @return The number of bytes written. | |||
* | |||
* @see NullEscherSerializationListener | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -90,58 +70,30 @@ public class EscherSpgrRecord | |||
return 8 + 16; | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
return 8 + 16; | |||
} | |||
/** | |||
* The 16 bit identifier of this shape group record. | |||
*/ | |||
public short getRecordId() | |||
{ | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
/** | |||
* The short name for this record | |||
*/ | |||
public String getRecordName() | |||
{ | |||
public String getRecordName() { | |||
return "Spgr"; | |||
} | |||
/** | |||
* @return the string representation of this record. | |||
*/ | |||
public String toString() | |||
{ | |||
String nl = System.getProperty("line.separator"); | |||
// String extraData; | |||
// ByteArrayOutputStream b = new ByteArrayOutputStream(); | |||
// try | |||
// { | |||
// HexDump.dump(this.remainingData, 0, b, 0); | |||
// extraData = b.toString(); | |||
// } | |||
// catch ( Exception e ) | |||
// { | |||
// extraData = "error"; | |||
// } | |||
return getClass().getName() + ":" + nl + | |||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + nl + | |||
" Options: 0x" + HexDump.toHex(getOptions()) + nl + | |||
" RectX: " + field_1_rectX1 + nl + | |||
" RectY: " + field_2_rectY1 + nl + | |||
" RectWidth: " + field_3_rectX2 + nl + | |||
" RectHeight: " + field_4_rectY2 + nl; | |||
public String toString() { | |||
return getClass().getName() + ":" + '\n' + | |||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + '\n' + | |||
" Options: 0x" + HexDump.toHex(getOptions()) + '\n' + | |||
" RectX: " + field_1_rectX1 + '\n' + | |||
" RectY: " + field_2_rectY1 + '\n' + | |||
" RectWidth: " + field_3_rectX2 + '\n' + | |||
" RectHeight: " + field_4_rectY2 + '\n'; | |||
} | |||
/** | |||
@@ -203,8 +155,7 @@ public class EscherSpgrRecord | |||
/** | |||
* The starting bottom-right coordinate of child records. | |||
*/ | |||
public void setRectY2( int field_4_rectY2 ) | |||
{ | |||
this.field_4_rectY2 = field_4_rectY2; | |||
public void setRectY2(int rectY2) { | |||
this.field_4_rectY2 = rectY2; | |||
} | |||
} |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,7 +14,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.HexDump; | |||
@@ -39,16 +38,7 @@ public class EscherSplitMenuColorsRecord | |||
private int field_3_color3; | |||
private int field_4_color4; | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
int size = 0; | |||
@@ -62,16 +52,6 @@ public class EscherSplitMenuColorsRecord | |||
return 8 + size + bytesRemaining; | |||
} | |||
/** | |||
* This method serializes this escher record into a byte array. | |||
* | |||
* @param offset The offset into <code>data</code> to start writing the record data to. | |||
* @param data The byte array to serialize to. | |||
* @param listener A listener to retrieve start and end callbacks. Use a <code>NullEscherSerailizationListener</code> to ignore these events. | |||
* @return The number of bytes written. | |||
* | |||
* @see NullEscherSerializationListener | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
// int field_2_numIdClusters = field_5_fileIdClusters.length + 1; | |||
@@ -91,59 +71,31 @@ public class EscherSplitMenuColorsRecord | |||
return getRecordSize(); | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
return 8 + 4 * 4; | |||
} | |||
/** | |||
* @return the 16 bit identifer for this record. | |||
*/ | |||
public short getRecordId() | |||
{ | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
/** | |||
* The short name for this record | |||
*/ | |||
public String getRecordName() | |||
{ | |||
public String getRecordName() { | |||
return "SplitMenuColors"; | |||
} | |||
/** | |||
* @return a string representation of this record. | |||
*/ | |||
public String toString() | |||
{ | |||
String nl = System.getProperty("line.separator"); | |||
// String extraData; | |||
// ByteArrayOutputStream b = new ByteArrayOutputStream(); | |||
// try | |||
// { | |||
// HexDump.dump(this.remainingData, 0, b, 0); | |||
// extraData = b.toString(); | |||
// } | |||
// catch ( Exception e ) | |||
// { | |||
// extraData = "error"; | |||
// } | |||
return getClass().getName() + ":" + nl + | |||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + nl + | |||
" Options: 0x" + HexDump.toHex(getOptions()) + nl + | |||
" Color1: 0x" + HexDump.toHex(field_1_color1) + nl + | |||
" Color2: 0x" + HexDump.toHex(field_2_color2) + nl + | |||
" Color3: 0x" + HexDump.toHex(field_3_color3) + nl + | |||
" Color4: 0x" + HexDump.toHex(field_4_color4) + nl + | |||
public String toString() { | |||
return getClass().getName() + ":" + '\n' + | |||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + '\n' + | |||
" Options: 0x" + HexDump.toHex(getOptions()) + '\n' + | |||
" Color1: 0x" + HexDump.toHex(field_1_color1) + '\n' + | |||
" Color2: 0x" + HexDump.toHex(field_2_color2) + '\n' + | |||
" Color3: 0x" + HexDump.toHex(field_3_color3) + '\n' + | |||
" Color4: 0x" + HexDump.toHex(field_4_color4) + '\n' + | |||
""; | |||
} | |||
public int getColor1() |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,7 +14,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import org.apache.poi.util.HexDump; | |||
@@ -24,7 +23,7 @@ import org.apache.poi.util.RecordFormatException; | |||
/** | |||
* Holds data from the parent application. Most commonly used to store | |||
* text in the format of the parent application, rather than in | |||
* text in the format of the parent application, rather than in | |||
* Escher format. We don't attempt to understand the contents, since | |||
* they will be in the parent's format, not Escher format. | |||
* | |||
@@ -45,16 +44,7 @@ public class EscherTextboxRecord extends EscherRecord | |||
{ | |||
} | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
// Save the data, ready for the calling code to do something | |||
@@ -64,12 +54,6 @@ public class EscherTextboxRecord extends EscherRecord | |||
return bytesRemaining + 8; | |||
} | |||
/** | |||
* Writes this record and any contained records to the supplied byte | |||
* array. | |||
* | |||
* @return the number of bytes written. | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -113,12 +97,6 @@ public class EscherTextboxRecord extends EscherRecord | |||
setData(b,0,b.length); | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
return 8 + thedata.length; | |||
@@ -130,11 +108,7 @@ public class EscherTextboxRecord extends EscherRecord | |||
return super.clone(); | |||
} | |||
/** | |||
* The short name for this record | |||
*/ | |||
public String getRecordName() | |||
{ | |||
public String getRecordName() { | |||
return "ClientTextbox"; | |||
} | |||
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,7 +14,7 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
/** | |||
@@ -23,16 +22,12 @@ package org.apache.poi.ddf; | |||
* | |||
* @author Glen Stampoultzis (glens at apache.org) | |||
*/ | |||
public class NullEscherSerializationListener implements EscherSerializationListener | |||
{ | |||
public void beforeRecordSerialize( int offset, short recordId, EscherRecord record ) | |||
{ | |||
public class NullEscherSerializationListener implements EscherSerializationListener { | |||
public void beforeRecordSerialize(int offset, short recordId, EscherRecord record) { | |||
// do nothing | |||
} | |||
public void afterRecordSerialize( int offset, short recordId, int size, EscherRecord record ) | |||
{ | |||
public void afterRecordSerialize(int offset, short recordId, int size, EscherRecord record) { | |||
// do nothing | |||
} | |||
} |
@@ -1,4 +1,3 @@ | |||
/* ==================================================================== | |||
Licensed to the Apache Software Foundation (ASF) under one or more | |||
contributor license agreements. See the NOTICE file distributed with | |||
@@ -15,47 +14,35 @@ | |||
See the License for the specific language governing permissions and | |||
limitations under the License. | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndian; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.ArrayList; | |||
/** | |||
* This record is used whenever a escher record is encountered that | |||
* we do not explicitly support. | |||
* | |||
* @author Glen Stampoultzis (glens at apache.org) | |||
*/ | |||
public class UnknownEscherRecord extends EscherRecord | |||
{ | |||
public final class UnknownEscherRecord extends EscherRecord { | |||
private static final byte[] NO_BYTES = new byte[0]; | |||
/** The data for this record not including the the 8 byte header */ | |||
private byte[] thedata = NO_BYTES; | |||
private List childRecords = new ArrayList(); | |||
private List<EscherRecord> _childRecords; | |||
public UnknownEscherRecord() | |||
{ | |||
public UnknownEscherRecord() { | |||
_childRecords = new ArrayList<EscherRecord>(); | |||
} | |||
/** | |||
* This method deserializes the record from a byte array. | |||
* | |||
* @param data The byte array containing the escher record information | |||
* @param offset The starting offset into <code>data</code>. | |||
* @param recordFactory May be null since this is not a container record. | |||
* @return The number of bytes read from the byte array. | |||
*/ | |||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory ) | |||
{ | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
if ( isContainerRecord() ) | |||
{ | |||
if (isContainerRecord()) { | |||
int bytesWritten = 0; | |||
thedata = new byte[0]; | |||
offset += 8; | |||
@@ -71,38 +58,24 @@ public class UnknownEscherRecord extends EscherRecord | |||
} | |||
return bytesWritten; | |||
} | |||
else | |||
{ | |||
thedata = new byte[bytesRemaining]; | |||
System.arraycopy( data, offset + 8, thedata, 0, bytesRemaining ); | |||
return bytesRemaining + 8; | |||
} | |||
thedata = new byte[bytesRemaining]; | |||
System.arraycopy( data, offset + 8, thedata, 0, bytesRemaining ); | |||
return bytesRemaining + 8; | |||
} | |||
/** | |||
* Writes this record and any contained records to the supplied byte | |||
* array. | |||
* | |||
* @return the number of bytes written. | |||
*/ | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
LittleEndian.putShort(data, offset, getOptions()); | |||
LittleEndian.putShort(data, offset+2, getRecordId()); | |||
int remainingBytes = thedata.length; | |||
for ( Iterator iterator = getChildRecords().iterator(); iterator.hasNext(); ) | |||
{ | |||
EscherRecord r = (EscherRecord) iterator.next(); | |||
for (EscherRecord r : _childRecords) { | |||
remainingBytes += r.getRecordSize(); | |||
} | |||
LittleEndian.putInt(data, offset+4, remainingBytes); | |||
System.arraycopy(thedata, 0, data, offset+8, thedata.length); | |||
int pos = offset+8+thedata.length; | |||
for ( Iterator iterator = getChildRecords().iterator(); iterator.hasNext(); ) | |||
{ | |||
EscherRecord r = (EscherRecord) iterator.next(); | |||
for (EscherRecord r : _childRecords) { | |||
pos += r.serialize(pos, data, listener ); | |||
} | |||
@@ -110,90 +83,53 @@ public class UnknownEscherRecord extends EscherRecord | |||
return pos - offset; | |||
} | |||
public byte[] getData() | |||
{ | |||
public byte[] getData() { | |||
return thedata; | |||
} | |||
/** | |||
* Returns the number of bytes that are required to serialize this record. | |||
* | |||
* @return Number of bytes | |||
*/ | |||
public int getRecordSize() | |||
{ | |||
public int getRecordSize() { | |||
return 8 + thedata.length; | |||
} | |||
public List getChildRecords() | |||
{ | |||
return childRecords; | |||
public List<EscherRecord> getChildRecords() { | |||
return _childRecords; | |||
} | |||
public void setChildRecords( List childRecords ) | |||
{ | |||
this.childRecords = childRecords; | |||
public void setChildRecords(List<EscherRecord> childRecords) { | |||
_childRecords = childRecords; | |||
} | |||
public Object clone() | |||
{ | |||
public Object clone() { | |||
// shallow clone | |||
return super.clone(); | |||
} | |||
/** | |||
* The short name for this record | |||
*/ | |||
public String getRecordName() | |||
{ | |||
public String getRecordName() { | |||
return "Unknown 0x" + HexDump.toHex(getRecordId()); | |||
} | |||
public String toString() | |||
{ | |||
String nl = System.getProperty( "line.separator" ); | |||
public String toString() { | |||
StringBuffer children = new StringBuffer(); | |||
if ( getChildRecords().size() > 0 ) | |||
{ | |||
children.append( " children: " + nl ); | |||
for ( Iterator iterator = getChildRecords().iterator(); iterator.hasNext(); ) | |||
{ | |||
EscherRecord record = (EscherRecord) iterator.next(); | |||
if (getChildRecords().size() > 0) { | |||
children.append( " children: " + '\n' ); | |||
for (EscherRecord record : _childRecords) { | |||
children.append( record.toString() ); | |||
children.append( nl ); | |||
children.append( '\n' ); | |||
} | |||
} | |||
String theDumpHex = ""; | |||
try | |||
{ | |||
if (thedata.length != 0) | |||
{ | |||
theDumpHex = " Extra Data("+thedata.length+"):" + nl; | |||
theDumpHex += HexDump.dump(thedata, 0, 0); | |||
} | |||
} | |||
catch ( Exception e ) | |||
{ | |||
theDumpHex = "Error!!"; | |||
} | |||
String theDumpHex = HexDump.toHex(thedata, 32); | |||
return getClass().getName() + ":" + nl + | |||
" isContainer: " + isContainerRecord() + nl + | |||
" options: 0x" + HexDump.toHex( getOptions() ) + nl + | |||
" recordId: 0x" + HexDump.toHex( getRecordId() ) + nl + | |||
" numchildren: " + getChildRecords().size() + nl + | |||
return getClass().getName() + ":" + '\n' + | |||
" isContainer: " + isContainerRecord() + '\n' + | |||
" options: 0x" + HexDump.toHex( getOptions() ) + '\n' + | |||
" recordId: 0x" + HexDump.toHex( getRecordId() ) + '\n' + | |||
" numchildren: " + getChildRecords().size() + '\n' + | |||
theDumpHex + | |||
children.toString(); | |||
} | |||
public void addChildRecord( EscherRecord childRecord ) | |||
{ | |||
public void addChildRecord(EscherRecord childRecord) { | |||
getChildRecords().add( childRecord ); | |||
} | |||
} | |||