Escher records for drawing format support

git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/branches/REL_2_BRANCH@353495 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Glen Stampoultzis 2004-02-10 21:58:00 +00:00
parent bad7b56f31
commit 104093d45e
15 changed files with 3083 additions and 11 deletions

View File

@ -0,0 +1,266 @@
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache POI" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache POI", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.poi.hssf.record;
import org.apache.poi.ddf.DefaultEscherRecordFactory;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherRecordFactory;
import org.apache.poi.ddf.NullEscherSerializationListener;
import org.apache.poi.util.LittleEndian;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* The escher container record is used to hold escher records. It is abstract and
* must be subclassed for maximum benefit.
*
* @author Glen Stampoultzis (glens at apache.org)
*/
public abstract class AbstractEscherHolderRecord
extends Record
{
private static final boolean DESERIALISE = System.getProperty("poi.deserialize.escher") != null;
private List escherRecords;
private byte[] rawData;
public AbstractEscherHolderRecord()
{
escherRecords = new ArrayList();
}
/**
* Constructs a Bar record and sets its fields appropriately.
*
* @param id id must be 0x1017 or an exception
* will be throw upon validation
* @param size size the size of the data area of the record
* @param data data of the record (should not contain sid/len)
*/
public AbstractEscherHolderRecord(short id, short size, byte [] data)
{
super(id, size, data);
}
/**
* Constructs a Bar record and sets its fields appropriately.
*
* @param id id must be 0x1017 or an exception
* will be throw upon validation
* @param size size the size of the data area of the record
* @param data data of the record (should not contain sid/len)
* @param offset of the record's data
*/
public AbstractEscherHolderRecord(short id, short size, byte [] data, int offset)
{
super(id, size, data, offset);
}
/**
* Checks the sid matches the expected side for this record
*
* @param id the expected sid.
*/
protected void validateSid(short id)
{
if (id != getSid())
{
throw new RecordFormatException("Not a Bar record");
}
}
protected void fillFields(byte [] data, short size, int offset)
{
escherRecords = new ArrayList();
if (! DESERIALISE )
{
rawData = new byte[size];
System.arraycopy(data, offset, rawData, 0, size);
}
else
{
EscherRecordFactory recordFactory = new DefaultEscherRecordFactory();
int pos = offset;
while ( pos < offset + size )
{
EscherRecord r = recordFactory.createRecord(data, pos);
int bytesRead = r.fillFields(data, pos, recordFactory );
escherRecords.add(r);
pos += bytesRead;
}
}
}
public String toString()
{
StringBuffer buffer = new StringBuffer();
final String nl = System.getProperty("line.separator");
buffer.append("[" + getRecordName() + "]" + nl);
for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
{
EscherRecord r = (EscherRecord) iterator.next();
buffer.append(r.toString());
}
buffer.append("[/" + getRecordName() + "]" + nl);
return buffer.toString();
}
protected abstract String getRecordName();
public int serialize(int offset, byte[] data)
{
if (escherRecords.size() == 0 && rawData != null)
{
System.arraycopy( rawData, 0, data, offset, rawData.length);
return rawData.length;
}
else
{
collapseShapeInformation();
LittleEndian.putShort(data, 0 + offset, getSid());
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
int pos = offset + 4;
for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
{
EscherRecord r = (EscherRecord) iterator.next();
pos += r.serialize(pos, data, new NullEscherSerializationListener() );
}
return getRecordSize();
}
}
/**
* Size of record (including 4 byte header)
*/
public int getRecordSize()
{
if (escherRecords.size() == 0 && rawData != null)
{
return rawData.length;
}
else
{
collapseShapeInformation();
int size = 4;
for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
{
EscherRecord r = (EscherRecord) iterator.next();
size += r.getRecordSize();
}
return size;
}
}
private void collapseShapeInformation()
{
}
public abstract short getSid();
public Object clone()
{
throw new IllegalStateException("Not implemented yet.");
}
public void addEscherRecord(int index, EscherRecord element)
{
escherRecords.add( index, element );
}
public boolean addEscherRecord(EscherRecord element)
{
return escherRecords.add( element );
}
public List getEscherRecords()
{
return escherRecords;
}
public void clearEscherRecords()
{
escherRecords.clear();
}
public EscherRecord getEscherRecord(int index)
{
return (EscherRecord) escherRecords.get(index);
}
} // END OF CLASS

View File

@ -0,0 +1,498 @@
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache POI" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache POI", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.poi.hssf.record;
import org.apache.poi.util.*;
/**
* The common object data record is used to store all common preferences for an excel object.
* NOTE: This source is automatically generated please do not modify this file. Either subclass or
* remove the record in src/records/definitions.
* @author Glen Stampoultzis (glens at apache.org)
*/
public class CommonObjectDataSubRecord
extends SubRecord
{
public final static short sid = 0x15;
private short field_1_objectType;
public final static short OBJECT_TYPE_GROUP = 0;
public final static short OBJECT_TYPE_LINE = 1;
public final static short OBJECT_TYPE_RECTANGLE = 2;
public final static short OBJECT_TYPE_OVAL = 3;
public final static short OBJECT_TYPE_ARC = 4;
public final static short OBJECT_TYPE_CHART = 5;
public final static short OBJECT_TYPE_TEXT = 6;
public final static short OBJECT_TYPE_BUTTON = 7;
public final static short OBJECT_TYPE_PICTURE = 8;
public final static short OBJECT_TYPE_POLYGON = 9;
public final static short OBJECT_TYPE_RESERVED1 = 10;
public final static short OBJECT_TYPE_CHECKBOX = 11;
public final static short OBJECT_TYPE_OPTION_BUTTON = 12;
public final static short OBJECT_TYPE_EDIT_BOX = 13;
public final static short OBJECT_TYPE_LABEL = 14;
public final static short OBJECT_TYPE_DIALOG_BOX = 15;
public final static short OBJECT_TYPE_SPINNER = 16;
public final static short OBJECT_TYPE_SCROLL_BAR = 17;
public final static short OBJECT_TYPE_LIST_BOX = 18;
public final static short OBJECT_TYPE_GROUP_BOX = 19;
public final static short OBJECT_TYPE_COMBO_BOX = 20;
public final static short OBJECT_TYPE_RESERVED2 = 21;
public final static short OBJECT_TYPE_RESERVED3 = 22;
public final static short OBJECT_TYPE_RESERVED4 = 23;
public final static short OBJECT_TYPE_RESERVED5 = 24;
public final static short OBJECT_TYPE_COMMENT = 25;
public final static short OBJECT_TYPE_RESERVED6 = 26;
public final static short OBJECT_TYPE_RESERVED7 = 27;
public final static short OBJECT_TYPE_RESERVED8 = 28;
public final static short OBJECT_TYPE_RESERVED9 = 29;
public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30;
private short field_2_objectId;
private short field_3_option;
private BitField locked = new BitField(0x1);
private BitField printable = new BitField(0x10);
private BitField autofill = new BitField(0x2000);
private BitField autoline = new BitField(0x4000);
private int field_4_reserved1;
private int field_5_reserved2;
private int field_6_reserved3;
public CommonObjectDataSubRecord()
{
}
/**
* Constructs a CommonObjectData record and sets its fields appropriately.
*
* @param id id must be 0x15 or an exception
* will be throw upon validation
* @param size size the size of the data area of the record
* @param data data of the record (should not contain sid/len)
*/
public CommonObjectDataSubRecord(short id, short size, byte [] data)
{
super(id, size, data);
}
/**
* Constructs a CommonObjectData record and sets its fields appropriately.
*
* @param id id must be 0x15 or an exception
* will be throw upon validation
* @param size size the size of the data area of the record
* @param data data of the record (should not contain sid/len)
* @param offset of the record's data
*/
public CommonObjectDataSubRecord(short id, short size, byte [] data, int offset)
{
super(id, size, data, offset);
}
/**
* Checks the sid matches the expected side for this record
*
* @param id the expected sid.
*/
protected void validateSid(short id)
{
if (id != sid)
{
throw new RecordFormatException("Not a CommonObjectData record");
}
}
protected void fillFields(byte [] data, short size, int offset)
{
int pos = 0;
field_1_objectType = LittleEndian.getShort(data, pos + 0x0 + offset);
field_2_objectId = LittleEndian.getShort(data, pos + 0x2 + offset);
field_3_option = LittleEndian.getShort(data, pos + 0x4 + offset);
field_4_reserved1 = LittleEndian.getInt(data, pos + 0x6 + offset);
field_5_reserved2 = LittleEndian.getInt(data, pos + 0xa + offset);
field_6_reserved3 = LittleEndian.getInt(data, pos + 0xe + offset);
}
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append("[ftCmo]\n");
buffer.append(" .objectType = ")
.append("0x").append(HexDump.toHex( getObjectType ()))
.append(" (").append( getObjectType() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append(" .objectId = ")
.append("0x").append(HexDump.toHex( getObjectId ()))
.append(" (").append( getObjectId() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append(" .option = ")
.append("0x").append(HexDump.toHex( getOption ()))
.append(" (").append( getOption() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append(" .locked = ").append(isLocked()).append('\n');
buffer.append(" .printable = ").append(isPrintable()).append('\n');
buffer.append(" .autofill = ").append(isAutofill()).append('\n');
buffer.append(" .autoline = ").append(isAutoline()).append('\n');
buffer.append(" .reserved1 = ")
.append("0x").append(HexDump.toHex( getReserved1 ()))
.append(" (").append( getReserved1() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append(" .reserved2 = ")
.append("0x").append(HexDump.toHex( getReserved2 ()))
.append(" (").append( getReserved2() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append(" .reserved3 = ")
.append("0x").append(HexDump.toHex( getReserved3 ()))
.append(" (").append( getReserved3() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append("[/ftCmo]\n");
return buffer.toString();
}
public int serialize(int offset, byte[] data)
{
int pos = 0;
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
LittleEndian.putShort(data, 4 + offset + pos, field_1_objectType);
LittleEndian.putShort(data, 6 + offset + pos, field_2_objectId);
LittleEndian.putShort(data, 8 + offset + pos, field_3_option);
LittleEndian.putInt(data, 10 + offset + pos, field_4_reserved1);
LittleEndian.putInt(data, 14 + offset + pos, field_5_reserved2);
LittleEndian.putInt(data, 18 + offset + pos, field_6_reserved3);
return getRecordSize();
}
/**
* Size of record (exluding 4 byte header)
*/
public int getRecordSize()
{
return 4 + 2 + 2 + 2 + 4 + 4 + 4;
}
public short getSid()
{
return this.sid;
}
public Object clone() {
CommonObjectDataSubRecord rec = new CommonObjectDataSubRecord();
rec.field_1_objectType = field_1_objectType;
rec.field_2_objectId = field_2_objectId;
rec.field_3_option = field_3_option;
rec.field_4_reserved1 = field_4_reserved1;
rec.field_5_reserved2 = field_5_reserved2;
rec.field_6_reserved3 = field_6_reserved3;
return rec;
}
/**
* Get the object type field for the CommonObjectData record.
*
* @return One of
* OBJECT_TYPE_GROUP
* OBJECT_TYPE_LINE
* OBJECT_TYPE_RECTANGLE
* OBJECT_TYPE_OVAL
* OBJECT_TYPE_ARC
* OBJECT_TYPE_CHART
* OBJECT_TYPE_TEXT
* OBJECT_TYPE_BUTTON
* OBJECT_TYPE_PICTURE
* OBJECT_TYPE_POLYGON
* OBJECT_TYPE_RESERVED1
* OBJECT_TYPE_CHECKBOX
* OBJECT_TYPE_OPTION_BUTTON
* OBJECT_TYPE_EDIT_BOX
* OBJECT_TYPE_LABEL
* OBJECT_TYPE_DIALOG_BOX
* OBJECT_TYPE_SPINNER
* OBJECT_TYPE_SCROLL_BAR
* OBJECT_TYPE_LIST_BOX
* OBJECT_TYPE_GROUP_BOX
* OBJECT_TYPE_COMBO_BOX
* OBJECT_TYPE_RESERVED2
* OBJECT_TYPE_RESERVED3
* OBJECT_TYPE_RESERVED4
* OBJECT_TYPE_RESERVED5
* OBJECT_TYPE_COMMENT
* OBJECT_TYPE_RESERVED6
* OBJECT_TYPE_RESERVED7
* OBJECT_TYPE_RESERVED8
* OBJECT_TYPE_RESERVED9
* OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING
*/
public short getObjectType()
{
return field_1_objectType;
}
/**
* Set the object type field for the CommonObjectData record.
*
* @param field_1_objectType
* One of
* OBJECT_TYPE_GROUP
* OBJECT_TYPE_LINE
* OBJECT_TYPE_RECTANGLE
* OBJECT_TYPE_OVAL
* OBJECT_TYPE_ARC
* OBJECT_TYPE_CHART
* OBJECT_TYPE_TEXT
* OBJECT_TYPE_BUTTON
* OBJECT_TYPE_PICTURE
* OBJECT_TYPE_POLYGON
* OBJECT_TYPE_RESERVED1
* OBJECT_TYPE_CHECKBOX
* OBJECT_TYPE_OPTION_BUTTON
* OBJECT_TYPE_EDIT_BOX
* OBJECT_TYPE_LABEL
* OBJECT_TYPE_DIALOG_BOX
* OBJECT_TYPE_SPINNER
* OBJECT_TYPE_SCROLL_BAR
* OBJECT_TYPE_LIST_BOX
* OBJECT_TYPE_GROUP_BOX
* OBJECT_TYPE_COMBO_BOX
* OBJECT_TYPE_RESERVED2
* OBJECT_TYPE_RESERVED3
* OBJECT_TYPE_RESERVED4
* OBJECT_TYPE_RESERVED5
* OBJECT_TYPE_COMMENT
* OBJECT_TYPE_RESERVED6
* OBJECT_TYPE_RESERVED7
* OBJECT_TYPE_RESERVED8
* OBJECT_TYPE_RESERVED9
* OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING
*/
public void setObjectType(short field_1_objectType)
{
this.field_1_objectType = field_1_objectType;
}
/**
* Get the object id field for the CommonObjectData record.
*/
public short getObjectId()
{
return field_2_objectId;
}
/**
* Set the object id field for the CommonObjectData record.
*/
public void setObjectId(short field_2_objectId)
{
this.field_2_objectId = field_2_objectId;
}
/**
* Get the option field for the CommonObjectData record.
*/
public short getOption()
{
return field_3_option;
}
/**
* Set the option field for the CommonObjectData record.
*/
public void setOption(short field_3_option)
{
this.field_3_option = field_3_option;
}
/**
* Get the reserved1 field for the CommonObjectData record.
*/
public int getReserved1()
{
return field_4_reserved1;
}
/**
* Set the reserved1 field for the CommonObjectData record.
*/
public void setReserved1(int field_4_reserved1)
{
this.field_4_reserved1 = field_4_reserved1;
}
/**
* Get the reserved2 field for the CommonObjectData record.
*/
public int getReserved2()
{
return field_5_reserved2;
}
/**
* Set the reserved2 field for the CommonObjectData record.
*/
public void setReserved2(int field_5_reserved2)
{
this.field_5_reserved2 = field_5_reserved2;
}
/**
* Get the reserved3 field for the CommonObjectData record.
*/
public int getReserved3()
{
return field_6_reserved3;
}
/**
* Set the reserved3 field for the CommonObjectData record.
*/
public void setReserved3(int field_6_reserved3)
{
this.field_6_reserved3 = field_6_reserved3;
}
/**
* Sets the locked field value.
* true if object is locked when sheet has been protected
*/
public void setLocked(boolean value)
{
field_3_option = locked.setShortBoolean(field_3_option, value);
}
/**
* true if object is locked when sheet has been protected
* @return the locked field value.
*/
public boolean isLocked()
{
return locked.isSet(field_3_option);
}
/**
* Sets the printable field value.
* object appears when printed
*/
public void setPrintable(boolean value)
{
field_3_option = printable.setShortBoolean(field_3_option, value);
}
/**
* object appears when printed
* @return the printable field value.
*/
public boolean isPrintable()
{
return printable.isSet(field_3_option);
}
/**
* Sets the autofill field value.
* whether object uses an automatic fill style
*/
public void setAutofill(boolean value)
{
field_3_option = autofill.setShortBoolean(field_3_option, value);
}
/**
* whether object uses an automatic fill style
* @return the autofill field value.
*/
public boolean isAutofill()
{
return autofill.isSet(field_3_option);
}
/**
* Sets the autoline field value.
* whether object uses an automatic line style
*/
public void setAutoline(boolean value)
{
field_3_option = autoline.setShortBoolean(field_3_option, value);
}
/**
* whether object uses an automatic line style
* @return the autoline field value.
*/
public boolean isAutoline()
{
return autoline.isSet(field_3_option);
}
} // END OF CLASS

View File

@ -0,0 +1,30 @@
package org.apache.poi.hssf.record;
public class DrawingGroupRecord extends AbstractEscherHolderRecord
{
public static final short sid = 0xEB;
public DrawingGroupRecord()
{
}
public DrawingGroupRecord( short id, short size, byte[] data )
{
super( id, size, data );
}
public DrawingGroupRecord( short id, short size, byte[] data, int offset )
{
super( id, size, data, offset );
}
protected String getRecordName()
{
return "MSODRAWINGGROUP";
}
public short getSid()
{
return sid;
}
}

View File

@ -0,0 +1,97 @@
package org.apache.poi.hssf.record;
import org.apache.poi.util.LittleEndian;
public class DrawingRecord extends Record
{
public static final short sid = 0xEC;
private byte[] recordData;
public DrawingRecord()
{
}
public DrawingRecord( short id, short size, byte[] data )
{
super( id, size, data );
}
public DrawingRecord( short id, short size, byte[] data, int offset )
{
super( id, size, data, offset );
}
/**
* Checks the sid matches the expected side for this record
*
* @param id the expected sid.
*/
protected void validateSid(short id)
{
if (id != sid)
{
throw new RecordFormatException("Not a MSODRAWING record");
}
}
protected void fillFields( byte[] data, short size, int offset )
{
if (offset == 0 && size == data.length)
{
recordData = data;
}
else
{
recordData = new byte[size];
System.arraycopy(data, offset, recordData, 0, size);
}
}
protected void fillFields( byte[] data, short size )
{
recordData = data;
}
public int serialize( int offset, byte[] data )
{
if (recordData == null)
{
recordData = new byte[ 0 ];
}
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, ( short ) (recordData.length));
if (recordData.length > 0)
{
System.arraycopy(recordData, 0, data, 4 + offset, recordData.length);
}
return getRecordSize();
}
public int getRecordSize()
{
int retval = 4;
if (recordData != null)
{
retval += recordData.length;
}
return retval;
}
public short getSid()
{
return sid;
}
public byte[] getData()
{
return recordData;
}
public void setData( byte[] thedata )
{
this.recordData = thedata;
}
}

View File

@ -0,0 +1,35 @@
package org.apache.poi.hssf.record;
/**
* This is purely for the biff viewer. During normal operations we don't want
* to be seeing this.
*/
public class DrawingRecordForBiffViewer
extends AbstractEscherHolderRecord
{
public static final short sid = 0xEC;
public DrawingRecordForBiffViewer()
{
}
public DrawingRecordForBiffViewer( short id, short size, byte[] data )
{
super( id, size, data );
}
public DrawingRecordForBiffViewer( short id, short size, byte[] data, int offset )
{
super( id, size, data, offset );
}
protected String getRecordName()
{
return "MSODRAWING";
}
public short getSid()
{
return sid;
}
}

View File

@ -0,0 +1,30 @@
package org.apache.poi.hssf.record;
public class DrawingSelectionRecord extends AbstractEscherHolderRecord
{
public static final short sid = 0xED;
public DrawingSelectionRecord()
{
}
public DrawingSelectionRecord( short id, short size, byte[] data )
{
super( id, size, data );
}
public DrawingSelectionRecord( short id, short size, byte[] data, int offset )
{
super( id, size, data, offset );
}
protected String getRecordName()
{
return "MSODRAWINGSELECTION";
}
public short getSid()
{
return sid;
}
}

View File

@ -0,0 +1,176 @@
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache POI" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache POI", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.poi.hssf.record;
import org.apache.poi.util.*;
/**
* The end data record is used to denote the end of the subrecords.
* NOTE: This source is automatically generated please do not modify this file. Either subclass or
* remove the record in src/records/definitions.
* @author Glen Stampoultzis (glens at apache.org)
*/
public class EndSubRecord
extends SubRecord
{
public final static short sid = 0x00;
public EndSubRecord()
{
}
/**
* Constructs a End record and sets its fields appropriately.
*
* @param id id must be 0x00 or an exception
* will be throw upon validation
* @param size size the size of the data area of the record
* @param data data of the record (should not contain sid/len)
*/
public EndSubRecord(short id, short size, byte [] data)
{
super(id, size, data);
}
/**
* Constructs a End record and sets its fields appropriately.
*
* @param id id must be 0x00 or an exception
* will be throw upon validation
* @param size size the size of the data area of the record
* @param data data of the record (should not contain sid/len)
* @param offset of the record's data
*/
public EndSubRecord(short id, short size, byte [] data, int offset)
{
super(id, size, data, offset);
}
/**
* Checks the sid matches the expected side for this record
*
* @param id the expected sid.
*/
protected void validateSid(short id)
{
if (id != sid)
{
throw new RecordFormatException("Not a End record");
}
}
protected void fillFields(byte [] data, short size, int offset)
{
int pos = 0;
}
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append("[ftEnd]\n");
buffer.append("[/ftEnd]\n");
return buffer.toString();
}
public int serialize(int offset, byte[] data)
{
int pos = 0;
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
return getRecordSize();
}
/**
* Size of record (exluding 4 byte header)
*/
public int getRecordSize()
{
return 4 ;
}
public short getSid()
{
return this.sid;
}
public Object clone() {
EndSubRecord rec = new EndSubRecord();
return rec;
}
} // END OF CLASS

View File

@ -0,0 +1,696 @@
package org.apache.poi.hssf.record;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.model.AbstractShape;
import org.apache.poi.hssf.model.TextboxShape;
import org.apache.poi.hssf.model.DrawingManager;
import org.apache.poi.hssf.model.ConvertAnchor;
import java.util.*;
/**
* This class is used to aggregate the MSODRAWING and OBJ record
* combinations. This is necessary due to the bizare way in which
* these records are serialized. What happens is that you get a
* combination of MSODRAWING -> OBJ -> MSODRAWING -> OBJ records
* but the escher records are serialized _across_ the MSODRAWING
* records.
* <p>
* It gets even worse when you start looking at TXO records.
* <p>
* So what we do with this class is aggregate lazily. That is
* we don't aggregate the MSODRAWING -> OBJ records unless we
* need to modify them.
*
*
* @author Glen Stampoultzis (glens at apache.org)
*/
public class EscherAggregate extends AbstractEscherHolderRecord
{
public static final short sid = 9876;
public static final short ST_MIN = (short) 0;
public static final short ST_NOT_PRIMATIVE = ST_MIN;
public static final short ST_RECTANGLE = (short) 1;
public static final short ST_ROUNDRECTANGLE = (short) 2;
public static final short ST_ELLIPSE = (short) 3;
public static final short ST_DIAMOND = (short) 4;
public static final short ST_ISOCELESTRIANGLE = (short) 5;
public static final short ST_RIGHTTRIANGLE = (short) 6;
public static final short ST_PARALLELOGRAM = (short) 7;
public static final short ST_TRAPEZOID = (short) 8;
public static final short ST_HEXAGON = (short) 9;
public static final short ST_OCTAGON = (short) 10;
public static final short ST_PLUS = (short) 11;
public static final short ST_STAR = (short) 12;
public static final short ST_ARROW = (short) 13;
public static final short ST_THICKARROW = (short) 14;
public static final short ST_HOMEPLATE = (short) 15;
public static final short ST_CUBE = (short) 16;
public static final short ST_BALLOON = (short) 17;
public static final short ST_SEAL = (short) 18;
public static final short ST_ARC = (short) 19;
public static final short ST_LINE = (short) 20;
public static final short ST_PLAQUE = (short) 21;
public static final short ST_CAN = (short) 22;
public static final short ST_DONUT = (short) 23;
public static final short ST_TEXTSIMPLE = (short) 24;
public static final short ST_TEXTOCTAGON = (short) 25;
public static final short ST_TEXTHEXAGON = (short) 26;
public static final short ST_TEXTCURVE = (short) 27;
public static final short ST_TEXTWAVE = (short) 28;
public static final short ST_TEXTRING = (short) 29;
public static final short ST_TEXTONCURVE = (short) 30;
public static final short ST_TEXTONRING = (short) 31;
public static final short ST_STRAIGHTCONNECTOR1 = (short) 32;
public static final short ST_BENTCONNECTOR2 = (short) 33;
public static final short ST_BENTCONNECTOR3 = (short) 34;
public static final short ST_BENTCONNECTOR4 = (short) 35;
public static final short ST_BENTCONNECTOR5 = (short) 36;
public static final short ST_CURVEDCONNECTOR2 = (short) 37;
public static final short ST_CURVEDCONNECTOR3 = (short) 38;
public static final short ST_CURVEDCONNECTOR4 = (short) 39;
public static final short ST_CURVEDCONNECTOR5 = (short) 40;
public static final short ST_CALLOUT1 = (short) 41;
public static final short ST_CALLOUT2 = (short) 42;
public static final short ST_CALLOUT3 = (short) 43;
public static final short ST_ACCENTCALLOUT1 = (short) 44;
public static final short ST_ACCENTCALLOUT2 = (short) 45;
public static final short ST_ACCENTCALLOUT3 = (short) 46;
public static final short ST_BORDERCALLOUT1 = (short) 47;
public static final short ST_BORDERCALLOUT2 = (short) 48;
public static final short ST_BORDERCALLOUT3 = (short) 49;
public static final short ST_ACCENTBORDERCALLOUT1 = (short) 50;
public static final short ST_ACCENTBORDERCALLOUT2 = (short) 51;
public static final short ST_ACCENTBORDERCALLOUT3 = (short) 52;
public static final short ST_RIBBON = (short) 53;
public static final short ST_RIBBON2 = (short) 54;
public static final short ST_CHEVRON = (short) 55;
public static final short ST_PENTAGON = (short) 56;
public static final short ST_NOSMOKING = (short) 57;
public static final short ST_SEAL8 = (short) 58;
public static final short ST_SEAL16 = (short) 59;
public static final short ST_SEAL32 = (short) 60;
public static final short ST_WEDGERECTCALLOUT = (short) 61;
public static final short ST_WEDGERRECTCALLOUT = (short) 62;
public static final short ST_WEDGEELLIPSECALLOUT = (short) 63;
public static final short ST_WAVE = (short) 64;
public static final short ST_FOLDEDCORNER = (short) 65;
public static final short ST_LEFTARROW = (short) 66;
public static final short ST_DOWNARROW = (short) 67;
public static final short ST_UPARROW = (short) 68;
public static final short ST_LEFTRIGHTARROW = (short) 69;
public static final short ST_UPDOWNARROW = (short) 70;
public static final short ST_IRREGULARSEAL1 = (short) 71;
public static final short ST_IRREGULARSEAL2 = (short) 72;
public static final short ST_LIGHTNINGBOLT = (short) 73;
public static final short ST_HEART = (short) 74;
public static final short ST_PICTUREFRAME = (short) 75;
public static final short ST_QUADARROW = (short) 76;
public static final short ST_LEFTARROWCALLOUT = (short) 77;
public static final short ST_RIGHTARROWCALLOUT = (short) 78;
public static final short ST_UPARROWCALLOUT = (short) 79;
public static final short ST_DOWNARROWCALLOUT = (short) 80;
public static final short ST_LEFTRIGHTARROWCALLOUT = (short) 81;
public static final short ST_UPDOWNARROWCALLOUT = (short) 82;
public static final short ST_QUADARROWCALLOUT = (short) 83;
public static final short ST_BEVEL = (short) 84;
public static final short ST_LEFTBRACKET = (short) 85;
public static final short ST_RIGHTBRACKET = (short) 86;
public static final short ST_LEFTBRACE = (short) 87;
public static final short ST_RIGHTBRACE = (short) 88;
public static final short ST_LEFTUPARROW = (short) 89;
public static final short ST_BENTUPARROW = (short) 90;
public static final short ST_BENTARROW = (short) 91;
public static final short ST_SEAL24 = (short) 92;
public static final short ST_STRIPEDRIGHTARROW = (short) 93;
public static final short ST_NOTCHEDRIGHTARROW = (short) 94;
public static final short ST_BLOCKARC = (short) 95;
public static final short ST_SMILEYFACE = (short) 96;
public static final short ST_VERTICALSCROLL = (short) 97;
public static final short ST_HORIZONTALSCROLL = (short) 98;
public static final short ST_CIRCULARARROW = (short) 99;
public static final short ST_NOTCHEDCIRCULARARROW = (short) 100;
public static final short ST_UTURNARROW = (short) 101;
public static final short ST_CURVEDRIGHTARROW = (short) 102;
public static final short ST_CURVEDLEFTARROW = (short) 103;
public static final short ST_CURVEDUPARROW = (short) 104;
public static final short ST_CURVEDDOWNARROW = (short) 105;
public static final short ST_CLOUDCALLOUT = (short) 106;
public static final short ST_ELLIPSERIBBON = (short) 107;
public static final short ST_ELLIPSERIBBON2 = (short) 108;
public static final short ST_FLOWCHARTPROCESS = (short) 109;
public static final short ST_FLOWCHARTDECISION = (short) 110;
public static final short ST_FLOWCHARTINPUTOUTPUT = (short) 111;
public static final short ST_FLOWCHARTPREDEFINEDPROCESS = (short) 112;
public static final short ST_FLOWCHARTINTERNALSTORAGE = (short) 113;
public static final short ST_FLOWCHARTDOCUMENT = (short) 114;
public static final short ST_FLOWCHARTMULTIDOCUMENT = (short) 115;
public static final short ST_FLOWCHARTTERMINATOR = (short) 116;
public static final short ST_FLOWCHARTPREPARATION = (short) 117;
public static final short ST_FLOWCHARTMANUALINPUT = (short) 118;
public static final short ST_FLOWCHARTMANUALOPERATION = (short) 119;
public static final short ST_FLOWCHARTCONNECTOR = (short) 120;
public static final short ST_FLOWCHARTPUNCHEDCARD = (short) 121;
public static final short ST_FLOWCHARTPUNCHEDTAPE = (short) 122;
public static final short ST_FLOWCHARTSUMMINGJUNCTION = (short) 123;
public static final short ST_FLOWCHARTOR = (short) 124;
public static final short ST_FLOWCHARTCOLLATE = (short) 125;
public static final short ST_FLOWCHARTSORT = (short) 126;
public static final short ST_FLOWCHARTEXTRACT = (short) 127;
public static final short ST_FLOWCHARTMERGE = (short) 128;
public static final short ST_FLOWCHARTOFFLINESTORAGE = (short) 129;
public static final short ST_FLOWCHARTONLINESTORAGE = (short) 130;
public static final short ST_FLOWCHARTMAGNETICTAPE = (short) 131;
public static final short ST_FLOWCHARTMAGNETICDISK = (short) 132;
public static final short ST_FLOWCHARTMAGNETICDRUM = (short) 133;
public static final short ST_FLOWCHARTDISPLAY = (short) 134;
public static final short ST_FLOWCHARTDELAY = (short) 135;
public static final short ST_TEXTPLAINTEXT = (short) 136;
public static final short ST_TEXTSTOP = (short) 137;
public static final short ST_TEXTTRIANGLE = (short) 138;
public static final short ST_TEXTTRIANGLEINVERTED = (short) 139;
public static final short ST_TEXTCHEVRON = (short) 140;
public static final short ST_TEXTCHEVRONINVERTED = (short) 141;
public static final short ST_TEXTRINGINSIDE = (short) 142;
public static final short ST_TEXTRINGOUTSIDE = (short) 143;
public static final short ST_TEXTARCHUPCURVE = (short) 144;
public static final short ST_TEXTARCHDOWNCURVE = (short) 145;
public static final short ST_TEXTCIRCLECURVE = (short) 146;
public static final short ST_TEXTBUTTONCURVE = (short) 147;
public static final short ST_TEXTARCHUPPOUR = (short) 148;
public static final short ST_TEXTARCHDOWNPOUR = (short) 149;
public static final short ST_TEXTCIRCLEPOUR = (short) 150;
public static final short ST_TEXTBUTTONPOUR = (short) 151;
public static final short ST_TEXTCURVEUP = (short) 152;
public static final short ST_TEXTCURVEDOWN = (short) 153;
public static final short ST_TEXTCASCADEUP = (short) 154;
public static final short ST_TEXTCASCADEDOWN = (short) 155;
public static final short ST_TEXTWAVE1 = (short) 156;
public static final short ST_TEXTWAVE2 = (short) 157;
public static final short ST_TEXTWAVE3 = (short) 158;
public static final short ST_TEXTWAVE4 = (short) 159;
public static final short ST_TEXTINFLATE = (short) 160;
public static final short ST_TEXTDEFLATE = (short) 161;
public static final short ST_TEXTINFLATEBOTTOM = (short) 162;
public static final short ST_TEXTDEFLATEBOTTOM = (short) 163;
public static final short ST_TEXTINFLATETOP = (short) 164;
public static final short ST_TEXTDEFLATETOP = (short) 165;
public static final short ST_TEXTDEFLATEINFLATE = (short) 166;
public static final short ST_TEXTDEFLATEINFLATEDEFLATE = (short) 167;
public static final short ST_TEXTFADERIGHT = (short) 168;
public static final short ST_TEXTFADELEFT = (short) 169;
public static final short ST_TEXTFADEUP = (short) 170;
public static final short ST_TEXTFADEDOWN = (short) 171;
public static final short ST_TEXTSLANTUP = (short) 172;
public static final short ST_TEXTSLANTDOWN = (short) 173;
public static final short ST_TEXTCANUP = (short) 174;
public static final short ST_TEXTCANDOWN = (short) 175;
public static final short ST_FLOWCHARTALTERNATEPROCESS = (short) 176;
public static final short ST_FLOWCHARTOFFPAGECONNECTOR = (short) 177;
public static final short ST_CALLOUT90 = (short) 178;
public static final short ST_ACCENTCALLOUT90 = (short) 179;
public static final short ST_BORDERCALLOUT90 = (short) 180;
public static final short ST_ACCENTBORDERCALLOUT90 = (short) 181;
public static final short ST_LEFTRIGHTUPARROW = (short) 182;
public static final short ST_SUN = (short) 183;
public static final short ST_MOON = (short) 184;
public static final short ST_BRACKETPAIR = (short) 185;
public static final short ST_BRACEPAIR = (short) 186;
public static final short ST_SEAL4 = (short) 187;
public static final short ST_DOUBLEWAVE = (short) 188;
public static final short ST_ACTIONBUTTONBLANK = (short) 189;
public static final short ST_ACTIONBUTTONHOME = (short) 190;
public static final short ST_ACTIONBUTTONHELP = (short) 191;
public static final short ST_ACTIONBUTTONINFORMATION = (short) 192;
public static final short ST_ACTIONBUTTONFORWARDNEXT = (short) 193;
public static final short ST_ACTIONBUTTONBACKPREVIOUS = (short) 194;
public static final short ST_ACTIONBUTTONEND = (short) 195;
public static final short ST_ACTIONBUTTONBEGINNING = (short) 196;
public static final short ST_ACTIONBUTTONRETURN = (short) 197;
public static final short ST_ACTIONBUTTONDOCUMENT = (short) 198;
public static final short ST_ACTIONBUTTONSOUND = (short) 199;
public static final short ST_ACTIONBUTTONMOVIE = (short) 200;
public static final short ST_HOSTCONTROL = (short) 201;
public static final short ST_TEXTBOX = (short) 202;
public static final short ST_NIL = (short) 0x0FFF;
protected HSSFPatriarch patriarch;
/** Maps shape container objects to their OBJ records */
private Map shapeToObj = new HashMap();
private DrawingManager drawingManager;
private short drawingGroupId;
public EscherAggregate( DrawingManager drawingManager )
{
this.drawingManager = drawingManager;
}
/**
* @return Returns the current sid.
*/
public short getSid()
{
return sid;
}
/**
* Unused since this is an aggregate record. Use createAggregate().
*
* @see #createAggregate
*/
protected void fillFields( byte[] data, short size, int offset )
{
throw new IllegalStateException( "Should not reach here" );
}
/**
* Calculates the string representation of this record. This is
* simply a dump of all the records.
*/
public String toString()
{
String nl = System.getProperty( "line.separtor" );
StringBuffer result = new StringBuffer();
result.append( '[' ).append( getRecordName() ).append( ']' + nl );
for ( Iterator iterator = getEscherRecords().iterator(); iterator.hasNext(); )
{
EscherRecord escherRecord = (EscherRecord) iterator.next();
result.append( escherRecord.toString() );
}
result.append( "[/" ).append( getRecordName() ).append( ']' + nl );
return result.toString();
}
/**
* Collapses the drawing records into an aggregate.
*/
public static EscherAggregate createAggregate( List records, int locFirstDrawingRecord, DrawingManager drawingManager )
{
// Keep track of any shape records created so we can match them back to the object id's.
// Textbox objects are also treated as shape objects.
final List shapeRecords = new ArrayList();
EscherRecordFactory recordFactory = new DefaultEscherRecordFactory()
{
public EscherRecord createRecord( byte[] data, int offset )
{
EscherRecord r = super.createRecord( data, offset );
if ( r.getRecordId() == EscherClientDataRecord.RECORD_ID || r.getRecordId() == EscherTextboxRecord.RECORD_ID )
{
shapeRecords.add( r );
}
return r;
}
};
// Calculate the size of the buffer
EscherAggregate agg = new EscherAggregate(drawingManager);
int loc = locFirstDrawingRecord;
int dataSize = 0;
while ( loc + 1 < records.size()
&& sid( records, loc ) == DrawingRecord.sid
&& isObjectRecord( records, loc + 1 ) )
{
dataSize += ( (DrawingRecord) records.get( loc ) ).getData().length;
loc += 2;
}
// Create one big buffer
byte buffer[] = new byte[dataSize];
int offset = 0;
loc = locFirstDrawingRecord;
while ( loc + 1 < records.size()
&& sid( records, loc ) == DrawingRecord.sid
&& isObjectRecord( records, loc + 1 ) )
{
DrawingRecord drawingRecord = (DrawingRecord) records.get( loc );
System.arraycopy( drawingRecord.getData(), 0, buffer, offset, drawingRecord.getData().length );
offset += drawingRecord.getData().length;
loc += 2;
}
// Decode the shapes
// agg.escherRecords = new ArrayList();
int pos = 0;
while ( pos < dataSize )
{
EscherRecord r = recordFactory.createRecord( buffer, pos );
int bytesRead = r.fillFields( buffer, pos, recordFactory );
agg.addEscherRecord( r );
pos += bytesRead;
}
// Associate the object records with the shapes
loc = locFirstDrawingRecord;
int shapeIndex = 0;
agg.shapeToObj = new HashMap();
while ( loc + 1 < records.size()
&& sid( records, loc ) == DrawingRecord.sid
&& isObjectRecord( records, loc + 1 ) )
{
Record objRecord = (Record) records.get( loc + 1 );
agg.shapeToObj.put( shapeRecords.get( shapeIndex++ ), objRecord );
loc += 2;
}
return agg;
}
/**
* Serializes this aggregate to a byte array. Since this is an aggregate
* record it will effectively serialize the aggregated records.
*
* @param offset The offset into the start of the array.
* @param data The byte array to serialize to.
* @return The number of bytes serialized.
*/
public int serialize( int offset, byte[] data )
{
convertUserModelToRecords();
// Determine buffer size
List records = getEscherRecords();
int size = getEscherRecordSize( records );
byte[] buffer = new byte[size];
// Serialize escher records into one big data structure and keep note of ending offsets.
final List spEndingOffsets = new ArrayList();
final List shapes = new ArrayList();
int pos = 0;
for ( Iterator iterator = records.iterator(); iterator.hasNext(); )
{
EscherRecord e = (EscherRecord) iterator.next();
pos += e.serialize( pos, buffer, new EscherSerializationListener()
{
public void beforeRecordSerialize( int offset, short recordId, EscherRecord record )
{
}
public void afterRecordSerialize( int offset, short recordId, int size, EscherRecord record )
{
if ( recordId == EscherClientDataRecord.RECORD_ID || recordId == EscherTextboxRecord.RECORD_ID )
{
spEndingOffsets.add( new Integer( offset ) );
shapes.add( record );
}
}
} );
}
// todo: fix this
shapes.add( 0, null );
spEndingOffsets.add( 0, null );
// Split escher records into separate MSODRAWING and OBJ, TXO records. (We don't break on
// the first one because it's the patriach).
pos = offset;
for ( int i = 1; i < shapes.size(); i++ )
{
int endOffset = ( (Integer) spEndingOffsets.get( i ) ).intValue() - 1;
int startOffset;
if ( i == 1 )
startOffset = 0;
else
startOffset = ( (Integer) spEndingOffsets.get( i - 1 ) ).intValue();
// Create and write a new MSODRAWING record
DrawingRecord drawing = new DrawingRecord();
byte[] drawingData = new byte[endOffset - startOffset + 1];
System.arraycopy( buffer, startOffset, drawingData, 0, drawingData.length );
drawing.setData( drawingData );
int temp = drawing.serialize( pos, data );
pos += temp;
// Write the matching OBJ record
Record obj = (Record) shapeToObj.get( shapes.get( i ) );
temp = obj.serialize( pos, data );
pos += temp;
}
int bytesWritten = pos - offset;
if ( bytesWritten != getRecordSize() )
throw new RecordFormatException( bytesWritten + " bytes written but getRecordSize() reports " + getRecordSize() );
return bytesWritten;
}
/**
* How many bytes do the raw escher records contain.
* @param records List of escher records
* @return the number of bytes
*/
private int getEscherRecordSize( List records )
{
int size = 0;
for ( Iterator iterator = records.iterator(); iterator.hasNext(); )
size += ( (EscherRecord) iterator.next() ).getRecordSize();
return size;
}
/**
* The number of bytes required to serialize this record.
*/
public int getRecordSize()
{
convertUserModelToRecords();
List records = getEscherRecords();
int rawEscherSize = getEscherRecordSize( records );
int drawingRecordSize = rawEscherSize + ( shapeToObj.size() ) * 4;
int objRecordSize = 0;
for ( Iterator iterator = shapeToObj.values().iterator(); iterator.hasNext(); )
{
Record r = (Record) iterator.next();
objRecordSize += r.getRecordSize();
}
return drawingRecordSize + objRecordSize;
}
/**
* Associates an escher record to an OBJ record or a TXO record.
*/
public Object assoicateShapeToObjRecord( EscherRecord r, Record objRecord )
{
return shapeToObj.put( r, objRecord );
}
public HSSFPatriarch getPatriarch()
{
return patriarch;
}
public void setPatriarch( HSSFPatriarch patriarch )
{
this.patriarch = patriarch;
}
public void clear()
{
clearEscherRecords();
shapeToObj.clear();
// lastShapeId = 1024;
}
protected String getRecordName()
{
return "ESCHERAGGREGATE";
}
// =============== Private methods ========================
private static boolean isObjectRecord( List records, int loc )
{
return sid( records, loc ) == ObjRecord.sid || sid( records, loc ) == TextObjectRecord.sid;
}
private void convertUserModelToRecords()
{
if ( patriarch != null )
{
shapeToObj.clear();
clearEscherRecords();
if ( patriarch.getChildren().size() != 0 )
{
convertPatriarch( patriarch );
EscherContainerRecord dgContainer = (EscherContainerRecord) getEscherRecord( 0 );
EscherContainerRecord spgrContainer = null;
for ( int i = 0; i < dgContainer.getChildRecords().size(); i++ )
if ( dgContainer.getChild( i ).getRecordId() == EscherContainerRecord.SPGR_CONTAINER )
spgrContainer = (EscherContainerRecord) dgContainer.getChild( i );
convertShapes( patriarch, spgrContainer, shapeToObj );
patriarch = null;
}
}
}
private void convertShapes( HSSFShapeContainer parent, EscherContainerRecord escherParent, Map shapeToObj )
{
if ( escherParent == null ) throw new IllegalArgumentException( "Parent record required" );
List shapes = parent.getChildren();
for ( Iterator iterator = shapes.iterator(); iterator.hasNext(); )
{
HSSFShape shape = (HSSFShape) iterator.next();
if ( shape instanceof HSSFShapeGroup )
{
convertGroup( (HSSFShapeGroup) shape, escherParent, shapeToObj );
}
else
{
AbstractShape shapeModel = AbstractShape.createShape(
shape,
drawingManager.allocateShapeId(drawingGroupId) );
shapeToObj.put( findClientData( shapeModel.getSpContainer() ), shapeModel.getObjRecord() );
if ( shapeModel instanceof TextboxShape )
{
EscherRecord escherTextbox = ( (TextboxShape) shapeModel ).getEscherTextbox();
shapeToObj.put( escherTextbox, ( (TextboxShape) shapeModel ).getTextObjectRecord() );
// escherParent.addChildRecord(escherTextbox);
}
escherParent.addChildRecord( shapeModel.getSpContainer() );
}
}
}
private void convertGroup( HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj )
{
EscherContainerRecord spgrContainer = new EscherContainerRecord();
EscherContainerRecord spContainer = new EscherContainerRecord();
EscherSpgrRecord spgr = new EscherSpgrRecord();
EscherSpRecord sp = new EscherSpRecord();
EscherOptRecord opt = new EscherOptRecord();
EscherRecord anchor;
EscherClientDataRecord clientData = new EscherClientDataRecord();
spgrContainer.setRecordId( EscherContainerRecord.SPGR_CONTAINER );
spgrContainer.setOptions( (short) 0x000F );
spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
spContainer.setOptions( (short) 0x000F );
spgr.setRecordId( EscherSpgrRecord.RECORD_ID );
spgr.setOptions( (short) 0x0001 );
spgr.setRectX1( shape.getX1() );
spgr.setRectY1( shape.getY1() );
spgr.setRectX2( shape.getX2() );
spgr.setRectY2( shape.getY2() );
sp.setRecordId( EscherSpRecord.RECORD_ID );
sp.setOptions( (short) 0x0002 );
int shapeId = drawingManager.allocateShapeId(drawingGroupId);
sp.setShapeId( shapeId );
if (shape.getAnchor() instanceof HSSFClientAnchor)
sp.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR );
else
sp.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_CHILD );
opt.setRecordId( EscherOptRecord.RECORD_ID );
opt.setOptions( (short) 0x0023 );
opt.addEscherProperty( new EscherBoolProperty( EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x00040004 ) );
opt.addEscherProperty( new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x00080000 ) );
anchor = ConvertAnchor.createAnchor( shape.getAnchor() );
// clientAnchor.setCol1( ( (HSSFClientAnchor) shape.getAnchor() ).getCol1() );
// clientAnchor.setRow1( (short) ( (HSSFClientAnchor) shape.getAnchor() ).getRow1() );
// clientAnchor.setDx1( (short) shape.getAnchor().getDx1() );
// clientAnchor.setDy1( (short) shape.getAnchor().getDy1() );
// clientAnchor.setCol2( ( (HSSFClientAnchor) shape.getAnchor() ).getCol2() );
// clientAnchor.setRow2( (short) ( (HSSFClientAnchor) shape.getAnchor() ).getRow2() );
// clientAnchor.setDx2( (short) shape.getAnchor().getDx2() );
// clientAnchor.setDy2( (short) shape.getAnchor().getDy2() );
clientData.setRecordId( EscherClientDataRecord.RECORD_ID );
clientData.setOptions( (short) 0x0000 );
spgrContainer.addChildRecord( spContainer );
spContainer.addChildRecord( spgr );
spContainer.addChildRecord( sp );
spContainer.addChildRecord( opt );
spContainer.addChildRecord( anchor );
spContainer.addChildRecord( clientData );
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord();
cmo.setObjectType( CommonObjectDataSubRecord.OBJECT_TYPE_GROUP );
cmo.setObjectId( (short) ( shapeId ) );
cmo.setLocked( true );
cmo.setPrintable( true );
cmo.setAutofill( true );
cmo.setAutoline( true );
GroupMarkerSubRecord gmo = new GroupMarkerSubRecord();
EndSubRecord end = new EndSubRecord();
obj.addSubRecord( cmo );
obj.addSubRecord( gmo );
obj.addSubRecord( end );
shapeToObj.put( clientData, obj );
escherParent.addChildRecord( spgrContainer );
convertShapes( shape, spgrContainer, shapeToObj );
}
private EscherRecord findClientData( EscherContainerRecord spContainer )
{
for ( Iterator iterator = spContainer.getChildRecords().iterator(); iterator.hasNext(); )
{
EscherRecord r = (EscherRecord) iterator.next();
if ( r.getRecordId() == EscherClientDataRecord.RECORD_ID )
return r;
}
throw new IllegalArgumentException( "Can not find client data record" );
}
private void convertPatriarch( HSSFPatriarch patriarch )
{
EscherContainerRecord dgContainer = new EscherContainerRecord();
EscherDgRecord dg;
EscherContainerRecord spgrContainer = new EscherContainerRecord();
EscherContainerRecord spContainer1 = new EscherContainerRecord();
EscherSpgrRecord spgr = new EscherSpgrRecord();
EscherSpRecord sp1 = new EscherSpRecord();
dgContainer.setRecordId( EscherContainerRecord.DG_CONTAINER );
dgContainer.setOptions( (short) 0x000F );
dg = drawingManager.createDgRecord();
drawingGroupId = dg.getDrawingGroupId();
// dg.setOptions( (short) ( drawingId << 4 ) );
// dg.setNumShapes( getNumberOfShapes( patriarch ) );
// dg.setLastMSOSPID( 0 ); // populated after all shape id's are assigned.
spgrContainer.setRecordId( EscherContainerRecord.SPGR_CONTAINER );
spgrContainer.setOptions( (short) 0x000F );
spContainer1.setRecordId( EscherContainerRecord.SP_CONTAINER );
spContainer1.setOptions( (short) 0x000F );
spgr.setRecordId( EscherSpgrRecord.RECORD_ID );
spgr.setOptions( (short) 0x0001 ); // don't know what the 1 is for.
spgr.setRectX1( patriarch.getX1() );
spgr.setRectY1( patriarch.getY1() );
spgr.setRectX2( patriarch.getX2() );
spgr.setRectY2( patriarch.getY2() );
sp1.setRecordId( EscherSpRecord.RECORD_ID );
sp1.setOptions( (short) 0x0002 );
sp1.setShapeId( drawingManager.allocateShapeId(dg.getDrawingGroupId()) );
sp1.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_PATRIARCH );
dgContainer.addChildRecord( dg );
dgContainer.addChildRecord( spgrContainer );
spgrContainer.addChildRecord( spContainer1 );
spContainer1.addChildRecord( spgr );
spContainer1.addChildRecord( sp1 );
addEscherRecord( dgContainer );
}
/** Retrieve the number of shapes (including the patriarch). */
// private int getNumberOfShapes( HSSFPatriarch patriarch )
// {
// return patriarch.countOfAllChildren();
// }
private static short sid( List records, int loc )
{
return ( (Record) records.get( loc ) ).getSid();
}
}

View File

@ -0,0 +1,176 @@
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache POI" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache POI", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.poi.hssf.record;
import org.apache.poi.util.*;
/**
* The group marker record is used as a position holder for groups.
* @author Glen Stampoultzis (glens at apache.org)
*/
public class GroupMarkerSubRecord
extends SubRecord
{
public final static short sid = 0x06;
private byte[] reserved = new byte[0]; // would really love to know what goes in here.
public GroupMarkerSubRecord()
{
}
/**
* Constructs a group marker record and sets its fields appropriately.
*
* @param id id must be 0x00 or an exception
* will be throw upon validation
* @param size size the size of the data area of the record
* @param data data of the record (should not contain sid/len)
*/
public GroupMarkerSubRecord(short id, short size, byte [] data)
{
super(id, size, data);
}
/**
* Constructs a group marker record and sets its fields appropriately.
*
* @param id id must be 0x00 or an exception
* will be throw upon validation
* @param size size the size of the data area of the record
* @param data data of the record (should not contain sid/len)
* @param offset of the record's data
*/
public GroupMarkerSubRecord(short id, short size, byte [] data, int offset)
{
super(id, size, data, offset);
}
/**
* Checks the sid matches the expected side for this record
*
* @param id the expected sid.
*/
protected void validateSid(short id)
{
if (id != sid)
{
throw new RecordFormatException("Not a Group Marker record");
}
}
protected void fillFields(byte [] data, short size, int offset)
{
// int pos = 0;
reserved = new byte[size];
System.arraycopy(data, offset, reserved, 0, size);
}
public String toString()
{
StringBuffer buffer = new StringBuffer();
String nl = System.getProperty("line.separator");
buffer.append("[ftGmo]" + nl);
buffer.append(" reserved = ").append(HexDump.toHex(reserved)).append(nl);
buffer.append("[/ftGmo]" + nl);
return buffer.toString();
}
public int serialize(int offset, byte[] data)
{
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
System.arraycopy(reserved, 0, data, offset + 4, getRecordSize() - 4);
return getRecordSize();
}
/**
* Size of record (exluding 4 byte header)
*/
public int getRecordSize()
{
return 4 + reserved.length;
}
public short getSid()
{
return sid;
}
public Object clone() {
GroupMarkerSubRecord rec = new GroupMarkerSubRecord();
rec.reserved = new byte[reserved.length];
for ( int i = 0; i < reserved.length; i++ )
rec.reserved[i] = reserved[i];
return rec;
}
} // END OF CLASS

View File

@ -0,0 +1,227 @@
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache POI" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache POI", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.poi.hssf.record;
import org.apache.poi.util.*;
import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;
/**
* The obj record is used to hold various graphic objects and controls.
*
* @author Glen Stampoultzis (glens at apache.org)
*/
public class ObjRecord
extends Record
{
public final static short sid = 0x5D;
private List subrecords;
//00000000 15 00 12 00 01 00 01 00 11 60 00 00 00 00 00 0D .........`......
//00000010 26 01 00 00 00 00 00 00 00 00 &.........
public ObjRecord()
{
subrecords = new ArrayList(2);
}
/**
* Constructs a OBJ record and sets its fields appropriately.
*
* @param id id must be 0x5D or an exception
* will be throw upon validation
* @param size size the size of the data area of the record
* @param data data of the record (should not contain sid/len)
*/
public ObjRecord(short id, short size, byte [] data)
{
super(id, size, data);
}
/**
* Constructs a obj record and sets its fields appropriately.
*
* @param id id must be 0x5D or an exception
* will be throw upon validation
* @param size size the size of the data area of the record
* @param data data of the record (should not contain sid/len)
* @param offset of the record's data
*/
public ObjRecord(short id, short size, byte[] data, int offset)
{
super(id, size, data, offset);
}
/**
* Checks the sid matches the expected side for this record
*
* @param id the expected sid.
*/
protected void validateSid(short id)
{
if (id != sid)
{
throw new RecordFormatException("Not an OBJ record");
}
}
protected void fillFields(byte [] data, short size, int offset)
{
subrecords = new ArrayList();
int pos = offset;
while (pos - offset < size)
{
short subRecordSid = LittleEndian.getShort(data, pos);
short subRecordSize = LittleEndian.getShort(data, pos + 2);
Record subRecord = SubRecord.createSubRecord(subRecordSid, subRecordSize, data, pos + 4);
subrecords.add(subRecord);
pos += 4 + subRecordSize;
}
}
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append("[OBJ]\n");
for ( Iterator iterator = subrecords.iterator(); iterator.hasNext(); )
{
Record record = (Record) iterator.next();
buffer.append("SUBRECORD: " + record.toString());
}
buffer.append("[/OBJ]\n");
return buffer.toString();
}
public int serialize(int offset, byte[] data)
{
int pos = 0;
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
pos = offset + 4;
for ( Iterator iterator = subrecords.iterator(); iterator.hasNext(); )
{
Record record = (Record) iterator.next();
pos += record.serialize(pos, data);
}
return getRecordSize();
}
/**
* Size of record (excluding 4 byte header)
*/
public int getRecordSize()
{
int size = 0;
for ( Iterator iterator = subrecords.iterator(); iterator.hasNext(); )
{
Record record = (Record) iterator.next();
size += record.getRecordSize();
}
return 4 + size;
}
public short getSid()
{
return sid;
}
public List getSubRecords()
{
return subrecords;
}
public void clearSubRecords()
{
subrecords.clear();
}
public void addSubRecord(int index, Object element)
{
subrecords.add( index, element );
}
public boolean addSubRecord(Object o)
{
return subrecords.add( o );
}
public Object clone()
{
ObjRecord rec = new ObjRecord();
rec.subrecords = new ArrayList();
for ( Iterator iterator = subrecords.iterator(); iterator.hasNext(); )
subrecords.add(( (Record) iterator.next() ).clone());
return rec;
}
} // END OF CLASS

View File

@ -55,15 +55,13 @@
package org.apache.poi.hssf.record;
import java.io.InputStream;
import java.io.IOException;
import java.util.*;
import java.lang.reflect.Constructor;
import org.apache.poi.util.LittleEndian;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.*;
/**
* Title: Record Factory<P>
* Description: Takes a stream and outputs an array of Record objects.<P>
@ -112,6 +110,8 @@ public class RecordFactory
FormulaRecord.class, BoolErrRecord.class, ExternSheetRecord.class,
NameRecord.class, LeftMarginRecord.class, RightMarginRecord.class,
TopMarginRecord.class, BottomMarginRecord.class,
DrawingRecord.class, DrawingGroupRecord.class, DrawingSelectionRecord.class,
ObjRecord.class, TextObjectRecord.class,
PaletteRecord.class, StringRecord.class, RecalcIdRecord.class, SharedFormulaRecord.class,
HorizontalPageBreakRecord.class, VerticalPageBreakRecord.class
};
@ -145,6 +145,8 @@ public class RecordFactory
LeftMarginRecord.class, RightMarginRecord.class,
TopMarginRecord.class, BottomMarginRecord.class,
PaletteRecord.class, StringRecord.class, RecalcIdRecord.class, SharedFormulaRecord.class,
DrawingRecord.class, DrawingGroupRecord.class, DrawingSelectionRecord.class,
ObjRecord.class, TextObjectRecord.class,
HorizontalPageBreakRecord.class, VerticalPageBreakRecord.class
};
@ -362,6 +364,7 @@ public class RecordFactory
}
catch (Exception illegalArgumentException)
{
illegalArgumentException.printStackTrace();
throw new RecordFormatException(
"Unable to determine record types");
}

View File

@ -0,0 +1,98 @@
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache POI" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache POI", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.poi.hssf.record;
/**
* Subrecords are part of the OBJ class.
*/
abstract public class SubRecord
extends Record
{
public SubRecord()
{
}
public SubRecord( short id, short size, byte[] data )
{
super( id, size, data );
}
public SubRecord( short id, short size, byte[] data, int offset )
{
super( id, size, data, offset );
}
public static Record createSubRecord( short subRecordSid, short size, byte[] data, int offset )
{
Record r = null;
switch ( subRecordSid )
{
case CommonObjectDataSubRecord.sid:
r = new CommonObjectDataSubRecord( subRecordSid, size, data, offset );
break;
case GroupMarkerSubRecord.sid:
r = new GroupMarkerSubRecord( subRecordSid, size, data, offset );
break;
case EndSubRecord.sid:
r = new EndSubRecord( subRecordSid, size, data, offset );
break;
default:
r = new UnknownRecord( subRecordSid, size, data, offset );
}
return r;
}
}

View File

@ -0,0 +1,519 @@
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache POI" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache POI", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.poi.hssf.record;
import org.apache.poi.util.*;
/**
* The TXO record is used to define the properties of a text box. It is followed
by two continue records unless there is no actual text. The first continue record contains
the text data and the next continue record contains the formatting runs.
* NOTE: This source is automatically generated please do not modify this file. Either subclass or
* remove the record in src/records/definitions.
* @author Glen Stampoultzis (glens at apache.org)
*/
public class TextObjectBaseRecord
extends Record
{
public final static short sid = 0x1B6;
private short field_1_options;
private BitField reserved1 = new BitField(0x1);
private BitField HorizontalTextAlignment = new BitField(0x000E);
public final static short HORIZONTAL_TEXT_ALIGNMENT_LEFT_ALIGNED = 1;
public final static short HORIZONTAL_TEXT_ALIGNMENT_CENTERED = 2;
public final static short HORIZONTAL_TEXT_ALIGNMENT_RIGHT_ALIGNED = 3;
public final static short HORIZONTAL_TEXT_ALIGNMENT_JUSTIFIED = 4;
private BitField VerticalTextAlignment = new BitField(0x0070);
public final static short VERTICAL_TEXT_ALIGNMENT_TOP = 1;
public final static short VERTICAL_TEXT_ALIGNMENT_CENTER = 2;
public final static short VERTICAL_TEXT_ALIGNMENT_BOTTOM = 3;
public final static short VERTICAL_TEXT_ALIGNMENT_JUSTIFY = 4;
private BitField reserved2 = new BitField(0x0180);
private BitField textLocked = new BitField(0x200);
private BitField reserved3 = new BitField(0xFC00);
private short field_2_textOrientation;
public final static short TEXT_ORIENTATION_NONE = 0;
public final static short TEXT_ORIENTATION_TOP_TO_BOTTOM = 1;
public final static short TEXT_ORIENTATION_ROT_RIGHT = 2;
public final static short TEXT_ORIENTATION_ROT_LEFT = 3;
private short field_3_reserved4;
private short field_4_reserved5;
private short field_5_reserved6;
private short field_6_textLength;
private short field_7_formattingRunLength;
private int field_8_reserved7;
public TextObjectBaseRecord()
{
}
/**
* Constructs a TextObjectBase record and sets its fields appropriately.
*
* @param id id must be 0x1B6 or an exception
* will be throw upon validation
* @param size size the size of the data area of the record
* @param data data of the record (should not contain sid/len)
*/
public TextObjectBaseRecord(short id, short size, byte [] data)
{
super(id, size, data);
}
/**
* Constructs a TextObjectBase record and sets its fields appropriately.
*
* @param id id must be 0x1B6 or an exception
* will be throw upon validation
* @param size size the size of the data area of the record
* @param data data of the record (should not contain sid/len)
* @param offset of the record's data
*/
public TextObjectBaseRecord(short id, short size, byte [] data, int offset)
{
super(id, size, data, offset);
}
/**
* Checks the sid matches the expected side for this record
*
* @param id the expected sid.
*/
protected void validateSid(short id)
{
if (id != sid)
{
throw new RecordFormatException("Not a TextObjectBase record");
}
}
protected void fillFields(byte [] data, short size, int offset)
{
int pos = 0;
field_1_options = LittleEndian.getShort(data, pos + 0x0 + offset);
field_2_textOrientation = LittleEndian.getShort(data, pos + 0x2 + offset);
field_3_reserved4 = LittleEndian.getShort(data, pos + 0x4 + offset);
field_4_reserved5 = LittleEndian.getShort(data, pos + 0x6 + offset);
field_5_reserved6 = LittleEndian.getShort(data, pos + 0x8 + offset);
field_6_textLength = LittleEndian.getShort(data, pos + 0xa + offset);
field_7_formattingRunLength = LittleEndian.getShort(data, pos + 0xc + offset);
field_8_reserved7 = LittleEndian.getInt(data, pos + 0xe + offset);
}
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append("[TXO]\n");
buffer.append(" .options = ")
.append("0x").append(HexDump.toHex( getOptions ()))
.append(" (").append( getOptions() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append(" .reserved1 = ").append(isReserved1()).append('\n');
buffer.append(" .HorizontalTextAlignment = ").append(getHorizontalTextAlignment()).append('\n');
buffer.append(" .VerticalTextAlignment = ").append(getVerticalTextAlignment()).append('\n');
buffer.append(" .reserved2 = ").append(getReserved2()).append('\n');
buffer.append(" .textLocked = ").append(isTextLocked()).append('\n');
buffer.append(" .reserved3 = ").append(getReserved3()).append('\n');
buffer.append(" .textOrientation = ")
.append("0x").append(HexDump.toHex( getTextOrientation ()))
.append(" (").append( getTextOrientation() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append(" .reserved4 = ")
.append("0x").append(HexDump.toHex( getReserved4 ()))
.append(" (").append( getReserved4() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append(" .reserved5 = ")
.append("0x").append(HexDump.toHex( getReserved5 ()))
.append(" (").append( getReserved5() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append(" .reserved6 = ")
.append("0x").append(HexDump.toHex( getReserved6 ()))
.append(" (").append( getReserved6() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append(" .textLength = ")
.append("0x").append(HexDump.toHex( getTextLength ()))
.append(" (").append( getTextLength() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append(" .formattingRunLength = ")
.append("0x").append(HexDump.toHex( getFormattingRunLength ()))
.append(" (").append( getFormattingRunLength() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append(" .reserved7 = ")
.append("0x").append(HexDump.toHex( getReserved7 ()))
.append(" (").append( getReserved7() ).append(" )");
buffer.append(System.getProperty("line.separator"));
buffer.append("[/TXO]\n");
return buffer.toString();
}
public int serialize(int offset, byte[] data)
{
int pos = 0;
LittleEndian.putShort(data, 0 + offset, sid);
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
LittleEndian.putShort(data, 4 + offset + pos, field_1_options);
LittleEndian.putShort(data, 6 + offset + pos, field_2_textOrientation);
LittleEndian.putShort(data, 8 + offset + pos, field_3_reserved4);
LittleEndian.putShort(data, 10 + offset + pos, field_4_reserved5);
LittleEndian.putShort(data, 12 + offset + pos, field_5_reserved6);
LittleEndian.putShort(data, 14 + offset + pos, field_6_textLength);
LittleEndian.putShort(data, 16 + offset + pos, field_7_formattingRunLength);
LittleEndian.putInt(data, 18 + offset + pos, field_8_reserved7);
return getRecordSize();
}
/**
* Size of record (exluding 4 byte header)
*/
public int getRecordSize()
{
return 4 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 4;
}
public short getSid()
{
return this.sid;
}
public Object clone() {
TextObjectBaseRecord rec = new TextObjectBaseRecord();
rec.field_1_options = field_1_options;
rec.field_2_textOrientation = field_2_textOrientation;
rec.field_3_reserved4 = field_3_reserved4;
rec.field_4_reserved5 = field_4_reserved5;
rec.field_5_reserved6 = field_5_reserved6;
rec.field_6_textLength = field_6_textLength;
rec.field_7_formattingRunLength = field_7_formattingRunLength;
rec.field_8_reserved7 = field_8_reserved7;
return rec;
}
/**
* Get the options field for the TextObjectBase record.
*/
public short getOptions()
{
return field_1_options;
}
/**
* Set the options field for the TextObjectBase record.
*/
public void setOptions(short field_1_options)
{
this.field_1_options = field_1_options;
}
/**
* Get the text orientation field for the TextObjectBase record.
*
* @return One of
* TEXT_ORIENTATION_NONE
* TEXT_ORIENTATION_TOP_TO_BOTTOM
* TEXT_ORIENTATION_ROT_RIGHT
* TEXT_ORIENTATION_ROT_LEFT
*/
public short getTextOrientation()
{
return field_2_textOrientation;
}
/**
* Set the text orientation field for the TextObjectBase record.
*
* @param field_2_textOrientation
* One of
* TEXT_ORIENTATION_NONE
* TEXT_ORIENTATION_TOP_TO_BOTTOM
* TEXT_ORIENTATION_ROT_RIGHT
* TEXT_ORIENTATION_ROT_LEFT
*/
public void setTextOrientation(short field_2_textOrientation)
{
this.field_2_textOrientation = field_2_textOrientation;
}
/**
* Get the reserved4 field for the TextObjectBase record.
*/
public short getReserved4()
{
return field_3_reserved4;
}
/**
* Set the reserved4 field for the TextObjectBase record.
*/
public void setReserved4(short field_3_reserved4)
{
this.field_3_reserved4 = field_3_reserved4;
}
/**
* Get the reserved5 field for the TextObjectBase record.
*/
public short getReserved5()
{
return field_4_reserved5;
}
/**
* Set the reserved5 field for the TextObjectBase record.
*/
public void setReserved5(short field_4_reserved5)
{
this.field_4_reserved5 = field_4_reserved5;
}
/**
* Get the reserved6 field for the TextObjectBase record.
*/
public short getReserved6()
{
return field_5_reserved6;
}
/**
* Set the reserved6 field for the TextObjectBase record.
*/
public void setReserved6(short field_5_reserved6)
{
this.field_5_reserved6 = field_5_reserved6;
}
/**
* Get the text length field for the TextObjectBase record.
*/
public short getTextLength()
{
return field_6_textLength;
}
/**
* Set the text length field for the TextObjectBase record.
*/
public void setTextLength(short field_6_textLength)
{
this.field_6_textLength = field_6_textLength;
}
/**
* Get the formatting run length field for the TextObjectBase record.
*/
public short getFormattingRunLength()
{
return field_7_formattingRunLength;
}
/**
* Set the formatting run length field for the TextObjectBase record.
*/
public void setFormattingRunLength(short field_7_formattingRunLength)
{
this.field_7_formattingRunLength = field_7_formattingRunLength;
}
/**
* Get the reserved7 field for the TextObjectBase record.
*/
public int getReserved7()
{
return field_8_reserved7;
}
/**
* Set the reserved7 field for the TextObjectBase record.
*/
public void setReserved7(int field_8_reserved7)
{
this.field_8_reserved7 = field_8_reserved7;
}
/**
* Sets the reserved1 field value.
* reserved field
*/
public void setReserved1(boolean value)
{
field_1_options = reserved1.setShortBoolean(field_1_options, value);
}
/**
* reserved field
* @return the reserved1 field value.
*/
public boolean isReserved1()
{
return reserved1.isSet(field_1_options);
}
/**
* Sets the Horizontal text alignment field value.
*
*/
public void setHorizontalTextAlignment(short value)
{
field_1_options = HorizontalTextAlignment.setShortValue(field_1_options, value);
}
/**
*
* @return the Horizontal text alignment field value.
*/
public short getHorizontalTextAlignment()
{
return HorizontalTextAlignment.getShortValue(field_1_options);
}
/**
* Sets the Vertical text alignment field value.
*
*/
public void setVerticalTextAlignment(short value)
{
field_1_options = VerticalTextAlignment.setShortValue(field_1_options, value);
}
/**
*
* @return the Vertical text alignment field value.
*/
public short getVerticalTextAlignment()
{
return VerticalTextAlignment.getShortValue(field_1_options);
}
/**
* Sets the reserved2 field value.
*
*/
public void setReserved2(short value)
{
field_1_options = reserved2.setShortValue(field_1_options, value);
}
/**
*
* @return the reserved2 field value.
*/
public short getReserved2()
{
return reserved2.getShortValue(field_1_options);
}
/**
* Sets the text locked field value.
* Text has been locked
*/
public void setTextLocked(boolean value)
{
field_1_options = textLocked.setShortBoolean(field_1_options, value);
}
/**
* Text has been locked
* @return the text locked field value.
*/
public boolean isTextLocked()
{
return textLocked.isSet(field_1_options);
}
/**
* Sets the reserved3 field value.
*
*/
public void setReserved3(short value)
{
field_1_options = reserved3.setShortValue(field_1_options, value);
}
/**
*
* @return the reserved3 field value.
*/
public short getReserved3()
{
return reserved3.getShortValue(field_1_options);
}
} // END OF CLASS

View File

@ -0,0 +1,216 @@
package org.apache.poi.hssf.record;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.util.StringUtil;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.HexDump;
import java.io.UnsupportedEncodingException;
public class TextObjectRecord
extends TextObjectBaseRecord
{
HSSFRichTextString str = new HSSFRichTextString( "" );
int continueRecordCount = 0; // how many times has continue record been called?
public TextObjectRecord()
{
}
public TextObjectRecord( short id, short size, byte[] data )
{
super( id, size, data );
}
public TextObjectRecord( short id, short size, byte[] data, int offset )
{
super( id, size, data, offset );
}
public int getRecordSize()
{
int continue1Size = 0;
int continue2Size = 0;
if (str.length() != 0)
{
continue1Size = str.length() * 2 + 1 + 4;
continue2Size = (str.numFormattingRuns() + 1) * 8 + 4;
}
return super.getRecordSize() + continue1Size + continue2Size;
}
public int serialize( int offset, byte[] data )
{
// Temporarily blank out str so that record size is calculated without the continue records.
HSSFRichTextString temp = str;
str = new HSSFRichTextString("");
int bytesWritten1 = super.serialize( offset, data );
str = temp;
int pos = offset + bytesWritten1;
if ( str.toString().equals( "" ) == false )
{
ContinueRecord c1 = createContinue1();
ContinueRecord c2 = createContinue2();
int bytesWritten2 = c1.serialize( pos, data );
pos += bytesWritten2;
int bytesWritten3 = c2.serialize( pos, data );
pos += bytesWritten3;
int size = bytesWritten1 + bytesWritten2 + bytesWritten3;
if ( size != getRecordSize() )
throw new RecordFormatException(size + " bytes written but getRecordSize() reports " + getRecordSize());
return size;
}
if ( bytesWritten1 != getRecordSize() )
throw new RecordFormatException(bytesWritten1 + " bytes written but getRecordSize() reports " + getRecordSize());
return bytesWritten1;
}
private ContinueRecord createContinue1()
{
ContinueRecord c1 = new ContinueRecord();
byte[] c1Data = new byte[str.length() * 2 + 1];
try
{
c1Data[0] = 1;
System.arraycopy( str.toString().getBytes( "UTF-16LE" ), 0, c1Data, 1, str.length() * 2 );
}
catch ( UnsupportedEncodingException e )
{
throw new RuntimeException( e.getMessage() );
}
c1.setData( c1Data );
return c1;
}
private ContinueRecord createContinue2()
{
ContinueRecord c2 = new ContinueRecord();
byte[] c2Data = new byte[str.numFormattingRuns() * 8 + 8];
int pos = 0;
for ( int i = 0; i < str.numFormattingRuns(); i++ )
{
LittleEndian.putShort( c2Data, pos, (short) str.getIndexOfFormattingRun( i ) );
pos += 2;
LittleEndian.putShort( c2Data, pos, str.getFontOfFormattingRun( i ) == str.NO_FONT ? 0 : str.getFontOfFormattingRun( i ) );
pos += 2;
pos += 4; // skip reserved
}
LittleEndian.putShort( c2Data, pos, (short) str.length() );
pos += 2;
LittleEndian.putShort( c2Data, pos, (short) 0 );
pos += 2;
pos += 4; // skip reserved
c2.setData( c2Data );
return c2;
}
public void processContinueRecord( byte[] data )
{
if ( continueRecordCount == 0 )
processRawString( data );
else
processFontRuns( data );
continueRecordCount++;
}
private void processFontRuns( byte[] data )
{
int pos = 0;
do
{
short index = LittleEndian.getShort( data, pos );
pos += 2;
short iFont = LittleEndian.getShort( data, pos );
pos += 2;
pos += 4; // skip reserved.
if ( index >= str.length() )
break;
str.applyFont( index, str.length(), iFont );
}
while ( true );
}
private void processRawString( byte[] data )
{
String s;
int pos = 0;
byte compressByte = data[pos++];
boolean isCompressed = compressByte == 0;
try
{
if ( isCompressed )
{
s = new String( data, pos, getTextLength(), StringUtil.getPreferredEncoding() );
}
else
{
s = new String( data, pos, getTextLength() * 2, "UTF-16LE" );
}
}
catch ( UnsupportedEncodingException e )
{
throw new RuntimeException( e.getMessage() );
}
str = new HSSFRichTextString( s );
}
public HSSFRichTextString getStr()
{
return str;
}
public void setStr( HSSFRichTextString str )
{
this.str = str;
}
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append( "[TXO]\n" );
buffer.append( " .options = " )
.append( "0x" ).append( HexDump.toHex( getOptions() ) )
.append( " (" ).append( getOptions() ).append( " )" );
buffer.append( System.getProperty( "line.separator" ) );
buffer.append( " .reserved1 = " ).append( isReserved1() ).append( '\n' );
buffer.append( " .HorizontalTextAlignment = " ).append( getHorizontalTextAlignment() ).append( '\n' );
buffer.append( " .VerticalTextAlignment = " ).append( getVerticalTextAlignment() ).append( '\n' );
buffer.append( " .reserved2 = " ).append( getReserved2() ).append( '\n' );
buffer.append( " .textLocked = " ).append( isTextLocked() ).append( '\n' );
buffer.append( " .reserved3 = " ).append( getReserved3() ).append( '\n' );
buffer.append( " .textOrientation = " )
.append( "0x" ).append( HexDump.toHex( getTextOrientation() ) )
.append( " (" ).append( getTextOrientation() ).append( " )" );
buffer.append( System.getProperty( "line.separator" ) );
buffer.append( " .reserved4 = " )
.append( "0x" ).append( HexDump.toHex( getReserved4() ) )
.append( " (" ).append( getReserved4() ).append( " )" );
buffer.append( System.getProperty( "line.separator" ) );
buffer.append( " .reserved5 = " )
.append( "0x" ).append( HexDump.toHex( getReserved5() ) )
.append( " (" ).append( getReserved5() ).append( " )" );
buffer.append( System.getProperty( "line.separator" ) );
buffer.append( " .reserved6 = " )
.append( "0x" ).append( HexDump.toHex( getReserved6() ) )
.append( " (" ).append( getReserved6() ).append( " )" );
buffer.append( System.getProperty( "line.separator" ) );
buffer.append( " .textLength = " )
.append( "0x" ).append( HexDump.toHex( getTextLength() ) )
.append( " (" ).append( getTextLength() ).append( " )" );
buffer.append( System.getProperty( "line.separator" ) );
buffer.append( " .reserved7 = " )
.append( "0x" ).append( HexDump.toHex( getReserved7() ) )
.append( " (" ).append( getReserved7() ).append( " )" );
buffer.append( System.getProperty( "line.separator" ) );
buffer.append( " .string = " ).append(str).append('\n');
buffer.append( "[/TXO]\n" );
return buffer.toString();
}
}

View File

@ -1,4 +1,3 @@
/* ====================================================================
* The Apache Software License, Version 1.1
*
@ -92,10 +91,16 @@ public class UnknownRecord
thedata = data;
}
/**
* spit the record out AS IS. no interperatation or identification
*/
public UnknownRecord( short id, short size, byte[] data, int offset )
{
sid = id;
thedata = new byte[size];
System.arraycopy(data, offset, thedata, 0, size);
}
/**
* spit the record out AS IS. no interpretation or identification
*/
public int serialize(int offset, byte [] data)
{
if (thedata == null)