git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1747090 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_15_BETA2
@@ -27,6 +27,7 @@ import org.apache.poi.poifs.filesystem.DirectoryEntry; | |||
* You will typically find the implementation of | |||
* a given format's text extractor under | |||
* org.apache.poi.[format].extractor . | |||
* | |||
* @see org.apache.poi.hssf.extractor.ExcelExtractor | |||
* @see org.apache.poi.hslf.extractor.PowerPointExtractor | |||
* @see org.apache.poi.hdgf.extractor.VisioTextExtractor | |||
@@ -49,6 +50,8 @@ public abstract class POIOLE2TextExtractor extends POITextExtractor { | |||
* Creates a new text extractor, using the same | |||
* document as another text extractor. Normally | |||
* only used by properties extractors. | |||
* | |||
* @param otherExtractor the extractor which document to be used | |||
*/ | |||
protected POIOLE2TextExtractor(POIOLE2TextExtractor otherExtractor) { | |||
this.document = otherExtractor.document; | |||
@@ -79,7 +82,8 @@ public abstract class POIOLE2TextExtractor extends POITextExtractor { | |||
* | |||
* @return an instance of POIExtractor that can extract meta-data. | |||
*/ | |||
public POITextExtractor getMetadataTextExtractor() { | |||
@Override | |||
public POITextExtractor getMetadataTextExtractor() { | |||
return new HPSFPropertiesExtractor(this); | |||
} | |||
@@ -25,6 +25,7 @@ import java.io.IOException; | |||
* You will typically find the implementation of | |||
* a given format's text extractor under | |||
* org.apache.poi.[format].extractor . | |||
* | |||
* @see org.apache.poi.hssf.extractor.ExcelExtractor | |||
* @see org.apache.poi.hslf.extractor.PowerPointExtractor | |||
* @see org.apache.poi.hdgf.extractor.VisioTextExtractor | |||
@@ -46,11 +47,15 @@ public abstract class POITextExtractor implements Closeable { | |||
* Returns another text extractor, which is able to | |||
* output the textual content of the document | |||
* metadata / properties, such as author and title. | |||
* | |||
* @return the metadata and text extractor | |||
*/ | |||
public abstract POITextExtractor getMetadataTextExtractor(); | |||
/** | |||
* Used to ensure file handle cleanup. | |||
* | |||
* @param fs filesystem to close | |||
*/ | |||
public void setFilesystem(Closeable fs) { | |||
fsToClose = fs; | |||
@@ -63,7 +68,8 @@ public abstract class POITextExtractor implements Closeable { | |||
* | |||
* The Extractor cannot be used after close has been called. | |||
*/ | |||
public void close() throws IOException { | |||
@Override | |||
public void close() throws IOException { | |||
if(fsToClose != null) { | |||
fsToClose.close(); | |||
} |
@@ -16,7 +16,11 @@ | |||
==================================================================== */ | |||
package org.apache.poi.ddf; | |||
import java.util.*; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.Comparator; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndian; | |||
@@ -24,9 +28,6 @@ import org.apache.poi.util.LittleEndian; | |||
/** | |||
* Common abstract class for {@link EscherOptRecord} and | |||
* {@link EscherTertiaryOptRecord} | |||
* | |||
* @author Sergey Vladimirov (vlsergey {at} gmail {dot} com) | |||
* @author Glen Stampoultzis | |||
*/ | |||
public abstract class AbstractEscherOptRecord extends EscherRecord | |||
{ | |||
@@ -40,6 +41,7 @@ public abstract class AbstractEscherOptRecord extends EscherRecord | |||
properties.add( prop ); | |||
} | |||
@Override | |||
public int fillFields( byte[] data, int offset, | |||
EscherRecordFactory recordFactory ) | |||
{ | |||
@@ -54,6 +56,8 @@ public abstract class AbstractEscherOptRecord extends EscherRecord | |||
/** | |||
* The list of properties stored by this record. | |||
* | |||
* @return the list of properties | |||
*/ | |||
public List<EscherProperty> getEscherProperties() | |||
{ | |||
@@ -62,12 +66,16 @@ public abstract class AbstractEscherOptRecord extends EscherRecord | |||
/** | |||
* The list of properties stored by this record. | |||
* | |||
* @param index the ordinal index of the property | |||
* @return the escher property | |||
*/ | |||
public EscherProperty getEscherProperty( int index ) | |||
{ | |||
return properties.get( index ); | |||
} | |||
private int getPropertiesSize() | |||
{ | |||
int totalSize = 0; | |||
@@ -99,6 +107,7 @@ public abstract class AbstractEscherOptRecord extends EscherRecord | |||
return null; | |||
} | |||
@Override | |||
public int serialize( int offset, byte[] data, | |||
EscherSerializationListener listener ) | |||
{ | |||
@@ -127,6 +136,7 @@ public abstract class AbstractEscherOptRecord extends EscherRecord | |||
{ | |||
Collections.sort( properties, new Comparator<EscherProperty>() | |||
{ | |||
@Override | |||
public int compare( EscherProperty p1, EscherProperty p2 ) | |||
{ | |||
short s1 = p1.getPropertyNumber(); | |||
@@ -166,6 +176,7 @@ public abstract class AbstractEscherOptRecord extends EscherRecord | |||
/** | |||
* Retrieve the string representation of this record. | |||
*/ | |||
@Override | |||
public String toString() | |||
{ | |||
String nl = System.getProperty( "line.separator" ); |
@@ -26,9 +26,6 @@ import org.apache.poi.util.LittleEndian; | |||
/** | |||
* Generates escher records when provided the byte array containing those records. | |||
* | |||
* @author Glen Stampoultzis | |||
* @author Nick Burch (nick at torchbox . com) | |||
* | |||
* @see EscherRecordFactory | |||
*/ | |||
public class DefaultEscherRecordFactory implements EscherRecordFactory { | |||
@@ -56,6 +53,7 @@ public class DefaultEscherRecordFactory implements EscherRecordFactory { | |||
* @param offset The starting offset into the byte array | |||
* @return The generated escher record | |||
*/ | |||
@Override | |||
public EscherRecord createRecord(byte[] data, int offset) { | |||
short options = LittleEndian.getShort( data, offset ); | |||
short recordId = LittleEndian.getShort( data, offset + 2 ); |
@@ -26,8 +26,6 @@ import org.apache.poi.util.LittleEndian; | |||
/** | |||
* Escher array properties are the most wierd construction ever invented | |||
* with all sorts of special cases. I'm hopeful I've got them all. | |||
* | |||
* @author Glen Stampoultzis (glens at superlinksoftware.com) | |||
*/ | |||
public final class EscherArrayProperty extends EscherComplexProperty implements Iterable<byte[]> { | |||
/** | |||
@@ -120,6 +118,7 @@ public final class EscherArrayProperty extends EscherComplexProperty implements | |||
System.arraycopy( element, 0, _complexData, FIXED_SIZE + index * actualSize, actualSize); | |||
} | |||
@Override | |||
public String toString() { | |||
StringBuffer results = new StringBuffer(); | |||
results.append(" {EscherArrayProperty:" + '\n'); | |||
@@ -138,6 +137,7 @@ public final class EscherArrayProperty extends EscherComplexProperty implements | |||
+ ", data: " + '\n' + results.toString(); | |||
} | |||
@Override | |||
public String toXml(String tab){ | |||
StringBuilder builder = new StringBuilder(); | |||
builder.append(tab).append("<").append(getClass().getSimpleName()).append(" id=\"0x").append(HexDump.toHex(getId())) | |||
@@ -185,6 +185,7 @@ public final class EscherArrayProperty extends EscherComplexProperty implements | |||
* Needs special code to handle the case when the size doesn't | |||
* include the size of the header block | |||
*/ | |||
@Override | |||
public int serializeSimplePart(byte[] data, int pos) { | |||
LittleEndian.putShort(data, pos, getId()); | |||
int recordSize = _complexData.length; | |||
@@ -199,25 +200,29 @@ public final class EscherArrayProperty extends EscherComplexProperty implements | |||
* 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) { | |||
private static int getActualSizeOfElements(short sizeOfElements) { | |||
if (sizeOfElements < 0) { | |||
return (short) ( ( -sizeOfElements ) >> 2 ); | |||
} | |||
return sizeOfElements; | |||
} | |||
@Override | |||
public Iterator<byte[]> iterator() { | |||
return new Iterator<byte[]>(){ | |||
int idx = 0; | |||
@Override | |||
public boolean hasNext() { | |||
return (idx < getNumberOfElementsInArray()); | |||
} | |||
@Override | |||
public byte[] next() { | |||
if (!hasNext()) throw new NoSuchElementException(); | |||
return getElement(idx++); | |||
} | |||
@Override | |||
public void remove() { | |||
throw new UnsupportedOperationException("not yet implemented"); | |||
} |
@@ -25,7 +25,6 @@ import org.apache.poi.util.LittleEndian; | |||
* extra information about the blip. A blip record is actually stored inside | |||
* the BSE record even though the BSE record isn't actually a container record. | |||
* | |||
* @author Glen Stampoultzis | |||
* @see EscherBlipRecord | |||
*/ | |||
public final class EscherBSERecord extends EscherRecord { | |||
@@ -56,6 +55,7 @@ public final class EscherBSERecord extends EscherRecord { | |||
private byte[] _remainingData = new byte[0]; | |||
@Override | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
@@ -87,6 +87,7 @@ public final class EscherBSERecord extends EscherRecord { | |||
} | |||
@Override | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -124,6 +125,7 @@ public final class EscherBSERecord extends EscherRecord { | |||
return pos - offset; | |||
} | |||
@Override | |||
public int getRecordSize() { | |||
int field_12_size = 0; | |||
if(field_12_blipRecord != null) { | |||
@@ -137,6 +139,7 @@ public final class EscherBSERecord extends EscherRecord { | |||
1 + 1 + field_12_size + remaining_size; | |||
} | |||
@Override | |||
public String getRecordName() { | |||
return "BSE"; | |||
} | |||
@@ -144,6 +147,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* The expected blip type under windows (failure to match this blip type will result in | |||
* Excel converting to this format). | |||
* | |||
* @return win32 blip type | |||
*/ | |||
public byte getBlipTypeWin32() { | |||
return field_1_blipTypeWin32; | |||
@@ -151,6 +156,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* Set the expected win32 blip type | |||
* | |||
* @param blipTypeWin32 win32 blip type | |||
*/ | |||
public void setBlipTypeWin32(byte blipTypeWin32) { | |||
field_1_blipTypeWin32 = blipTypeWin32; | |||
@@ -159,6 +166,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* The expected blip type under MacOS (failure to match this blip type will result in | |||
* Excel converting to this format). | |||
* | |||
* @return MacOS blip type | |||
*/ | |||
public byte getBlipTypeMacOS() { | |||
return field_2_blipTypeMacOS; | |||
@@ -166,6 +175,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* Set the expected MacOS blip type | |||
* | |||
* @param blipTypeMacOS MacOS blip type | |||
*/ | |||
public void setBlipTypeMacOS(byte blipTypeMacOS) { | |||
field_2_blipTypeMacOS = blipTypeMacOS; | |||
@@ -173,6 +184,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* 16 byte MD4 checksum. | |||
* | |||
* @return 16 byte MD4 checksum | |||
*/ | |||
public byte[] getUid() { | |||
return field_3_uid; | |||
@@ -180,6 +193,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* 16 byte MD4 checksum. | |||
* | |||
* @param uid 16 byte MD4 checksum | |||
*/ | |||
public void setUid(byte[] uid) { | |||
if (uid == null || uid.length != 16) { | |||
@@ -190,6 +205,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* unused | |||
* | |||
* @return an unknown tag | |||
*/ | |||
public short getTag() { | |||
return field_4_tag; | |||
@@ -197,6 +214,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* unused | |||
* | |||
* @param tag unknown tag | |||
*/ | |||
public void setTag(short tag) { | |||
field_4_tag = tag; | |||
@@ -204,6 +223,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* Blip size in stream. | |||
* | |||
* @return the blip size | |||
*/ | |||
public int getSize() { | |||
return field_5_size; | |||
@@ -211,6 +232,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* Blip size in stream. | |||
* | |||
* @param size blip size | |||
*/ | |||
public void setSize(int size) { | |||
field_5_size = size; | |||
@@ -218,6 +241,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* The reference count of this blip. | |||
* | |||
* @return the reference count | |||
*/ | |||
public int getRef() { | |||
return field_6_ref; | |||
@@ -225,6 +250,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* The reference count of this blip. | |||
* | |||
* @param ref the reference count | |||
*/ | |||
public void setRef(int ref) { | |||
field_6_ref = ref; | |||
@@ -232,6 +259,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* File offset in the delay stream. | |||
* | |||
* @return the file offset | |||
*/ | |||
public int getOffset() { | |||
return field_7_offset; | |||
@@ -239,6 +268,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* File offset in the delay stream. | |||
* | |||
* @param offset the file offset | |||
*/ | |||
public void setOffset(int offset) { | |||
field_7_offset = offset; | |||
@@ -246,6 +277,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* Defines the way this blip is used. | |||
* | |||
* @return the blip usage | |||
*/ | |||
public byte getUsage() { | |||
return field_8_usage; | |||
@@ -253,6 +286,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* Defines the way this blip is used. | |||
* | |||
* @param usage the blip usae | |||
*/ | |||
public void setUsage(byte usage) { | |||
field_8_usage = usage; | |||
@@ -260,6 +295,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* The length in characters of the blip name. | |||
* | |||
* @return the blip name length | |||
*/ | |||
public byte getName() { | |||
return field_9_name; | |||
@@ -267,6 +304,8 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* The length in characters of the blip name. | |||
* | |||
* @param name the blip name length | |||
*/ | |||
public void setName(byte name) { | |||
field_9_name = name; | |||
@@ -314,6 +353,7 @@ public final class EscherBSERecord extends EscherRecord { | |||
} | |||
} | |||
@Override | |||
public String toString() { | |||
String extraData = _remainingData == null ? null : HexDump.toHex(_remainingData, 32); | |||
return getClass().getName() + ":" + '\n' + | |||
@@ -356,6 +396,10 @@ public final class EscherBSERecord extends EscherRecord { | |||
/** | |||
* Retrieve the string representation given a blip id. | |||
* | |||
* @param b the blip type byte-encoded | |||
* | |||
* @return the blip type as string | |||
*/ | |||
public static String getBlipType(byte b) { | |||
switch (b) { |
@@ -20,9 +20,6 @@ package org.apache.poi.ddf; | |||
import org.apache.poi.util.HexDump; | |||
import org.apache.poi.util.LittleEndian; | |||
/** | |||
* @author Glen Stampoultzis | |||
*/ | |||
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; | |||
@@ -33,6 +30,7 @@ public class EscherBitmapBlip extends EscherBlipRecord { | |||
private final byte[] field_1_UID = new byte[16]; | |||
private byte field_2_marker = (byte) 0xFF; | |||
@Override | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesAfterHeader = readHeader( data, offset ); | |||
int pos = offset + HEADER_SIZE; | |||
@@ -46,33 +44,44 @@ public class EscherBitmapBlip extends EscherBlipRecord { | |||
return bytesAfterHeader + HEADER_SIZE; | |||
} | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
listener.beforeRecordSerialize(offset, getRecordId(), this); | |||
@Override | |||
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() ); | |||
LittleEndian.putInt( data, offset + 4, getRecordSize() - HEADER_SIZE ); | |||
int pos = offset + HEADER_SIZE; | |||
LittleEndian.putShort( data, offset, getOptions() ); | |||
LittleEndian.putShort( data, offset + 2, getRecordId() ); | |||
LittleEndian.putInt( data, offset + 4, getRecordSize() - HEADER_SIZE ); | |||
int pos = offset + HEADER_SIZE; | |||
System.arraycopy( field_1_UID, 0, data, pos, 16 ); | |||
data[pos + 16] = field_2_marker; | |||
System.arraycopy( field_pictureData, 0, data, pos + 17, field_pictureData.length ); | |||
System.arraycopy( field_1_UID, 0, data, pos, 16 ); | |||
data[pos + 16] = field_2_marker; | |||
System.arraycopy( field_pictureData, 0, data, pos + 17, field_pictureData.length ); | |||
listener.afterRecordSerialize(offset + getRecordSize(), getRecordId(), getRecordSize(), this); | |||
return HEADER_SIZE + 16 + 1 + field_pictureData.length; | |||
} | |||
listener.afterRecordSerialize(offset + getRecordSize(), getRecordId(), getRecordSize(), this); | |||
return HEADER_SIZE + 16 + 1 + field_pictureData.length; | |||
} | |||
public int getRecordSize() | |||
{ | |||
return 8 + 16 + 1 + field_pictureData.length; | |||
} | |||
@Override | |||
public int getRecordSize() { | |||
return 8 + 16 + 1 + field_pictureData.length; | |||
} | |||
public byte[] getUID() | |||
{ | |||
/** | |||
* Gets the first MD4, that specifies the unique identifier of the | |||
* uncompressed blip data | |||
* | |||
* @return the first MD4 | |||
*/ | |||
public byte[] getUID() { | |||
return field_1_UID; | |||
} | |||
/** | |||
* Sets the first MD4, that specifies the unique identifier of the | |||
* uncompressed blip data | |||
* | |||
* @param field_1_UID the first MD4 | |||
*/ | |||
public void setUID( byte[] field_1_UID ) { | |||
if (field_1_UID == null || field_1_UID.length != 16) { | |||
throw new IllegalArgumentException("field_1_UID must be byte[16]"); | |||
@@ -80,29 +89,39 @@ public class EscherBitmapBlip extends EscherBlipRecord { | |||
System.arraycopy(field_1_UID, 0, this.field_1_UID , 0, 16); | |||
} | |||
public byte getMarker() | |||
{ | |||
/** | |||
* Gets an unsigned integer that specifies an application-defined internal | |||
* resource tag. This value MUST be 0xFF for external files. | |||
* | |||
* @return the marker | |||
*/ | |||
public byte getMarker() { | |||
return field_2_marker; | |||
} | |||
public void setMarker( byte field_2_marker ) | |||
{ | |||
/** | |||
* Sets an unsigned integer that specifies an application-defined internal | |||
* resource tag. This value MUST be 0xFF for external files. | |||
* | |||
* @param field_2_marker the marker | |||
*/ | |||
public void setMarker( byte field_2_marker ) { | |||
this.field_2_marker = field_2_marker; | |||
} | |||
public String toString() | |||
{ | |||
@Override | |||
public String toString() { | |||
String nl = System.getProperty( "line.separator" ); | |||
String extraData = HexDump.dump(this.field_pictureData, 0, 0); | |||
return getClass().getName() + ":" + nl + | |||
" RecordId: 0x" + HexDump.toHex( getRecordId() ) + nl + | |||
" Version: 0x" + HexDump.toHex( getVersion() ) + nl + | |||
" Instance: 0x" + HexDump.toHex( getInstance() ) + nl + | |||
" UID: 0x" + HexDump.toHex( field_1_UID ) + nl + | |||
" Marker: 0x" + HexDump.toHex( field_2_marker ) + nl + | |||
" Extra Data:" + nl + extraData; | |||
" RecordId: 0x" + HexDump.toHex( getRecordId() ) + nl + | |||
" Version: 0x" + HexDump.toHex( getVersion() ) + nl + | |||
" Instance: 0x" + HexDump.toHex( getInstance() ) + nl + | |||
" UID: 0x" + HexDump.toHex( field_1_UID ) + nl + | |||
" Marker: 0x" + HexDump.toHex( field_2_marker ) + nl + | |||
" Extra Data:" + nl + extraData; | |||
} | |||
@Override | |||
@@ -110,9 +129,9 @@ public class EscherBitmapBlip extends EscherBlipRecord { | |||
String extraData = HexDump.dump(this.field_pictureData, 0, 0); | |||
StringBuilder builder = new StringBuilder(); | |||
builder.append(tab).append(formatXmlRecordHeader(getClass().getSimpleName(), HexDump.toHex(getRecordId()), HexDump.toHex(getVersion()), HexDump.toHex(getInstance()))) | |||
.append(tab).append("\t").append("<UID>0x").append(HexDump.toHex(field_1_UID)).append("</UID>\n") | |||
.append(tab).append("\t").append("<Marker>0x").append(HexDump.toHex(field_2_marker)).append("</Marker>\n") | |||
.append(tab).append("\t").append("<ExtraData>").append(extraData).append("</ExtraData>\n"); | |||
.append(tab).append("\t").append("<UID>0x").append(HexDump.toHex(field_1_UID)).append("</UID>\n") | |||
.append(tab).append("\t").append("<Marker>0x").append(HexDump.toHex(field_2_marker)).append("</Marker>\n") | |||
.append(tab).append("\t").append("<ExtraData>").append(extraData).append("</ExtraData>\n"); | |||
builder.append(tab).append("</").append(getClass().getSimpleName()).append(">\n"); | |||
return builder.toString(); | |||
} |
@@ -20,10 +20,7 @@ package org.apache.poi.ddf; | |||
import org.apache.poi.util.LittleEndian; | |||
import org.apache.poi.util.HexDump; | |||
/** | |||
* @author Glen Stampoultzis | |||
*/ | |||
public class EscherBlipRecord extends EscherRecord { // TODO - instantiable superclass | |||
public class EscherBlipRecord extends EscherRecord { | |||
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"; | |||
@@ -35,6 +32,7 @@ public class EscherBlipRecord extends EscherRecord { // TODO - instantiable supe | |||
public EscherBlipRecord() { | |||
} | |||
@Override | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesAfterHeader = readHeader( data, offset ); | |||
int pos = offset + HEADER_SIZE; | |||
@@ -45,6 +43,7 @@ public class EscherBlipRecord extends EscherRecord { // TODO - instantiable supe | |||
return bytesAfterHeader + 8; | |||
} | |||
@Override | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize(offset, getRecordId(), this); | |||
@@ -57,18 +56,30 @@ public class EscherBlipRecord extends EscherRecord { // TODO - instantiable supe | |||
return field_pictureData.length + 4; | |||
} | |||
@Override | |||
public int getRecordSize() { | |||
return field_pictureData.length + HEADER_SIZE; | |||
} | |||
@Override | |||
public String getRecordName() { | |||
return "Blip"; | |||
} | |||
/** | |||
* Gets the picture data bytes | |||
* | |||
* @return the picture data | |||
*/ | |||
public byte[] getPicturedata() { | |||
return field_pictureData; | |||
} | |||
/** | |||
* Sets the picture data bytes | |||
* | |||
* @param pictureData the picture data | |||
*/ | |||
public void setPictureData(byte[] pictureData) { | |||
if (pictureData == null) { | |||
throw new IllegalArgumentException("picture data can't be null"); | |||
@@ -76,6 +87,7 @@ public class EscherBlipRecord extends EscherRecord { // TODO - instantiable supe | |||
field_pictureData = pictureData.clone(); | |||
} | |||
@Override | |||
public String toString() { | |||
String extraData = HexDump.toHex(field_pictureData, 32); | |||
return getClass().getName() + ":" + '\n' + |
@@ -25,7 +25,6 @@ import org.apache.poi.util.HexDump; | |||
* of the properties marked as boolean seem to actually contain special values. In other words | |||
* they're not true booleans. | |||
* | |||
* @author Glen Stampoultzis | |||
* @see EscherSimpleProperty | |||
* @see EscherProperty | |||
*/ | |||
@@ -45,6 +44,8 @@ public class EscherBoolProperty | |||
/** | |||
* Whether this boolean property is true | |||
* | |||
* @return the boolean property value | |||
*/ | |||
public boolean isTrue() | |||
{ | |||
@@ -53,6 +54,10 @@ public class EscherBoolProperty | |||
/** | |||
* Whether this boolean property is false | |||
* | |||
* @return true, if this boolean property is false | |||
* | |||
* @deprecated use !isTrue() instead, planed to be removed in POI 3.17 | |||
*/ | |||
public boolean isFalse() | |||
{ | |||
@@ -67,6 +72,7 @@ public class EscherBoolProperty | |||
// + ", value: " + (getValue() != 0); | |||
// } | |||
@Override | |||
public String toXml(String tab){ | |||
StringBuilder builder = new StringBuilder(); | |||
builder.append(tab).append("<").append(getClass().getSimpleName()).append(" id=\"0x").append(HexDump.toHex(getId())) |
@@ -25,7 +25,6 @@ import org.apache.poi.util.LittleEndian; | |||
* The escher child achor record is used to specify the position of a shape under an | |||
* existing group. The first level of shape records use a EscherClientAnchor record instead. | |||
* | |||
* @author Glen Stampoultzis | |||
* @see EscherChildAnchorRecord | |||
*/ | |||
public class EscherChildAnchorRecord | |||
@@ -39,6 +38,7 @@ public class EscherChildAnchorRecord | |||
private int field_3_dx2; | |||
private int field_4_dy2; | |||
@Override | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
@@ -63,6 +63,7 @@ public class EscherChildAnchorRecord | |||
return 8 + size; | |||
} | |||
@Override | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
int pos = offset; | |||
@@ -78,15 +79,18 @@ public class EscherChildAnchorRecord | |||
return pos - offset; | |||
} | |||
@Override | |||
public int getRecordSize() | |||
{ | |||
return 8 + 4 * 4; | |||
} | |||
@Override | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
@Override | |||
public String getRecordName() { | |||
return "ChildAnchor"; | |||
} | |||
@@ -95,6 +99,7 @@ public class EscherChildAnchorRecord | |||
/** | |||
* The string representation of this record | |||
*/ | |||
@Override | |||
public String toString() | |||
{ | |||
String nl = System.getProperty("line.separator"); | |||
@@ -124,6 +129,8 @@ public class EscherChildAnchorRecord | |||
/** | |||
* Retrieves offset within the parent coordinate space for the top left point. | |||
* | |||
* @return the x offset of the top left point | |||
*/ | |||
public int getDx1() | |||
{ | |||
@@ -132,6 +139,8 @@ public class EscherChildAnchorRecord | |||
/** | |||
* Sets offset within the parent coordinate space for the top left point. | |||
* | |||
* @param field_1_dx1 the x offset of the top left point | |||
*/ | |||
public void setDx1( int field_1_dx1 ) | |||
{ | |||
@@ -140,6 +149,8 @@ public class EscherChildAnchorRecord | |||
/** | |||
* Gets offset within the parent coordinate space for the top left point. | |||
* | |||
* @return the y offset of the top left point | |||
*/ | |||
public int getDy1() | |||
{ | |||
@@ -148,6 +159,8 @@ public class EscherChildAnchorRecord | |||
/** | |||
* Sets offset within the parent coordinate space for the top left point. | |||
* | |||
* @param field_2_dy1 the y offset of the top left point | |||
*/ | |||
public void setDy1( int field_2_dy1 ) | |||
{ | |||
@@ -156,6 +169,8 @@ public class EscherChildAnchorRecord | |||
/** | |||
* Retrieves offset within the parent coordinate space for the bottom right point. | |||
* | |||
* @return the x offset of the bottom right point | |||
*/ | |||
public int getDx2() | |||
{ | |||
@@ -164,6 +179,8 @@ public class EscherChildAnchorRecord | |||
/** | |||
* Sets offset within the parent coordinate space for the bottom right point. | |||
* | |||
* @param field_3_dx2 the x offset of the bottom right point | |||
*/ | |||
public void setDx2( int field_3_dx2 ) | |||
{ | |||
@@ -172,6 +189,8 @@ public class EscherChildAnchorRecord | |||
/** | |||
* Gets the offset within the parent coordinate space for the bottom right point. | |||
* | |||
* @return the y offset of the bottom right point | |||
*/ | |||
public int getDy2() | |||
{ | |||
@@ -180,6 +199,8 @@ public class EscherChildAnchorRecord | |||
/** | |||
* Sets the offset within the parent coordinate space for the bottom right point. | |||
* | |||
* @param field_4_dy2 the y offset of the bottom right point | |||
*/ | |||
public void setDy2( int field_4_dy2 ) | |||
{ |
@@ -26,7 +26,6 @@ import org.apache.poi.util.LittleEndian; | |||
* of the actual size of the cell. The EscherClientAnchorRecord only applies to the top-most | |||
* shapes. Shapes contained in groups are bound using the EscherChildAnchorRecords. | |||
* | |||
* @author Glen Stampoultzis | |||
* @see EscherChildAnchorRecord | |||
*/ | |||
public class EscherClientAnchorRecord | |||
@@ -55,6 +54,7 @@ public class EscherClientAnchorRecord | |||
private byte[] remainingData = new byte[0]; | |||
private boolean shortRecord = false; | |||
@Override | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
@@ -89,6 +89,7 @@ public class EscherClientAnchorRecord | |||
return 8 + size + bytesRemaining; | |||
} | |||
@Override | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -116,15 +117,18 @@ public class EscherClientAnchorRecord | |||
return pos - offset; | |||
} | |||
@Override | |||
public int getRecordSize() | |||
{ | |||
return 8 + (shortRecord ? 8 : 18) + (remainingData == null ? 0 : remainingData.length); | |||
} | |||
@Override | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
@Override | |||
public String getRecordName() { | |||
return "ClientAnchor"; | |||
} | |||
@@ -134,6 +138,7 @@ public class EscherClientAnchorRecord | |||
* | |||
* @return A string | |||
*/ | |||
@Override | |||
public String toString() | |||
{ | |||
String nl = System.getProperty("line.separator"); | |||
@@ -174,6 +179,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells. | |||
* | |||
* @return the move/size flag | |||
*/ | |||
public short getFlag() | |||
{ | |||
@@ -182,6 +189,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells. | |||
* | |||
* @param field_1_flag the move/size flag | |||
*/ | |||
public void setFlag( short field_1_flag ) | |||
{ | |||
@@ -190,6 +199,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* The column number for the top-left position. 0 based. | |||
* | |||
* @return the column number of the top-left corner | |||
*/ | |||
public short getCol1() | |||
{ | |||
@@ -198,6 +209,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* The column number for the top-left position. 0 based. | |||
* | |||
* @param field_2_col1 the column number of the top-left corner | |||
*/ | |||
public void setCol1( short field_2_col1 ) | |||
{ | |||
@@ -206,6 +219,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* The x offset within the top-left cell. Range is from 0 to 1023. | |||
* | |||
* @return the x offset of the top-left corner | |||
*/ | |||
public short getDx1() | |||
{ | |||
@@ -214,6 +229,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* The x offset within the top-left cell. Range is from 0 to 1023. | |||
* | |||
* @param field_3_dx1 the x offset of the top-left corner | |||
*/ | |||
public void setDx1( short field_3_dx1 ) | |||
{ | |||
@@ -222,6 +239,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* The row number for the top-left corner of the shape. | |||
* | |||
* @return the row number of the top-left corner | |||
*/ | |||
public short getRow1() | |||
{ | |||
@@ -229,7 +248,9 @@ public class EscherClientAnchorRecord | |||
} | |||
/** | |||
* The row number for the top-left corner of the shape. | |||
* The row number of the top-left corner of the shape. | |||
* | |||
* @param field_4_row1 the row number of the top-left corner | |||
*/ | |||
public void setRow1( short field_4_row1 ) | |||
{ | |||
@@ -238,6 +259,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* The y offset within the top-left corner of the current shape. | |||
* | |||
* @return the y offset of the top-left corner | |||
*/ | |||
public short getDy1() | |||
{ | |||
@@ -246,6 +269,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* The y offset within the top-left corner of the current shape. | |||
* | |||
* @param field_5_dy1 the y offset of the top-left corner | |||
*/ | |||
public void setDy1( short field_5_dy1 ) | |||
{ | |||
@@ -255,6 +280,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* The column of the bottom right corner of this shape. | |||
* | |||
* @return the column of the bottom right corner | |||
*/ | |||
public short getCol2() | |||
{ | |||
@@ -263,6 +290,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* The column of the bottom right corner of this shape. | |||
* | |||
* @param field_6_col2 the column of the bottom right corner | |||
*/ | |||
public void setCol2( short field_6_col2 ) | |||
{ | |||
@@ -272,6 +301,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* The x offset withing the cell for the bottom-right corner of this shape. | |||
* | |||
* @return the x offset of the bottom-right corner | |||
*/ | |||
public short getDx2() | |||
{ | |||
@@ -280,6 +311,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* The x offset withing the cell for the bottom-right corner of this shape. | |||
* | |||
* @param field_7_dx2 the x offset of the bottom-right corner | |||
*/ | |||
public void setDx2( short field_7_dx2 ) | |||
{ | |||
@@ -289,6 +322,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* The row number for the bottom-right corner of the current shape. | |||
* | |||
* @return the row number for the bottom-right corner | |||
*/ | |||
public short getRow2() | |||
{ | |||
@@ -297,6 +332,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* The row number for the bottom-right corner of the current shape. | |||
* | |||
* @param field_8_row2 the row number for the bottom-right corner | |||
*/ | |||
public void setRow2( short field_8_row2 ) | |||
{ | |||
@@ -306,6 +343,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* The y offset withing the cell for the bottom-right corner of this shape. | |||
* | |||
* @return the y offset of the bottom-right corner | |||
*/ | |||
public short getDy2() | |||
{ | |||
@@ -314,6 +353,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* The y offset withing the cell for the bottom-right corner of this shape. | |||
* | |||
* @param field_9_dy2 the y offset of the bottom-right corner | |||
*/ | |||
public void setDy2( short field_9_dy2 ) | |||
{ | |||
@@ -323,6 +364,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* Any remaining data in the record | |||
* | |||
* @return the remaining bytes | |||
*/ | |||
public byte[] getRemainingData() | |||
{ | |||
@@ -331,6 +374,8 @@ public class EscherClientAnchorRecord | |||
/** | |||
* Any remaining data in the record | |||
* | |||
* @param remainingData the remaining bytes | |||
*/ | |||
public void setRemainingData( byte[] remainingData ) { | |||
if (remainingData == null) { |
@@ -24,8 +24,6 @@ import org.apache.poi.util.LittleEndian; | |||
/** | |||
* The EscherClientDataRecord is used to store client specific data about the position of a | |||
* shape within a container. | |||
* | |||
* @author Glen Stampoultzis | |||
*/ | |||
public class EscherClientDataRecord | |||
extends EscherRecord | |||
@@ -35,6 +33,7 @@ public class EscherClientDataRecord | |||
private byte[] remainingData; | |||
@Override | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
@@ -43,6 +42,7 @@ public class EscherClientDataRecord | |||
return 8 + bytesRemaining; | |||
} | |||
@Override | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -57,15 +57,18 @@ public class EscherClientDataRecord | |||
return pos - offset; | |||
} | |||
@Override | |||
public int getRecordSize() | |||
{ | |||
return 8 + (remainingData == null ? 0 : remainingData.length); | |||
} | |||
@Override | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
@Override | |||
public String getRecordName() { | |||
return "ClientData"; | |||
} | |||
@@ -73,6 +76,7 @@ public class EscherClientDataRecord | |||
/** | |||
* Returns the string representation of this record. | |||
*/ | |||
@Override | |||
public String toString() | |||
{ | |||
String nl = System.getProperty("line.separator"); | |||
@@ -99,6 +103,8 @@ public class EscherClientDataRecord | |||
/** | |||
* Any data recording this record. | |||
* | |||
* @return the remaining bytes | |||
*/ | |||
public byte[] getRemainingData() | |||
{ | |||
@@ -107,6 +113,8 @@ public class EscherClientDataRecord | |||
/** | |||
* Any data recording this record. | |||
* | |||
* @param remainingData the remaining bytes | |||
*/ | |||
public void setRemainingData( byte[] remainingData ) { | |||
this.remainingData = (remainingData == null) |
@@ -66,6 +66,7 @@ public class EscherComplexProperty extends EscherProperty { | |||
/** | |||
* Serializes the simple part of this property. i.e. the first 6 bytes. | |||
*/ | |||
@Override | |||
public int serializeSimplePart(byte[] data, int pos) { | |||
LittleEndian.putShort(data, pos, getId()); | |||
LittleEndian.putInt(data, pos + 2, _complexData.length); | |||
@@ -79,6 +80,7 @@ public class EscherComplexProperty extends EscherProperty { | |||
* @param pos The offset within data to start serializing to. | |||
* @return The number of bytes serialized. | |||
*/ | |||
@Override | |||
public int serializeComplexPart(byte[] data, int pos) { | |||
System.arraycopy(_complexData, 0, data, pos, _complexData.length); | |||
return _complexData.length; | |||
@@ -86,6 +88,8 @@ public class EscherComplexProperty extends EscherProperty { | |||
/** | |||
* Get the complex data value. | |||
* | |||
* @return the complex bytes | |||
*/ | |||
public byte[] getComplexData() { | |||
return _complexData; | |||
@@ -97,6 +101,7 @@ public class EscherComplexProperty extends EscherProperty { | |||
* @param o The object to compare to. | |||
* @return True if the objects are equal. | |||
*/ | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
@@ -117,10 +122,12 @@ public class EscherComplexProperty extends EscherProperty { | |||
* | |||
* @return Number of bytes | |||
*/ | |||
@Override | |||
public int getPropertySize() { | |||
return 6 + _complexData.length; | |||
} | |||
@Override | |||
public int hashCode() { | |||
return getId() * 11; | |||
} | |||
@@ -128,6 +135,7 @@ public class EscherComplexProperty extends EscherProperty { | |||
/** | |||
* Retrieves the string representation for this property. | |||
*/ | |||
@Override | |||
public String toString() { | |||
String dataStr = HexDump.toHex( _complexData, 32); | |||
@@ -138,6 +146,7 @@ public class EscherComplexProperty extends EscherProperty { | |||
+ ", data: " + System.getProperty("line.separator") + dataStr; | |||
} | |||
@Override | |||
public String toXml(String tab){ | |||
StringBuilder builder = new StringBuilder(); | |||
builder.append(tab).append("<").append(getClass().getSimpleName()).append(" id=\"0x").append(HexDump.toHex(getId())) |
@@ -30,8 +30,6 @@ import org.apache.poi.util.POILogger; | |||
* The container records themselves never store any information beyond | |||
* the standard header used by all escher records. This one record is | |||
* used to represent many different types of records. | |||
* | |||
* @author Glen Stampoultzis | |||
*/ | |||
public final class EscherContainerRecord extends EscherRecord { | |||
public static final short DGG_CONTAINER = (short)0xF000; | |||
@@ -41,7 +39,7 @@ public final class EscherContainerRecord extends EscherRecord { | |||
public static final short SP_CONTAINER = (short)0xF004; | |||
public static final short SOLVER_CONTAINER = (short)0xF005; | |||
private static POILogger log = POILogFactory.getLogger(EscherContainerRecord.class); | |||
private static final POILogger log = POILogFactory.getLogger(EscherContainerRecord.class); | |||
/** | |||
* in case if document contains any charts we have such document structure: | |||
@@ -69,6 +67,7 @@ public final class EscherContainerRecord extends EscherRecord { | |||
private final List<EscherRecord> _childRecords = new ArrayList<EscherRecord>(); | |||
@Override | |||
public int fillFields(byte[] data, int pOffset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader(data, pOffset); | |||
int bytesWritten = 8; | |||
@@ -90,6 +89,7 @@ public final class EscherContainerRecord extends EscherRecord { | |||
return bytesWritten; | |||
} | |||
@Override | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -115,6 +115,7 @@ public final class EscherContainerRecord extends EscherRecord { | |||
return pos - offset; | |||
} | |||
@Override | |||
public int getRecordSize() { | |||
int childRecordsSize = 0; | |||
Iterator<EscherRecord> iterator = _childRecords.iterator(); | |||
@@ -126,8 +127,9 @@ public final class EscherContainerRecord extends EscherRecord { | |||
} | |||
/** | |||
* Do any of our (top level) children have the | |||
* given recordId? | |||
* Do any of our (top level) children have the given recordId? | |||
* | |||
* @return true, if any child has the given recordId | |||
*/ | |||
public boolean hasChildOfType(short recordId) { | |||
Iterator<EscherRecord> iterator = _childRecords.iterator(); | |||
@@ -139,6 +141,7 @@ public final class EscherContainerRecord extends EscherRecord { | |||
} | |||
return false; | |||
} | |||
@Override | |||
public EscherRecord getChild( int index ) { | |||
return _childRecords.get(index); | |||
} | |||
@@ -146,10 +149,14 @@ public final class EscherContainerRecord extends EscherRecord { | |||
/** | |||
* @return a copy of the list of all the child records of the container. | |||
*/ | |||
@Override | |||
public List<EscherRecord> getChildRecords() { | |||
return new ArrayList<EscherRecord>(_childRecords); | |||
} | |||
/** | |||
* @return an iterator over the child records | |||
*/ | |||
public Iterator<EscherRecord> getChildIterator() { | |||
return Collections.unmodifiableList(_childRecords).iterator(); | |||
} | |||
@@ -157,6 +164,7 @@ public final class EscherContainerRecord extends EscherRecord { | |||
/** | |||
* replaces the internal child list with the contents of the supplied <tt>childRecords</tt> | |||
*/ | |||
@Override | |||
public void setChildRecords(List<EscherRecord> childRecords) { | |||
if (childRecords == _childRecords) { | |||
throw new IllegalStateException("Child records private data member has escaped"); | |||
@@ -165,6 +173,12 @@ public final class EscherContainerRecord extends EscherRecord { | |||
_childRecords.addAll(childRecords); | |||
} | |||
/** | |||
* Removes the given escher record from the child list | |||
* | |||
* @param toBeRemoved the escher record to be removed | |||
* @return true, if the record was found and removed | |||
*/ | |||
public boolean removeChildRecord(EscherRecord toBeRemoved) { | |||
return _childRecords.remove(toBeRemoved); | |||
} | |||
@@ -188,6 +202,7 @@ public final class EscherContainerRecord extends EscherRecord { | |||
return containers; | |||
} | |||
@Override | |||
public String getRecordName() { | |||
switch (getRecordId()) { | |||
case DGG_CONTAINER: | |||
@@ -207,6 +222,7 @@ public final class EscherContainerRecord extends EscherRecord { | |||
} | |||
} | |||
@Override | |||
public void display(PrintWriter w, int indent) { | |||
super.display(w, indent); | |||
for (Iterator<EscherRecord> iterator = _childRecords.iterator(); iterator.hasNext();) | |||
@@ -216,10 +232,21 @@ public final class EscherContainerRecord extends EscherRecord { | |||
} | |||
} | |||
/** | |||
* Append a child record | |||
* | |||
* @param record the record to be added | |||
*/ | |||
public void addChildRecord(EscherRecord record) { | |||
_childRecords.add(record); | |||
} | |||
/** | |||
* Add a child record before the record with given recordId | |||
* | |||
* @param record the record to be added | |||
* @param insertBeforeRecordId the recordId of the next sibling | |||
*/ | |||
public void addChildBefore(EscherRecord record, int insertBeforeRecordId) { | |||
int idx = 0; | |||
for (EscherRecord rec : _childRecords) { | |||
@@ -230,6 +257,7 @@ public final class EscherContainerRecord extends EscherRecord { | |||
_childRecords.add(idx, record); | |||
} | |||
@Override | |||
public String toString() | |||
{ | |||
String nl = System.getProperty( "line.separator" ); | |||
@@ -294,6 +322,7 @@ public final class EscherContainerRecord extends EscherRecord { | |||
/** | |||
* Recursively find records with the specified record ID | |||
* | |||
* @param recordId the recordId to be searched for | |||
* @param out - list to store found records | |||
*/ | |||
public void getRecordsById(short recordId, List<EscherRecord> out){ |
@@ -24,8 +24,6 @@ import org.apache.poi.util.LittleEndian; | |||
/** | |||
* This record simply holds the number of shapes in the drawing group and the | |||
* last shape id used for this drawing group. | |||
* | |||
* @author Glen Stampoultzis | |||
*/ | |||
public class EscherDgRecord | |||
extends EscherRecord | |||
@@ -36,6 +34,7 @@ public class EscherDgRecord | |||
private int field_1_numShapes; | |||
private int field_2_lastMSOSPID; | |||
@Override | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
/*int bytesRemaining =*/ readHeader( data, offset ); | |||
int pos = offset + 8; | |||
@@ -48,6 +47,7 @@ public class EscherDgRecord | |||
return getRecordSize(); | |||
} | |||
@Override | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -69,15 +69,18 @@ public class EscherDgRecord | |||
* | |||
* @return Number of bytes | |||
*/ | |||
@Override | |||
public int getRecordSize() | |||
{ | |||
return 8 + 8; | |||
} | |||
@Override | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
@Override | |||
public String getRecordName() { | |||
return "Dg"; | |||
} | |||
@@ -85,6 +88,7 @@ public class EscherDgRecord | |||
/** | |||
* Returns the string representation of this record. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return getClass().getName() + ":" + '\n' + | |||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + '\n' + | |||
@@ -106,6 +110,8 @@ public class EscherDgRecord | |||
/** | |||
* The number of shapes in this drawing group. | |||
* | |||
* @return the number of shapes | |||
*/ | |||
public int getNumShapes() | |||
{ | |||
@@ -114,6 +120,8 @@ public class EscherDgRecord | |||
/** | |||
* The number of shapes in this drawing group. | |||
* | |||
* @param field_1_numShapes the number of shapes | |||
*/ | |||
public void setNumShapes( int field_1_numShapes ) | |||
{ | |||
@@ -122,6 +130,8 @@ public class EscherDgRecord | |||
/** | |||
* The last shape id used in this drawing group. | |||
* | |||
* @return the last shape id | |||
*/ | |||
public int getLastMSOSPID() | |||
{ | |||
@@ -130,6 +140,8 @@ public class EscherDgRecord | |||
/** | |||
* The last shape id used in this drawing group. | |||
* | |||
* @param field_2_lastMSOSPID the last shape id | |||
*/ | |||
public void setLastMSOSPID( int field_2_lastMSOSPID ) | |||
{ | |||
@@ -147,6 +159,9 @@ public class EscherDgRecord | |||
return (short) ( getOptions() >> 4 ); | |||
} | |||
/** | |||
* Increments the number of shapes | |||
*/ | |||
public void incrementShapeCount() | |||
{ | |||
this.field_1_numShapes++; |
@@ -64,6 +64,7 @@ public final class EscherDggRecord extends EscherRecord { | |||
} | |||
} | |||
@Override | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
@@ -85,6 +86,7 @@ public final class EscherDggRecord extends EscherRecord { | |||
return 8 + size + bytesRemaining; | |||
} | |||
@Override | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -107,18 +109,22 @@ public final class EscherDggRecord extends EscherRecord { | |||
return getRecordSize(); | |||
} | |||
@Override | |||
public int getRecordSize() { | |||
return 8 + 16 + (8 * field_5_fileIdClusters.length); | |||
} | |||
@Override | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
@Override | |||
public String getRecordName() { | |||
return "Dgg"; | |||
} | |||
@Override | |||
public String toString() { | |||
StringBuilder field_5_string = new StringBuilder(); | |||
@@ -154,12 +160,19 @@ public final class EscherDggRecord extends EscherRecord { | |||
return builder.toString(); | |||
} | |||
/** | |||
* Gets the next available shape id | |||
* | |||
* @return the next available shape id | |||
*/ | |||
public int getShapeIdMax() { | |||
return field_1_shapeIdMax; | |||
} | |||
/** | |||
* The maximum is actually the next available. shape id. | |||
* The maximum is actually the next available shape id. | |||
* | |||
* @param shapeIdMax the next available shape id | |||
*/ | |||
public void setShapeIdMax(int shapeIdMax) { | |||
this.field_1_shapeIdMax = shapeIdMax; | |||
@@ -167,46 +180,90 @@ public final class EscherDggRecord extends EscherRecord { | |||
/** | |||
* Number of id clusters + 1 | |||
* | |||
* @return the number of id clusters + 1 | |||
*/ | |||
public int getNumIdClusters() { | |||
return (field_5_fileIdClusters == null ? 0 : (field_5_fileIdClusters.length + 1)); | |||
} | |||
/** | |||
* Gets the number of shapes saved | |||
* | |||
* @return the number of shapes saved | |||
*/ | |||
public int getNumShapesSaved() { | |||
return field_3_numShapesSaved; | |||
} | |||
/** | |||
* Sets the number of shapes saved | |||
* | |||
* @param numShapesSaved the number of shapes saved | |||
*/ | |||
public void setNumShapesSaved(int numShapesSaved) { | |||
this.field_3_numShapesSaved = numShapesSaved; | |||
} | |||
/** | |||
* Gets the number of drawings saved | |||
* | |||
* @return the number of drawings saved | |||
*/ | |||
public int getDrawingsSaved() { | |||
return field_4_drawingsSaved; | |||
} | |||
/** | |||
* Sets the number of drawings saved | |||
* | |||
* @param drawingsSaved the number of drawings saved | |||
*/ | |||
public void setDrawingsSaved(int drawingsSaved) { | |||
this.field_4_drawingsSaved = drawingsSaved; | |||
} | |||
/** | |||
* Gets the maximum drawing group ID | |||
* | |||
* @return The maximum drawing group ID | |||
*/ | |||
public int getMaxDrawingGroupId() { | |||
return maxDgId; | |||
} | |||
/** | |||
* Sets the maximum drawing group ID | |||
* | |||
* @param id the maximum drawing group ID | |||
*/ | |||
public void setMaxDrawingGroupId(int id) { | |||
maxDgId = id; | |||
} | |||
/** | |||
* @return the file id clusters | |||
*/ | |||
public FileIdCluster[] getFileIdClusters() { | |||
return field_5_fileIdClusters; | |||
} | |||
/** | |||
* Sets the file id clusters | |||
* | |||
* @param fileIdClusters the file id clusters | |||
*/ | |||
public void setFileIdClusters(FileIdCluster[] fileIdClusters) { | |||
this.field_5_fileIdClusters = fileIdClusters.clone(); | |||
} | |||
/** | |||
* Add a new cluster | |||
* | |||
* @param dgId id of the drawing group (stored in the record options) | |||
* @param numShapedUsed initial value of the numShapedUsed field | |||
*/ | |||
public void addCluster(int dgId, int numShapedUsed) { | |||
addCluster(dgId, numShapedUsed, true); | |||
} | |||
@@ -228,6 +285,7 @@ public final class EscherDggRecord extends EscherRecord { | |||
} | |||
private static final Comparator<FileIdCluster> MY_COMP = new Comparator<FileIdCluster>() { | |||
@Override | |||
public int compare(FileIdCluster f1, FileIdCluster f2) { | |||
if (f1.getDrawingGroupId() == f2.getDrawingGroupId()) { | |||
return 0; |
@@ -31,9 +31,6 @@ import java.io.IOException; | |||
import java.util.zip.InflaterInputStream; | |||
import java.util.zip.DeflaterOutputStream; | |||
/** | |||
* @author Daniel Noll | |||
*/ | |||
public final class EscherMetafileBlip extends EscherBlipRecord { | |||
private static final POILogger log = POILogFactory.getLogger(EscherMetafileBlip.class); | |||
@@ -62,6 +59,7 @@ public final class EscherMetafileBlip extends EscherBlipRecord { | |||
private byte[] raw_pictureData; | |||
private byte[] remainingData; | |||
@Override | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesAfterHeader = readHeader( data, offset ); | |||
int pos = offset + HEADER_SIZE; | |||
@@ -102,6 +100,7 @@ public final class EscherMetafileBlip extends EscherBlipRecord { | |||
return bytesAfterHeader + HEADER_SIZE; | |||
} | |||
@Override | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize(offset, getRecordId(), this); | |||
@@ -157,6 +156,7 @@ public final class EscherMetafileBlip extends EscherBlipRecord { | |||
} | |||
} | |||
@Override | |||
public int getRecordSize() { | |||
int size = 8 + 50 + raw_pictureData.length; | |||
if(remainingData != null) size += remainingData.length; | |||
@@ -166,10 +166,22 @@ public final class EscherMetafileBlip extends EscherBlipRecord { | |||
return size; | |||
} | |||
/** | |||
* Gets the first MD4, that specifies the unique identifier of the | |||
* uncompressed blip data | |||
* | |||
* @return the first MD4 | |||
*/ | |||
public byte[] getUID() { | |||
return field_1_UID; | |||
} | |||
/** | |||
* Sets the first MD4, that specifies the unique identifier of the | |||
* uncompressed blip data | |||
* | |||
* @param uid the first MD4 | |||
*/ | |||
public void setUID(byte[] uid) { | |||
if (uid == null || uid.length != 16) { | |||
throw new IllegalArgumentException("uid must be byte[16]"); | |||
@@ -177,10 +189,22 @@ public final class EscherMetafileBlip extends EscherBlipRecord { | |||
System.arraycopy(uid, 0, field_1_UID, 0, field_1_UID.length); | |||
} | |||
/** | |||
* Gets the second MD4, that specifies the unique identifier of the | |||
* uncompressed blip data | |||
* | |||
* @return the second MD4 | |||
*/ | |||
public byte[] getPrimaryUID() { | |||
return field_2_UID; | |||
} | |||
/** | |||
* Sets the second MD4, that specifies the unique identifier of the | |||
* uncompressed blip data | |||
* | |||
* @param primaryUID the second MD4 | |||
*/ | |||
public void setPrimaryUID(byte[] primaryUID) { | |||
if (primaryUID == null || primaryUID.length != 16) { | |||
throw new IllegalArgumentException("primaryUID must be byte[16]"); | |||
@@ -188,14 +212,29 @@ public final class EscherMetafileBlip extends EscherBlipRecord { | |||
System.arraycopy(primaryUID, 0, field_2_UID, 0, field_2_UID.length); | |||
} | |||
/** | |||
* Gets the uncompressed size (in bytes) | |||
* | |||
* @return the uncompressed size | |||
*/ | |||
public int getUncompressedSize() { | |||
return field_2_cb; | |||
} | |||
/** | |||
* Sets the uncompressed size (in bytes) | |||
* | |||
* @param uncompressedSize the uncompressed size | |||
*/ | |||
public void setUncompressedSize(int uncompressedSize) { | |||
field_2_cb = uncompressedSize; | |||
} | |||
/** | |||
* Get the clipping region of the metafile | |||
* | |||
* @return the clipping region | |||
*/ | |||
public Rectangle getBounds() { | |||
return new Rectangle(field_3_rcBounds_x1, | |||
field_3_rcBounds_y1, | |||
@@ -203,6 +242,11 @@ public final class EscherMetafileBlip extends EscherBlipRecord { | |||
field_3_rcBounds_y2 - field_3_rcBounds_y1); | |||
} | |||
/** | |||
* Sets the clipping region | |||
* | |||
* @param bounds the clipping region | |||
*/ | |||
public void setBounds(Rectangle bounds) { | |||
field_3_rcBounds_x1 = bounds.x; | |||
field_3_rcBounds_y1 = bounds.y; | |||
@@ -210,37 +254,73 @@ public final class EscherMetafileBlip extends EscherBlipRecord { | |||
field_3_rcBounds_y2 = bounds.y + bounds.height; | |||
} | |||
/** | |||
* Gets the dimensions of the metafile | |||
* | |||
* @return the dimensions of the metafile | |||
*/ | |||
public Dimension getSizeEMU() { | |||
return new Dimension(field_4_ptSize_w, field_4_ptSize_h); | |||
} | |||
/** | |||
* Gets the dimensions of the metafile | |||
* | |||
* @param sizeEMU the dimensions of the metafile | |||
*/ | |||
public void setSizeEMU(Dimension sizeEMU) { | |||
field_4_ptSize_w = sizeEMU.width; | |||
field_4_ptSize_h = sizeEMU.height; | |||
} | |||
/** | |||
* Gets the compressed size of the metafile (in bytes) | |||
* | |||
* @return the compressed size | |||
*/ | |||
public int getCompressedSize() { | |||
return field_5_cbSave; | |||
} | |||
/** | |||
* Sets the compressed size of the metafile (in bytes) | |||
* | |||
* @param compressedSize the compressed size | |||
*/ | |||
public void setCompressedSize(int compressedSize) { | |||
field_5_cbSave = compressedSize; | |||
} | |||
/** | |||
* Gets the compression of the metafile | |||
* | |||
* @return true, if the metafile is compressed | |||
*/ | |||
public boolean isCompressed() { | |||
return (field_6_fCompression == 0); | |||
} | |||
/** | |||
* Sets the compression of the metafile | |||
* | |||
* @param compressed the compression state, true if it's compressed | |||
*/ | |||
public void setCompressed(boolean compressed) { | |||
field_6_fCompression = compressed ? 0 : (byte)0xFE; | |||
} | |||
/** | |||
* Returns any remaining bytes | |||
* | |||
* @return any remaining bytes | |||
*/ | |||
public byte[] getRemainingData() { | |||
return remainingData; | |||
} | |||
// filtering is always 254 according to available docs, so no point giving it a setter method. | |||
@Override | |||
public String toString() { | |||
String extraData = "";//HexDump.toHex(field_pictureData, 32); | |||
return getClass().getName() + ":" + '\n' + | |||
@@ -296,6 +376,7 @@ public final class EscherMetafileBlip extends EscherBlipRecord { | |||
return 0; | |||
} | |||
@Override | |||
public void setPictureData(byte[] pictureData) { | |||
super.setPictureData(pictureData); | |||
setUncompressedSize(pictureData.length); | |||
@@ -318,6 +399,11 @@ public final class EscherMetafileBlip extends EscherBlipRecord { | |||
setCompressed(true); | |||
} | |||
/** | |||
* Sets the filter byte - usually this is 0xFE | |||
* | |||
* @param filter the filter byte | |||
*/ | |||
public void setFilter(byte filter) { | |||
field_7_fFilter = filter; | |||
} |
@@ -24,8 +24,6 @@ import org.apache.poi.util.Internal; | |||
* determining the attributes of a shape. Properties can be of two types: simple | |||
* or complex. Simple types are fixed length. Complex properties are variable | |||
* length. | |||
* | |||
* @author Glen Stampoultzis | |||
*/ | |||
public class EscherOptRecord extends AbstractEscherOptRecord | |||
{ | |||
@@ -42,6 +40,7 @@ public class EscherOptRecord extends AbstractEscherOptRecord | |||
/** | |||
* Automatically recalculate the correct option | |||
*/ | |||
@Override | |||
@Internal | |||
public short getOptions() | |||
{ | |||
@@ -51,6 +50,7 @@ public class EscherOptRecord extends AbstractEscherOptRecord | |||
return super.getOptions(); | |||
} | |||
@Override | |||
public String getRecordName() | |||
{ | |||
return "Opt"; |
@@ -29,9 +29,6 @@ import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.util.zip.InflaterInputStream; | |||
/** | |||
* @author Daniel Noll | |||
*/ | |||
public final class EscherPictBlip extends EscherBlipRecord { | |||
private static final POILogger log = POILogFactory.getLogger(EscherPictBlip.class); | |||
@@ -55,6 +52,7 @@ public final class EscherPictBlip extends EscherBlipRecord { | |||
private byte[] raw_pictureData; | |||
@Override | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesAfterHeader = readHeader(data, offset); | |||
int pos = offset + HEADER_SIZE; | |||
@@ -88,6 +86,7 @@ public final class EscherPictBlip extends EscherBlipRecord { | |||
return bytesAfterHeader + HEADER_SIZE; | |||
} | |||
@Override | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize(offset, getRecordId(), this); | |||
@@ -136,14 +135,27 @@ public final class EscherPictBlip extends EscherBlipRecord { | |||
} | |||
} | |||
@Override | |||
public int getRecordSize() { | |||
return 8 + 50 + raw_pictureData.length; | |||
} | |||
/** | |||
* Gets the first MD4, that specifies the unique identifier of the | |||
* uncompressed blip data | |||
* | |||
* @return the first MD4 | |||
*/ | |||
public byte[] getUID() { | |||
return field_1_UID; | |||
} | |||
/** | |||
* Sets the first MD4, that specifies the unique identifier of the | |||
* uncompressed blip data | |||
* | |||
* @param uid the first MD4 | |||
*/ | |||
public void setUID(byte[] uid) { | |||
if (uid == null || uid.length != 16) { | |||
throw new IllegalArgumentException("uid must be byte[16]"); | |||
@@ -151,14 +163,29 @@ public final class EscherPictBlip extends EscherBlipRecord { | |||
System.arraycopy(uid, 0, field_1_UID, 0, field_1_UID.length); | |||
} | |||
/** | |||
* Gets the uncompressed size (in bytes) | |||
* | |||
* @return the uncompressed size | |||
*/ | |||
public int getUncompressedSize() { | |||
return field_2_cb; | |||
} | |||
/** | |||
* Sets the uncompressed size (in bytes) | |||
* | |||
* @param uncompressedSize the uncompressed size | |||
*/ | |||
public void setUncompressedSize(int uncompressedSize) { | |||
field_2_cb = uncompressedSize; | |||
} | |||
/** | |||
* Get the clipping region of the pict file | |||
* | |||
* @return the clipping region | |||
*/ | |||
public Rectangle getBounds() { | |||
return new Rectangle(field_3_rcBounds_x1, | |||
field_3_rcBounds_y1, | |||
@@ -166,6 +193,11 @@ public final class EscherPictBlip extends EscherBlipRecord { | |||
field_3_rcBounds_y2 - field_3_rcBounds_y1); | |||
} | |||
/** | |||
* Sets the clipping region | |||
* | |||
* @param bounds the clipping region | |||
*/ | |||
public void setBounds(Rectangle bounds) { | |||
field_3_rcBounds_x1 = bounds.x; | |||
field_3_rcBounds_y1 = bounds.y; | |||
@@ -173,33 +205,64 @@ public final class EscherPictBlip extends EscherBlipRecord { | |||
field_3_rcBounds_y2 = bounds.y + bounds.height; | |||
} | |||
/** | |||
* Gets the dimensions of the metafile | |||
* | |||
* @return the dimensions of the metafile | |||
*/ | |||
public Dimension getSizeEMU() { | |||
return new Dimension(field_4_ptSize_w, field_4_ptSize_h); | |||
} | |||
/** | |||
* Gets the dimensions of the metafile | |||
* | |||
* @param sizeEMU the dimensions of the metafile | |||
*/ | |||
public void setSizeEMU(Dimension sizeEMU) { | |||
field_4_ptSize_w = sizeEMU.width; | |||
field_4_ptSize_h = sizeEMU.height; | |||
} | |||
/** | |||
* Gets the compressed size of the metafile (in bytes) | |||
* | |||
* @return the compressed size | |||
*/ | |||
public int getCompressedSize() { | |||
return field_5_cbSave; | |||
} | |||
/** | |||
* Sets the compressed size of the metafile (in bytes) | |||
* | |||
* @param compressedSize the compressed size | |||
*/ | |||
public void setCompressedSize(int compressedSize) { | |||
field_5_cbSave = compressedSize; | |||
} | |||
/** | |||
* Gets the compression of the metafile | |||
* | |||
* @return true, if the metafile is compressed | |||
*/ | |||
public boolean isCompressed() { | |||
return (field_6_fCompression == 0); | |||
} | |||
/** | |||
* Sets the compression of the metafile | |||
* | |||
* @param compressed the compression state, true if it's 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. | |||
@Override | |||
public String toString() { | |||
String extraData = HexDump.toHex(field_pictureData, 32); | |||
return getClass().getName() + ":" + '\n' + |
@@ -21,8 +21,6 @@ import org.apache.poi.util.HexDump; | |||
/** | |||
* A color property. | |||
* | |||
* @author Glen Stampoultzis (glens at apache.org) | |||
*/ | |||
public class EscherRGBProperty | |||
extends EscherSimpleProperty | |||
@@ -33,26 +31,39 @@ public class EscherRGBProperty | |||
super( propertyNumber, rgbColor ); | |||
} | |||
/** | |||
* @return the rgb color as int value | |||
*/ | |||
public int getRgbColor() | |||
{ | |||
return propertyValue; | |||
} | |||
/** | |||
* @return the red part | |||
*/ | |||
public byte getRed() | |||
{ | |||
return (byte) ( propertyValue & 0xFF ); | |||
} | |||
/** | |||
* @return the green part | |||
*/ | |||
public byte getGreen() | |||
{ | |||
return (byte) ( (propertyValue >> 8) & 0xFF ); | |||
} | |||
/** | |||
* @return the blue part | |||
*/ | |||
public byte getBlue() | |||
{ | |||
return (byte) ( (propertyValue >> 16) & 0xFF ); | |||
} | |||
@Override | |||
public String toXml(String tab){ | |||
StringBuilder builder = new StringBuilder(); | |||
builder.append(tab).append("<").append(getClass().getSimpleName()).append(" id=\"0x").append(HexDump.toHex(getId())) |
@@ -24,8 +24,6 @@ import org.apache.poi.util.HexDump; | |||
* A simple property is of fixed length and as a property number in addition | |||
* to a 32-bit value. Properties that can't be stored in only 32-bits are | |||
* stored as EscherComplexProperty objects. | |||
* | |||
* @author Glen Stampoultzis (glens at apache.org) | |||
*/ | |||
public class EscherSimpleProperty extends EscherProperty | |||
{ | |||
@@ -56,6 +54,7 @@ public class EscherSimpleProperty extends EscherProperty | |||
* | |||
* @return the number of bytes serialized. | |||
*/ | |||
@Override | |||
public int serializeSimplePart( byte[] data, int offset ) | |||
{ | |||
LittleEndian.putShort(data, offset, getId()); | |||
@@ -67,6 +66,7 @@ public class EscherSimpleProperty extends EscherProperty | |||
* Escher properties consist of a simple fixed length part and a complex variable length part. | |||
* The fixed length part is serialized first. | |||
*/ | |||
@Override | |||
public int serializeComplexPart( byte[] data, int pos ) | |||
{ | |||
return 0; | |||
@@ -83,6 +83,7 @@ public class EscherSimpleProperty extends EscherProperty | |||
/** | |||
* Returns true if one escher property is equal to another. | |||
*/ | |||
@Override | |||
public boolean equals( Object o ) | |||
{ | |||
if ( this == o ) return true; | |||
@@ -100,6 +101,7 @@ public class EscherSimpleProperty extends EscherProperty | |||
* Returns a hashcode so that this object can be stored in collections that | |||
* require the use of such things. | |||
*/ | |||
@Override | |||
public int hashCode() | |||
{ | |||
return propertyValue; | |||
@@ -108,6 +110,7 @@ public class EscherSimpleProperty extends EscherProperty | |||
/** | |||
* @return the string representation of this property. | |||
*/ | |||
@Override | |||
public String toString() | |||
{ | |||
return "propNum: " + getPropertyNumber() | |||
@@ -118,6 +121,7 @@ public class EscherSimpleProperty extends EscherProperty | |||
+ ", value: " + propertyValue + " (0x" + HexDump.toHex(propertyValue) + ")"; | |||
} | |||
@Override | |||
public String toXml(String tab){ | |||
StringBuilder builder = new StringBuilder(); | |||
builder.append(tab).append("<").append(getClass().getSimpleName()).append(" id=\"0x").append(HexDump.toHex(getId())) |
@@ -23,8 +23,6 @@ import org.apache.poi.util.LittleEndian; | |||
/** | |||
* Together the the EscherOptRecord this record defines some of the basic | |||
* properties of a shape. | |||
* | |||
* @author Glen Stampoultzis (glens at apache.org) | |||
*/ | |||
public class EscherSpRecord | |||
extends EscherRecord | |||
@@ -48,6 +46,7 @@ public class EscherSpRecord | |||
private int field_1_shapeId; | |||
private int field_2_flags; | |||
@Override | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
/*int bytesRemaining =*/ readHeader( data, offset ); | |||
int pos = offset + 8; | |||
@@ -70,6 +69,7 @@ public class EscherSpRecord | |||
* | |||
* @see NullEscherSerializationListener | |||
*/ | |||
@Override | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -85,15 +85,18 @@ public class EscherSpRecord | |||
return 8 + 8; | |||
} | |||
@Override | |||
public int getRecordSize() | |||
{ | |||
return 8 + 8; | |||
} | |||
@Override | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
@Override | |||
public String getRecordName() { | |||
return "Sp"; | |||
} | |||
@@ -102,6 +105,7 @@ public class EscherSpRecord | |||
/** | |||
* @return the string representing this shape. | |||
*/ | |||
@Override | |||
public String toString() | |||
{ | |||
String nl = System.getProperty("line.separator"); | |||
@@ -162,6 +166,8 @@ public class EscherSpRecord | |||
/** | |||
* Sets a number that identifies this shape. | |||
* | |||
* @param field_1_shapeId the shape id | |||
*/ | |||
public void setShapeId( int field_1_shapeId ) | |||
{ | |||
@@ -170,6 +176,8 @@ public class EscherSpRecord | |||
/** | |||
* The flags that apply to this shape. | |||
* | |||
* @return the flags | |||
* | |||
* @see #FLAG_GROUP | |||
* @see #FLAG_CHILD | |||
@@ -191,6 +199,8 @@ public class EscherSpRecord | |||
/** | |||
* The flags that apply to this shape. | |||
* | |||
* @param field_2_flags the flags | |||
* | |||
* @see #FLAG_GROUP | |||
* @see #FLAG_CHILD |
@@ -24,8 +24,6 @@ import org.apache.poi.util.RecordFormatException; | |||
/** | |||
* The spgr record defines information about a shape group. Groups in escher | |||
* are simply another form of shape that you can't physically see. | |||
* | |||
* @author Glen Stampoultzis (glens at apache.org) | |||
*/ | |||
public class EscherSpgrRecord | |||
extends EscherRecord | |||
@@ -38,6 +36,7 @@ public class EscherSpgrRecord | |||
private int field_3_rectX2; | |||
private int field_4_rectY2; | |||
@Override | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
@@ -53,6 +52,7 @@ public class EscherSpgrRecord | |||
return 8 + size + bytesRemaining; | |||
} | |||
@Override | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -70,15 +70,18 @@ public class EscherSpgrRecord | |||
return 8 + 16; | |||
} | |||
@Override | |||
public int getRecordSize() | |||
{ | |||
return 8 + 16; | |||
} | |||
@Override | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
@Override | |||
public String getRecordName() { | |||
return "Spgr"; | |||
} | |||
@@ -86,6 +89,7 @@ public class EscherSpgrRecord | |||
/** | |||
* @return the string representation of this record. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return getClass().getName() + ":" + '\n' + | |||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + '\n' + | |||
@@ -111,6 +115,8 @@ public class EscherSpgrRecord | |||
/** | |||
* The starting top-left coordinate of child records. | |||
* | |||
* @return the top-left x coordinate | |||
*/ | |||
public int getRectX1() | |||
{ | |||
@@ -118,7 +124,9 @@ public class EscherSpgrRecord | |||
} | |||
/** | |||
* The starting top-left coordinate of child records. | |||
* The top-left coordinate of child records. | |||
* | |||
* @param x1 the top-left x coordinate | |||
*/ | |||
public void setRectX1( int x1 ) | |||
{ | |||
@@ -126,7 +134,9 @@ public class EscherSpgrRecord | |||
} | |||
/** | |||
* The starting top-left coordinate of child records. | |||
* The top-left coordinate of child records. | |||
* | |||
* @return the top-left y coordinate | |||
*/ | |||
public int getRectY1() | |||
{ | |||
@@ -134,7 +144,9 @@ public class EscherSpgrRecord | |||
} | |||
/** | |||
* The starting top-left coordinate of child records. | |||
* The top-left y coordinate of child records. | |||
* | |||
* @param y1 the top-left y coordinate | |||
*/ | |||
public void setRectY1( int y1 ) | |||
{ | |||
@@ -142,7 +154,9 @@ public class EscherSpgrRecord | |||
} | |||
/** | |||
* The starting bottom-right coordinate of child records. | |||
* The bottom-right x coordinate of child records. | |||
* | |||
* @return the bottom-right x coordinate | |||
*/ | |||
public int getRectX2() | |||
{ | |||
@@ -150,7 +164,9 @@ public class EscherSpgrRecord | |||
} | |||
/** | |||
* The starting bottom-right coordinate of child records. | |||
* The bottom-right x coordinate of child records. | |||
* | |||
* @param x2 the bottom-right x coordinate | |||
*/ | |||
public void setRectX2( int x2 ) | |||
{ | |||
@@ -158,7 +174,9 @@ public class EscherSpgrRecord | |||
} | |||
/** | |||
* The starting bottom-right coordinate of child records. | |||
* The bottom-right y coordinate of child records. | |||
* | |||
* @return the bottom-right y coordinate | |||
*/ | |||
public int getRectY2() | |||
{ | |||
@@ -166,7 +184,9 @@ public class EscherSpgrRecord | |||
} | |||
/** | |||
* The starting bottom-right coordinate of child records. | |||
* The bottom-right y coordinate of child records. | |||
* | |||
* @param rectY2 the bottom-right y coordinate | |||
*/ | |||
public void setRectY2(int rectY2) { | |||
this.field_4_rectY2 = rectY2; |
@@ -24,8 +24,6 @@ import org.apache.poi.util.RecordFormatException; | |||
/** | |||
* A list of the most recently used colours for the drawings contained in | |||
* this document. | |||
* | |||
* @author Glen Stampoultzis (glens at apache.org) | |||
*/ | |||
public class EscherSplitMenuColorsRecord | |||
extends EscherRecord | |||
@@ -38,6 +36,7 @@ public class EscherSplitMenuColorsRecord | |||
private int field_3_color3; | |||
private int field_4_color4; | |||
@Override | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
int pos = offset + 8; | |||
@@ -52,8 +51,8 @@ public class EscherSplitMenuColorsRecord | |||
return 8 + size + bytesRemaining; | |||
} | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
@Override | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) { | |||
// int field_2_numIdClusters = field_5_fileIdClusters.length + 1; | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -71,15 +70,17 @@ public class EscherSplitMenuColorsRecord | |||
return getRecordSize(); | |||
} | |||
public int getRecordSize() | |||
{ | |||
@Override | |||
public int getRecordSize() { | |||
return 8 + 4 * 4; | |||
} | |||
@Override | |||
public short getRecordId() { | |||
return RECORD_ID; | |||
} | |||
@Override | |||
public String getRecordName() { | |||
return "SplitMenuColors"; | |||
} | |||
@@ -87,6 +88,7 @@ public class EscherSplitMenuColorsRecord | |||
/** | |||
* @return a string representation of this record. | |||
*/ | |||
@Override | |||
public String toString() { | |||
return getClass().getName() + ":" + '\n' + | |||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + '\n' + | |||
@@ -111,44 +113,75 @@ public class EscherSplitMenuColorsRecord | |||
return builder.toString(); | |||
} | |||
public int getColor1() | |||
{ | |||
/** | |||
* Gets the fill color | |||
* | |||
* @return the fill color | |||
*/ | |||
public int getColor1() { | |||
return field_1_color1; | |||
} | |||
public void setColor1( int field_1_color1 ) | |||
{ | |||
/** | |||
* Sets the fill color | |||
* | |||
* @param field_1_color1 the fill color | |||
*/ | |||
public void setColor1( int field_1_color1 ) { | |||
this.field_1_color1 = field_1_color1; | |||
} | |||
public int getColor2() | |||
{ | |||
/** | |||
* Gets the line color | |||
* | |||
* @return the line color | |||
*/ | |||
public int getColor2() { | |||
return field_2_color2; | |||
} | |||
public void setColor2( int field_2_color2 ) | |||
{ | |||
/** | |||
* Sets the line color | |||
* | |||
* @param field_2_color2 the line color | |||
*/ | |||
public void setColor2( int field_2_color2 ) { | |||
this.field_2_color2 = field_2_color2; | |||
} | |||
public int getColor3() | |||
{ | |||
/** | |||
* Gets the shadow color | |||
* | |||
* @return the shadow color | |||
*/ | |||
public int getColor3() { | |||
return field_3_color3; | |||
} | |||
public void setColor3( int field_3_color3 ) | |||
{ | |||
/** | |||
* Sets the shadow color | |||
* | |||
* @param field_3_color3 the shadow color | |||
*/ | |||
public void setColor3( int field_3_color3 ) { | |||
this.field_3_color3 = field_3_color3; | |||
} | |||
public int getColor4() | |||
{ | |||
/** | |||
* Gets the 3-D color | |||
* | |||
* @return the 3-D color | |||
*/ | |||
public int getColor4() { | |||
return field_4_color4; | |||
} | |||
public void setColor4( int field_4_color4 ) | |||
{ | |||
/** | |||
* Sets the 3-D color | |||
* | |||
* @param field_4_color4 the 3-D color | |||
*/ | |||
public void setColor4( int field_4_color4 ) { | |||
this.field_4_color4 = field_4_color4; | |||
} | |||
} |
@@ -19,13 +19,12 @@ package org.apache.poi.ddf; | |||
/** | |||
* "The OfficeArtTertiaryFOPT record specifies a table of OfficeArtRGFOPTE properties, as defined in section 2.3.1." | |||
* -- [MS-ODRAW] -- v20110608; Office Drawing Binary File Format | |||
* | |||
* @author Sergey Vladimirov (vlsergey {at} gmail {dot} com) | |||
*/ | |||
public class EscherTertiaryOptRecord extends AbstractEscherOptRecord | |||
{ | |||
public static final short RECORD_ID = (short) 0xF122; | |||
@Override | |||
public String getRecordName() | |||
{ | |||
return "TertiaryOpt"; |
@@ -40,6 +40,7 @@ public final class EscherTextboxRecord extends EscherRecord implements Cloneable | |||
{ | |||
} | |||
@Override | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
@@ -50,6 +51,7 @@ public final class EscherTextboxRecord extends EscherRecord implements Cloneable | |||
return bytesRemaining + 8; | |||
} | |||
@Override | |||
public int serialize( int offset, byte[] data, EscherSerializationListener listener ) | |||
{ | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -73,6 +75,8 @@ public final class EscherTextboxRecord extends EscherRecord implements Cloneable | |||
* does not seem to put anything here, but with PowerPoint this will | |||
* contain the bytes that make up a TextHeaderAtom followed by a | |||
* TextBytesAtom/TextCharsAtom | |||
* | |||
* @return the extra data | |||
*/ | |||
public byte[] getData() | |||
{ | |||
@@ -83,16 +87,29 @@ public final class EscherTextboxRecord extends EscherRecord implements Cloneable | |||
* Sets the extra data (in the parent application's format) to be | |||
* contained by the record. Used when the parent application changes | |||
* the contents. | |||
* | |||
* @param b the buffer which contains the data | |||
* @param start the start position in the buffer | |||
* @param length the length of the block | |||
*/ | |||
public void setData(byte[] b, int start, int length) | |||
{ | |||
thedata = new byte[length]; | |||
System.arraycopy(b,start,thedata,0,length); | |||
} | |||
/** | |||
* Sets the extra data (in the parent application's format) to be | |||
* contained by the record. Used when the parent application changes | |||
* the contents. | |||
* | |||
* @param b the data | |||
*/ | |||
public void setData(byte[] b) { | |||
setData(b,0,b.length); | |||
} | |||
@Override | |||
public int getRecordSize() | |||
{ | |||
return 8 + thedata.length; | |||
@@ -107,10 +124,12 @@ public final class EscherTextboxRecord extends EscherRecord implements Cloneable | |||
return etr; | |||
} | |||
@Override | |||
public String getRecordName() { | |||
return "ClientTextbox"; | |||
} | |||
@Override | |||
public String toString() | |||
{ | |||
String nl = System.getProperty( "line.separator" ); |
@@ -19,14 +19,14 @@ package org.apache.poi.ddf; | |||
/** | |||
* Ignores all serialization events. | |||
* | |||
* @author Glen Stampoultzis (glens at apache.org) | |||
*/ | |||
public class NullEscherSerializationListener implements EscherSerializationListener { | |||
@Override | |||
public void beforeRecordSerialize(int offset, short recordId, EscherRecord record) { | |||
// do nothing | |||
} | |||
@Override | |||
public void afterRecordSerialize(int offset, short recordId, int size, EscherRecord record) { | |||
// do nothing | |||
} |
@@ -27,9 +27,6 @@ import org.apache.poi.util.LittleEndian; | |||
/** | |||
* This record is used whenever a escher record is encountered that | |||
* we do not explicitly support. | |||
* | |||
* @author Glen Stampoultzis (glens at apache.org) | |||
* @author Zhang Zhang (zhangzzh at gmail.com) | |||
*/ | |||
public final class UnknownEscherRecord extends EscherRecord implements Cloneable { | |||
private static final byte[] NO_BYTES = new byte[0]; | |||
@@ -42,13 +39,12 @@ public final class UnknownEscherRecord extends EscherRecord implements Cloneable | |||
_childRecords = new ArrayList<EscherRecord>(); | |||
} | |||
@Override | |||
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) { | |||
int bytesRemaining = readHeader( data, offset ); | |||
/* | |||
* Modified by Zhang Zhang | |||
* Have a check between avaliable bytes and bytesRemaining, | |||
* take the avaliable length if the bytesRemaining out of range. | |||
* July 09, 2010 | |||
*/ | |||
int avaliable = data.length - (offset + 8); | |||
if (bytesRemaining > avaliable) { | |||
@@ -77,6 +73,7 @@ public final class UnknownEscherRecord extends EscherRecord implements Cloneable | |||
return bytesRemaining + 8; | |||
} | |||
@Override | |||
public int serialize(int offset, byte[] data, EscherSerializationListener listener) { | |||
listener.beforeRecordSerialize( offset, getRecordId(), this ); | |||
@@ -97,18 +94,24 @@ public final class UnknownEscherRecord extends EscherRecord implements Cloneable | |||
return pos - offset; | |||
} | |||
/** | |||
* @return the data which makes up this record | |||
*/ | |||
public byte[] getData() { | |||
return thedata; | |||
} | |||
@Override | |||
public int getRecordSize() { | |||
return 8 + thedata.length; | |||
} | |||
@Override | |||
public List<EscherRecord> getChildRecords() { | |||
return _childRecords; | |||
} | |||
@Override | |||
public void setChildRecords(List<EscherRecord> childRecords) { | |||
_childRecords = childRecords; | |||
} | |||
@@ -122,10 +125,12 @@ public final class UnknownEscherRecord extends EscherRecord implements Cloneable | |||
return uer; | |||
} | |||
@Override | |||
public String getRecordName() { | |||
return "Unknown 0x" + HexDump.toHex(getRecordId()); | |||
} | |||
@Override | |||
public String toString() { | |||
StringBuffer children = new StringBuffer(); | |||
if (getChildRecords().size() > 0) { |