mirror of https://github.com/apache/poi.git
Added image support for POI. See the quick guide for details. Sponsored through superlink software.
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353660 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3c991cfc7a
commit
585f86a986
12
build.xml
12
build.xml
|
@ -256,10 +256,10 @@
|
|||
<copy todir="${main.output.dir}">
|
||||
<fileset dir="${main.resource1.dir}"/>
|
||||
</copy>
|
||||
<javac srcdir="${main.src}" destdir="${main.output.dir}" debug="on">
|
||||
<javac srcdir="${main.src}" destdir="${main.output.dir}" debug="on" fork="yes" includeAntRuntime="no" failonerror="true">
|
||||
<classpath refid="main.classpath"/>
|
||||
</javac>
|
||||
<javac srcdir="${main.src.test}" destdir="${main.output.test.dir}" debug="on">
|
||||
<javac srcdir="${main.src.test}" destdir="${main.output.test.dir}" debug="on" fork="yes" includeAntRuntime="no" failonerror="true">
|
||||
<classpath>
|
||||
<path refid="main.classpath"/>
|
||||
<pathelement location="${main.output.dir}"/>
|
||||
|
@ -269,10 +269,10 @@
|
|||
</target>
|
||||
|
||||
<target name="compile-scratchpad" depends="init">
|
||||
<javac srcdir="${scratchpad.src}" destdir="${scratchpad.output.dir}" debug="on">
|
||||
<javac srcdir="${scratchpad.src}" destdir="${scratchpad.output.dir}" debug="on" fork="yes" includeAntRuntime="no" failonerror="true">
|
||||
<classpath refid="scratchpad.classpath"/>
|
||||
</javac>
|
||||
<javac srcdir="${scratchpad.src.test}" destdir="${scratchpad.output.test.dir}" debug="on">
|
||||
<javac srcdir="${scratchpad.src.test}" destdir="${scratchpad.output.test.dir}" debug="on" fork="yes" includeAntRuntime="no" failonerror="true">
|
||||
<classpath>
|
||||
<path refid="scratchpad.classpath"/>
|
||||
<pathelement location="${scratchpad.output.dir}"/>
|
||||
|
@ -282,10 +282,10 @@
|
|||
</target>
|
||||
|
||||
<target name="compile-contrib" depends="init">
|
||||
<javac srcdir="${contrib.src}" destdir="${contrib.output.dir}" debug="on">
|
||||
<javac srcdir="${contrib.src}" destdir="${contrib.output.dir}" debug="on" fork="yes" includeAntRuntime="no" failonerror="true">
|
||||
<classpath refid="contrib.classpath"/>
|
||||
</javac>
|
||||
<javac srcdir="${contrib.src.test}" destdir="${contrib.output.test.dir}" debug="on">
|
||||
<javac srcdir="${contrib.src.test}" destdir="${contrib.output.test.dir}" debug="on" fork="yes" includeAntRuntime="no" failonerror="true">
|
||||
<classpath>
|
||||
<path refid="contrib.classpath"/>
|
||||
<pathelement location="${contrib.output.dir}"/>
|
||||
|
|
|
@ -31,20 +31,21 @@
|
|||
<li><link href="#CustomColors">Custom colors</link></li>
|
||||
<li><link href="#ReadWriteWorkbook">Reading and writing</link></li>
|
||||
<li><link href="#NewLinesInCells">Use newlines in cells.</link></li>
|
||||
<li><link href="#DataFormats">Create user defined data formats.</link></li>
|
||||
<li><link href="#DataFormats">Create user defined data formats</link></li>
|
||||
<li><link href="#FitTo">Fit Sheet to One Page</link></li>
|
||||
<li><link href="#PrintArea2">Set print area for a sheet.</link></li>
|
||||
<li><link href="#FooterPageNumbers">Set page numbers on the footer of a sheet.</link></li>
|
||||
<li><link href="#ShiftRows">Shift rows.</link></li>
|
||||
<li><link href="#SelectSheet">Set a sheet as selected.</link></li>
|
||||
<li><link href="#Zoom">Set the zoom magnification for a sheet.</link></li>
|
||||
<li><link href="#Splits">Create split and freeze panes.</link></li>
|
||||
<li><link href="#Repeating">Repeating rows and columns.</link></li>
|
||||
<li><link href="#HeaderFooter">Headers and Footers.</link></li>
|
||||
<li><link href="#DrawingShapes">Drawing Shapes.</link></li>
|
||||
<li><link href="#StylingShapes">Styling Shapes.</link></li>
|
||||
<li><link href="#Graphics2d">Shapes and Graphics2d.</link></li>
|
||||
<li><link href="#Outlining">Outlining.</link></li>
|
||||
<li><link href="#PrintArea2">Set print area for a sheet</link></li>
|
||||
<li><link href="#FooterPageNumbers">Set page numbers on the footer of a sheet</link></li>
|
||||
<li><link href="#ShiftRows">Shift rows</link></li>
|
||||
<li><link href="#SelectSheet">Set a sheet as selected</link></li>
|
||||
<li><link href="#Zoom">Set the zoom magnification for a sheet</link></li>
|
||||
<li><link href="#Splits">Create split and freeze panes</link></li>
|
||||
<li><link href="#Repeating">Repeating rows and columns</link></li>
|
||||
<li><link href="#HeaderFooter">Headers and Footers</link></li>
|
||||
<li><link href="#DrawingShapes">Drawing Shapes</link></li>
|
||||
<li><link href="#StylingShapes">Styling Shapes</link></li>
|
||||
<li><link href="#Graphics2d">Shapes and Graphics2d</link></li>
|
||||
<li><link href="#Outlining">Outlining</link></li>
|
||||
<li><link href="#Images">Images</link></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section><title>Features</title>
|
||||
|
@ -940,5 +941,34 @@
|
|||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<anchor id="Images"/>
|
||||
<section>
|
||||
<title>Images</title>
|
||||
<p>
|
||||
Images are part of the drawing support. To add an image just
|
||||
call <code>createPicture()</code> on the drawing patriarch.
|
||||
At the time of writing the following types are supported:
|
||||
</p>
|
||||
<ul>
|
||||
<li>PNG</li>
|
||||
<li>JPG</li>
|
||||
<li>DIB</li>
|
||||
</ul>
|
||||
<p>
|
||||
It is not currently possible to read existing images and it
|
||||
should be noted that any existing drawings may be erased
|
||||
once you add a image to a sheet.
|
||||
</p>
|
||||
<source>
|
||||
// Create the drawing patriarch. This is the top level container for
|
||||
// all shapes. This will clear out any existing shapes for that sheet.
|
||||
HSSFPatriarch patriarch = sheet5.createDrawingPatriarch();
|
||||
|
||||
HSSFClientAnchor anchor;
|
||||
anchor = new HSSFClientAnchor(0,0,0,255,(short)2,2,(short)4,7);
|
||||
anchor.setAnchorType( 2 );
|
||||
patriarch.createPicture(anchor, loadPicture( "src/resources/logos/logoKarmokar4.png", wb ));
|
||||
</source>
|
||||
</section>
|
||||
</body>
|
||||
</document>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
<release version="unreleased" date="???">
|
||||
<action dev="POI-DEVELOPERS" type="fix" context="All">Bugzilla Bug 29976 [PATCH] HSSF hyperlink formula size problem</action>
|
||||
<action dev="POI-DEVELOPERS" type="add" context="All">Image writing support</action>
|
||||
</release>
|
||||
|
||||
<release version="2.5.1-FINAL" date="29 Feburary 2004">
|
||||
|
|
|
@ -19,9 +19,7 @@ package org.apache.poi.hssf.usermodel.examples;
|
|||
|
||||
import org.apache.poi.hssf.usermodel.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Demonstrates how to use the office drawing capabilities of POI.
|
||||
|
@ -39,12 +37,14 @@ public class OfficeDrawing
|
|||
HSSFSheet sheet2 = wb.createSheet("second sheet");
|
||||
HSSFSheet sheet3 = wb.createSheet("third sheet");
|
||||
HSSFSheet sheet4 = wb.createSheet("fourth sheet");
|
||||
HSSFSheet sheet5 = wb.createSheet("fifth sheet");
|
||||
|
||||
// Draw stuff in them
|
||||
drawSheet1( sheet1 );
|
||||
drawSheet2( sheet2 );
|
||||
drawSheet3( sheet3 );
|
||||
drawSheet4( sheet4, wb );
|
||||
drawSheet5( sheet5, wb );
|
||||
|
||||
// Write the file out.
|
||||
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
|
||||
|
@ -143,6 +143,53 @@ public class OfficeDrawing
|
|||
textbox3.setNoFill(true); // make it transparent
|
||||
}
|
||||
|
||||
private static void drawSheet5( HSSFSheet sheet5, HSSFWorkbook wb ) throws IOException
|
||||
{
|
||||
|
||||
// Create the drawing patriarch. This is the top level container for
|
||||
// all shapes. This will clear out any existing shapes for that sheet.
|
||||
HSSFPatriarch patriarch = sheet5.createDrawingPatriarch();
|
||||
|
||||
HSSFClientAnchor anchor;
|
||||
anchor = new HSSFClientAnchor(0,0,0,255,(short)2,2,(short)4,7);
|
||||
anchor.setAnchorType( 2 );
|
||||
patriarch.createPicture(anchor, loadPicture( "src/resources/logos/logoKarmokar4.png", wb ));
|
||||
|
||||
anchor = new HSSFClientAnchor(0,0,0,255,(short)4,2,(short)5,7);
|
||||
anchor.setAnchorType( 2 );
|
||||
patriarch.createPicture(anchor, loadPicture( "src/resources/logos/logoKarmokar4edited.png", wb ));
|
||||
|
||||
anchor = new HSSFClientAnchor(0,0,1023,255,(short)6,2,(short)8,7);
|
||||
anchor.setAnchorType( 2 );
|
||||
HSSFPicture picture = patriarch.createPicture(anchor, loadPicture( "src/resources/logos/logoKarmokar4s.png", wb ));
|
||||
picture.setLineStyle( picture.LINESTYLE_DASHDOTGEL );
|
||||
|
||||
}
|
||||
|
||||
private static int loadPicture( String path, HSSFWorkbook wb ) throws IOException
|
||||
{
|
||||
int pictureIndex;
|
||||
FileInputStream fis = null;
|
||||
ByteArrayOutputStream bos = null;
|
||||
try
|
||||
{
|
||||
fis = new FileInputStream( path);
|
||||
bos = new ByteArrayOutputStream( );
|
||||
int c;
|
||||
while ( (c = fis.read()) != -1)
|
||||
bos.write( c );
|
||||
pictureIndex = wb.addPicture( bos.toByteArray(), HSSFWorkbook.PICTURE_TYPE_PNG );
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (fis != null)
|
||||
fis.close();
|
||||
if (bos != null)
|
||||
bos.close();
|
||||
}
|
||||
return pictureIndex;
|
||||
}
|
||||
|
||||
private static void drawOval( HSSFPatriarch patriarch )
|
||||
{
|
||||
// Create an oval and style to taste.
|
||||
|
|
|
@ -66,7 +66,17 @@ public class DefaultEscherRecordFactory
|
|||
}
|
||||
else if ( header.getRecordId() >= EscherBlipRecord.RECORD_ID_START && header.getRecordId() <= EscherBlipRecord.RECORD_ID_END )
|
||||
{
|
||||
EscherBlipRecord r = new EscherBlipRecord();
|
||||
EscherBlipRecord r;
|
||||
if (header.getRecordId() == EscherBitmapBlip.RECORD_ID_DIB ||
|
||||
header.getRecordId() == EscherBitmapBlip.RECORD_ID_JPEG ||
|
||||
header.getRecordId() == EscherBitmapBlip.RECORD_ID_PNG)
|
||||
{
|
||||
r = new EscherBitmapBlip();
|
||||
}
|
||||
else
|
||||
{
|
||||
r = new EscherBlipRecord();
|
||||
}
|
||||
r.setRecordId( header.getRecordId() );
|
||||
r.setOptions( header.getOptions() );
|
||||
return r;
|
||||
|
|
|
@ -17,15 +17,15 @@
|
|||
|
||||
package org.apache.poi.ddf;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* The BSE record is related closely to the <code>EscherBlipRecord</code> and stores
|
||||
* extra information about the blip.
|
||||
* extra information about the blip. A blip record is actually stored inside
|
||||
* the BSE record even though the BSE record isn't actually a container record.
|
||||
*
|
||||
* @author Glen Stampoultzis
|
||||
* @see EscherBlipRecord
|
||||
|
@ -56,6 +56,7 @@ public class EscherBSERecord
|
|||
private byte field_9_name;
|
||||
private byte field_10_unused2;
|
||||
private byte field_11_unused3;
|
||||
private EscherBlipRecord field_12_blipRecord;
|
||||
|
||||
private byte[] remainingData;
|
||||
|
||||
|
@ -85,9 +86,28 @@ public class EscherBSERecord
|
|||
field_10_unused2 = data[pos + 34];
|
||||
field_11_unused3 = data[pos + 35];
|
||||
bytesRemaining -= 36;
|
||||
int bytesRead = 0;
|
||||
if (bytesRemaining > 0)
|
||||
{
|
||||
field_12_blipRecord = (EscherBlipRecord) recordFactory.createRecord( data, pos + 36 );
|
||||
bytesRead = field_12_blipRecord.fillFields( data, pos + 36, recordFactory );
|
||||
}
|
||||
pos += 36 + bytesRead;
|
||||
bytesRemaining -= bytesRead;
|
||||
// if (field_1_blipTypeWin32 == BT_PNG)
|
||||
// {
|
||||
// byte[] uid = new byte[16];
|
||||
// System.arraycopy( data, pos + 36, uid, 0, 16 );
|
||||
// byte[] puid = new byte[16];
|
||||
// System.arraycopy( data, pos + 52, puid, 0, 16 );
|
||||
// byte tag = data[pos+68];
|
||||
// System.out.println( HexDump.dump( data, 0, 0 ) );
|
||||
// byte[] pngBytes = EscherBlipRecord.decompress( data, pos+69, bytesRemaining);
|
||||
// }
|
||||
|
||||
remainingData = new byte[bytesRemaining];
|
||||
System.arraycopy( data, pos + 36, remainingData, 0, bytesRemaining );
|
||||
return bytesRemaining + 8 + 36;
|
||||
System.arraycopy( data, pos, remainingData, 0, bytesRemaining );
|
||||
return bytesRemaining + 8 + 36 + (field_12_blipRecord == null ? 0 : field_12_blipRecord.getRecordSize()) ;
|
||||
|
||||
}
|
||||
|
||||
|
@ -104,9 +124,14 @@ public class EscherBSERecord
|
|||
{
|
||||
listener.beforeRecordSerialize( offset, getRecordId(), this );
|
||||
|
||||
if (remainingData == null)
|
||||
remainingData = new byte[0];
|
||||
|
||||
LittleEndian.putShort( data, offset, getOptions() );
|
||||
LittleEndian.putShort( data, offset + 2, getRecordId() );
|
||||
int remainingBytes = remainingData.length + 36;
|
||||
if (remainingData == null) remainingData = new byte[0];
|
||||
int blipSize = field_12_blipRecord == null ? 0 : field_12_blipRecord.getRecordSize();
|
||||
int remainingBytes = remainingData.length + 36 + blipSize;
|
||||
LittleEndian.putInt( data, offset + 4, remainingBytes );
|
||||
|
||||
data[offset + 8] = field_1_blipTypeWin32;
|
||||
|
@ -121,8 +146,15 @@ public class EscherBSERecord
|
|||
data[offset + 41] = field_9_name;
|
||||
data[offset + 42] = field_10_unused2;
|
||||
data[offset + 43] = field_11_unused3;
|
||||
System.arraycopy( remainingData, 0, data, offset + 44, remainingData.length );
|
||||
int pos = offset + 8 + 36 + remainingData.length;
|
||||
int bytesWritten = 0;
|
||||
if (field_12_blipRecord != null)
|
||||
{
|
||||
bytesWritten = field_12_blipRecord.serialize( offset + 44, data, new NullEscherSerializationListener() );
|
||||
}
|
||||
if (remainingData == null)
|
||||
remainingData = new byte[0];
|
||||
System.arraycopy( remainingData, 0, data, offset + 44 + bytesWritten, remainingData.length );
|
||||
int pos = offset + 8 + 36 + remainingData.length + bytesWritten;
|
||||
|
||||
listener.afterRecordSerialize(pos, getRecordId(), pos - offset, this);
|
||||
return pos - offset;
|
||||
|
@ -135,7 +167,7 @@ public class EscherBSERecord
|
|||
*/
|
||||
public int getRecordSize()
|
||||
{
|
||||
return 8 + 1 + 1 + 16 + 2 + 4 + 4 + 4 + 1 + 1 + 1 + 1 + remainingData.length;
|
||||
return 8 + 1 + 1 + 16 + 2 + 4 + 4 + 4 + 1 + 1 + 1 + 1 + field_12_blipRecord.getRecordSize() + (remainingData == null ? 0 : remainingData.length);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -312,6 +344,16 @@ public class EscherBSERecord
|
|||
this.field_11_unused3 = unused3;
|
||||
}
|
||||
|
||||
public EscherBlipRecord getBlipRecord()
|
||||
{
|
||||
return field_12_blipRecord;
|
||||
}
|
||||
|
||||
public void setBlipRecord( EscherBlipRecord field_12_blipRecord )
|
||||
{
|
||||
this.field_12_blipRecord = field_12_blipRecord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Any remaining data in this record.
|
||||
*/
|
||||
|
@ -360,9 +402,8 @@ public class EscherBSERecord
|
|||
" Name: " + field_9_name + nl +
|
||||
" Unused2: " + field_10_unused2 + nl +
|
||||
" Unused3: " + field_11_unused3 + nl +
|
||||
" blipRecord: " + field_12_blipRecord + nl +
|
||||
" Extra Data:" + nl + extraData;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,24 +17,14 @@
|
|||
|
||||
package org.apache.poi.ddf;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordFormatException;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.HexDump;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
|
||||
/**
|
||||
* The blip record is used to hold details about large binary objects that occur in escher such
|
||||
* as JPEG, GIF, PICT and WMF files. The contents of the stream is usually compressed. Inflate
|
||||
* can be used to decompress the data.
|
||||
*
|
||||
* @author Glen Stampoultzis
|
||||
* @see java.util.zip.Inflater
|
||||
* @version $Id$
|
||||
*/
|
||||
public class EscherBlipRecord
|
||||
extends EscherRecord
|
||||
|
@ -42,21 +32,14 @@ public class EscherBlipRecord
|
|||
public static final short RECORD_ID_START = (short) 0xF018;
|
||||
public static final short RECORD_ID_END = (short) 0xF117;
|
||||
public static final String RECORD_DESCRIPTION = "msofbtBlip";
|
||||
|
||||
private static final int HEADER_SIZE = 8;
|
||||
|
||||
private byte[] field_1_secondaryUID;
|
||||
private int field_2_cacheOfSize;
|
||||
private int field_3_boundaryTop;
|
||||
private int field_4_boundaryLeft;
|
||||
private int field_5_boundaryWidth;
|
||||
private int field_6_boundaryHeight;
|
||||
private int field_7_width;
|
||||
private int field_8_height;
|
||||
private int field_9_cacheOfSavedSize;
|
||||
private byte field_10_compressionFlag;
|
||||
private byte field_11_filter;
|
||||
private byte[] field_12_data;
|
||||
protected byte[] field_pictureData;
|
||||
|
||||
public EscherBlipRecord()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method deserializes the record from a byte array.
|
||||
|
@ -66,44 +49,27 @@ public class EscherBlipRecord
|
|||
* @param recordFactory May be null since this is not a container record.
|
||||
* @return The number of bytes read from the byte array.
|
||||
*/
|
||||
public int fillFields( byte[] data, int offset,
|
||||
EscherRecordFactory recordFactory
|
||||
)
|
||||
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory )
|
||||
{
|
||||
int bytesAfterHeader = readHeader( data, offset );
|
||||
int pos = offset + HEADER_SIZE;
|
||||
|
||||
int size = 0;
|
||||
field_1_secondaryUID = new byte[16];
|
||||
System.arraycopy( data, pos + size, field_1_secondaryUID, 0, 16 ); size += 16;
|
||||
field_2_cacheOfSize = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_3_boundaryTop = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_4_boundaryLeft = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_5_boundaryWidth = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_6_boundaryHeight = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_7_width = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_8_height = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_9_cacheOfSavedSize = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_10_compressionFlag = data[pos + size]; size++;
|
||||
field_11_filter = data[pos + size]; size++;
|
||||
field_pictureData = new byte[bytesAfterHeader];
|
||||
System.arraycopy(data, pos, field_pictureData, 0, bytesAfterHeader);
|
||||
|
||||
int bytesRemaining = bytesAfterHeader - size;
|
||||
field_12_data = new byte[bytesRemaining];
|
||||
System.arraycopy(data, pos + size, field_12_data, 0, bytesRemaining);
|
||||
|
||||
return bytesRemaining + HEADER_SIZE + bytesAfterHeader;
|
||||
return bytesAfterHeader + 8;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method serializes this escher record into a byte array.
|
||||
* Serializes the record to an existing byte array.
|
||||
*
|
||||
* @param offset The offset into <code>data</code> to start writing the record data to.
|
||||
* @param data The byte array to serialize to.
|
||||
* @param listener A listener to retrieve start and end callbacks. Use a <code>NullEscherSerailizationListener</code> to ignore these events.
|
||||
* @return The number of bytes written.
|
||||
*
|
||||
* @see NullEscherSerializationListener
|
||||
* @param offset the offset within the byte array
|
||||
* @param data the data array to serialize to
|
||||
* @param listener a listener for begin and end serialization events. This
|
||||
* is useful because the serialization is
|
||||
* hierarchical/recursive and sometimes you need to be able
|
||||
* break into that.
|
||||
* @return the number of bytes written.
|
||||
*/
|
||||
public int serialize( int offset, byte[] data, EscherSerializationListener listener )
|
||||
{
|
||||
|
@ -111,25 +77,11 @@ public class EscherBlipRecord
|
|||
|
||||
LittleEndian.putShort( data, offset, getOptions() );
|
||||
LittleEndian.putShort( data, offset + 2, getRecordId() );
|
||||
int remainingBytes = field_12_data.length + 36;
|
||||
LittleEndian.putInt( data, offset + 4, remainingBytes );
|
||||
|
||||
int pos = offset + HEADER_SIZE;
|
||||
System.arraycopy(field_1_secondaryUID, 0, data, pos, 16 ); pos += 16;
|
||||
LittleEndian.putInt( data, pos, field_2_cacheOfSize); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_3_boundaryTop); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_4_boundaryLeft); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_5_boundaryWidth); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_6_boundaryHeight); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_7_width); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_8_height); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_9_cacheOfSavedSize); pos += 4;
|
||||
data[pos++] = field_10_compressionFlag;
|
||||
data[pos++] = field_11_filter;
|
||||
System.arraycopy(field_12_data, 0, data, pos, field_12_data.length); pos += field_12_data.length;
|
||||
System.arraycopy( field_pictureData, 0, data, offset + 4, field_pictureData.length );
|
||||
|
||||
listener.afterRecordSerialize(pos, getRecordId(), pos - offset, this);
|
||||
return pos - offset;
|
||||
listener.afterRecordSerialize(offset + 4 + field_pictureData.length, getRecordId(), field_pictureData.length + 4, this);
|
||||
return field_pictureData.length + 4;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,7 +91,7 @@ public class EscherBlipRecord
|
|||
*/
|
||||
public int getRecordSize()
|
||||
{
|
||||
return 58 + field_12_data.length;
|
||||
return field_pictureData.length + 4;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,203 +102,6 @@ public class EscherBlipRecord
|
|||
return "Blip";
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the secondary UID
|
||||
*/
|
||||
public byte[] getSecondaryUID()
|
||||
{
|
||||
return field_1_secondaryUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the secondary UID
|
||||
*/
|
||||
public void setSecondaryUID( byte[] field_1_secondaryUID )
|
||||
{
|
||||
this.field_1_secondaryUID = field_1_secondaryUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the cache of the metafile size
|
||||
*/
|
||||
public int getCacheOfSize()
|
||||
{
|
||||
return field_2_cacheOfSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cache of the metafile size
|
||||
*/
|
||||
public void setCacheOfSize( int field_2_cacheOfSize )
|
||||
{
|
||||
this.field_2_cacheOfSize = field_2_cacheOfSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the top boundary of the metafile drawing commands
|
||||
*/
|
||||
public int getBoundaryTop()
|
||||
{
|
||||
return field_3_boundaryTop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the top boundary of the metafile drawing commands
|
||||
*/
|
||||
public void setBoundaryTop( int field_3_boundaryTop )
|
||||
{
|
||||
this.field_3_boundaryTop = field_3_boundaryTop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the left boundary of the metafile drawing commands
|
||||
*/
|
||||
public int getBoundaryLeft()
|
||||
{
|
||||
return field_4_boundaryLeft;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the left boundary of the metafile drawing commands
|
||||
*/
|
||||
public void setBoundaryLeft( int field_4_boundaryLeft )
|
||||
{
|
||||
this.field_4_boundaryLeft = field_4_boundaryLeft;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the boundary width of the metafile drawing commands
|
||||
*/
|
||||
public int getBoundaryWidth()
|
||||
{
|
||||
return field_5_boundaryWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the boundary width of the metafile drawing commands
|
||||
*/
|
||||
public void setBoundaryWidth( int field_5_boundaryWidth )
|
||||
{
|
||||
this.field_5_boundaryWidth = field_5_boundaryWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the boundary height of the metafile drawing commands
|
||||
*/
|
||||
public int getBoundaryHeight()
|
||||
{
|
||||
return field_6_boundaryHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the boundary height of the metafile drawing commands
|
||||
*/
|
||||
public void setBoundaryHeight( int field_6_boundaryHeight )
|
||||
{
|
||||
this.field_6_boundaryHeight = field_6_boundaryHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the width of the metafile in EMU's (English Metric Units).
|
||||
*/
|
||||
public int getWidth()
|
||||
{
|
||||
return field_7_width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width of the metafile in EMU's (English Metric Units).
|
||||
*/
|
||||
public void setWidth( int width )
|
||||
{
|
||||
this.field_7_width = width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the height of the metafile in EMU's (English Metric Units).
|
||||
*/
|
||||
public int getHeight()
|
||||
{
|
||||
return field_8_height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the height of the metafile in EMU's (English Metric Units).
|
||||
*/
|
||||
public void setHeight( int height )
|
||||
{
|
||||
this.field_8_height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the cache of the saved size
|
||||
*/
|
||||
public int getCacheOfSavedSize()
|
||||
{
|
||||
return field_9_cacheOfSavedSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cache of the saved size
|
||||
*/
|
||||
public void setCacheOfSavedSize( int field_9_cacheOfSavedSize )
|
||||
{
|
||||
this.field_9_cacheOfSavedSize = field_9_cacheOfSavedSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the contents of the blip compressed?
|
||||
*/
|
||||
public byte getCompressionFlag()
|
||||
{
|
||||
return field_10_compressionFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the contents of the blip is compressed
|
||||
*/
|
||||
public void setCompressionFlag( byte field_10_compressionFlag )
|
||||
{
|
||||
this.field_10_compressionFlag = field_10_compressionFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter should always be 0
|
||||
*/
|
||||
public byte getFilter()
|
||||
{
|
||||
return field_11_filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter should always be 0
|
||||
*/
|
||||
public void setFilter( byte field_11_filter )
|
||||
{
|
||||
this.field_11_filter = field_11_filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* The BLIP data
|
||||
*/
|
||||
public byte[] getData()
|
||||
{
|
||||
return field_12_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The BLIP data
|
||||
*/
|
||||
public void setData( byte[] field_12_data )
|
||||
{
|
||||
this.field_12_data = field_12_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The string representation of this record.
|
||||
*
|
||||
* @return A string
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
String nl = System.getProperty( "line.separator" );
|
||||
|
@ -355,7 +110,7 @@ public class EscherBlipRecord
|
|||
ByteArrayOutputStream b = new ByteArrayOutputStream();
|
||||
try
|
||||
{
|
||||
HexDump.dump( this.field_12_data, 0, b, 0 );
|
||||
HexDump.dump( this.field_pictureData, 0, b, 0 );
|
||||
extraData = b.toString();
|
||||
}
|
||||
catch ( Exception e )
|
||||
|
@ -365,70 +120,7 @@ public class EscherBlipRecord
|
|||
return getClass().getName() + ":" + nl +
|
||||
" RecordId: 0x" + HexDump.toHex( getRecordId() ) + nl +
|
||||
" Options: 0x" + HexDump.toHex( getOptions() ) + nl +
|
||||
" Secondary UID: " + HexDump.toHex( field_1_secondaryUID ) + nl +
|
||||
" CacheOfSize: " + field_2_cacheOfSize + nl +
|
||||
" BoundaryTop: " + field_3_boundaryTop + nl +
|
||||
" BoundaryLeft: " + field_4_boundaryLeft + nl +
|
||||
" BoundaryWidth: " + field_5_boundaryWidth + nl +
|
||||
" BoundaryHeight: " + field_6_boundaryHeight + nl +
|
||||
" X: " + field_7_width + nl +
|
||||
" Y: " + field_8_height + nl +
|
||||
" CacheOfSavedSize: " + field_9_cacheOfSavedSize + nl +
|
||||
" CompressionFlag: " + field_10_compressionFlag + nl +
|
||||
" Filter: " + field_11_filter + nl +
|
||||
" Data:" + nl + extraData;
|
||||
" Extra Data:" + nl + extraData;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress the contents of the provided array
|
||||
*
|
||||
* @param data An uncompressed byte array
|
||||
* @see DeflaterOutputStream#write(int b)
|
||||
*/
|
||||
public static byte[] compress( byte[] data )
|
||||
{
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream( out );
|
||||
try
|
||||
{
|
||||
for ( int i = 0; i < data.length; i++ )
|
||||
deflaterOutputStream.write( data[i] );
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
throw new RecordFormatException( e.toString() );
|
||||
}
|
||||
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompresses a byte array.
|
||||
*
|
||||
* @param data The compressed byte array
|
||||
* @param pos The starting position into the byte array
|
||||
* @param length The number of compressed bytes to decompress
|
||||
* @return An uncompressed byte array
|
||||
* @see InflaterInputStream#read
|
||||
*/
|
||||
public static byte[] decompress( byte[] data, int pos, int length )
|
||||
{
|
||||
byte[] compressedData = new byte[length];
|
||||
System.arraycopy( data, pos + 50, compressedData, 0, length );
|
||||
InputStream compressedInputStream = new ByteArrayInputStream( compressedData );
|
||||
InflaterInputStream inflaterInputStream = new InflaterInputStream( compressedInputStream );
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
int c;
|
||||
try
|
||||
{
|
||||
while ( ( c = inflaterInputStream.read() ) != -1 )
|
||||
out.write( c );
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
throw new RecordFormatException( e.toString() );
|
||||
}
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,435 @@
|
|||
|
||||
/* ====================================================================
|
||||
Copyright 2002-2004 Apache Software Foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.ddf;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordFormatException;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
|
||||
/**
|
||||
* The blip record is used to hold details about large binary objects that occur in escher such
|
||||
* as JPEG, GIF, PICT and WMF files. The contents of the stream is usually compressed. Inflate
|
||||
* can be used to decompress the data.
|
||||
*
|
||||
* @author Glen Stampoultzis
|
||||
* @see java.util.zip.Inflater
|
||||
*/
|
||||
public class EscherBlipWMFRecord
|
||||
extends EscherBlipRecord
|
||||
{
|
||||
// public static final short RECORD_ID_START = (short) 0xF018;
|
||||
// public static final short RECORD_ID_END = (short) 0xF117;
|
||||
public static final String RECORD_DESCRIPTION = "msofbtBlip";
|
||||
private static final int HEADER_SIZE = 8;
|
||||
|
||||
private byte[] field_1_secondaryUID;
|
||||
private int field_2_cacheOfSize;
|
||||
private int field_3_boundaryTop;
|
||||
private int field_4_boundaryLeft;
|
||||
private int field_5_boundaryWidth;
|
||||
private int field_6_boundaryHeight;
|
||||
private int field_7_width;
|
||||
private int field_8_height;
|
||||
private int field_9_cacheOfSavedSize;
|
||||
private byte field_10_compressionFlag;
|
||||
private byte field_11_filter;
|
||||
private byte[] field_12_data;
|
||||
|
||||
|
||||
/**
|
||||
* This method deserializes the record from a byte array.
|
||||
*
|
||||
* @param data The byte array containing the escher record information
|
||||
* @param offset The starting offset into <code>data</code>.
|
||||
* @param recordFactory May be null since this is not a container record.
|
||||
* @return The number of bytes read from the byte array.
|
||||
*/
|
||||
public int fillFields( byte[] data, int offset,
|
||||
EscherRecordFactory recordFactory
|
||||
)
|
||||
{
|
||||
int bytesAfterHeader = readHeader( data, offset );
|
||||
int pos = offset + HEADER_SIZE;
|
||||
|
||||
int size = 0;
|
||||
field_1_secondaryUID = new byte[16];
|
||||
System.arraycopy( data, pos + size, field_1_secondaryUID, 0, 16 ); size += 16;
|
||||
field_2_cacheOfSize = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_3_boundaryTop = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_4_boundaryLeft = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_5_boundaryWidth = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_6_boundaryHeight = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_7_width = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_8_height = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_9_cacheOfSavedSize = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_10_compressionFlag = data[pos + size]; size++;
|
||||
field_11_filter = data[pos + size]; size++;
|
||||
|
||||
int bytesRemaining = bytesAfterHeader - size;
|
||||
field_12_data = new byte[bytesRemaining];
|
||||
System.arraycopy(data, pos + size, field_12_data, 0, bytesRemaining);
|
||||
size += bytesRemaining;
|
||||
|
||||
return HEADER_SIZE + size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method serializes this escher record into a byte array.
|
||||
*
|
||||
* @param offset The offset into <code>data</code> to start writing the record data to.
|
||||
* @param data The byte array to serialize to.
|
||||
* @param listener A listener to retrieve start and end callbacks. Use a <code>NullEscherSerailizationListener</code> to ignore these events.
|
||||
* @return The number of bytes written.
|
||||
*
|
||||
* @see NullEscherSerializationListener
|
||||
*/
|
||||
public int serialize( int offset, byte[] data, EscherSerializationListener listener )
|
||||
{
|
||||
listener.beforeRecordSerialize(offset, getRecordId(), this);
|
||||
|
||||
LittleEndian.putShort( data, offset, getOptions() );
|
||||
LittleEndian.putShort( data, offset + 2, getRecordId() );
|
||||
int remainingBytes = field_12_data.length + 36;
|
||||
LittleEndian.putInt( data, offset + 4, remainingBytes );
|
||||
|
||||
int pos = offset + HEADER_SIZE;
|
||||
System.arraycopy(field_1_secondaryUID, 0, data, pos, 16 ); pos += 16;
|
||||
LittleEndian.putInt( data, pos, field_2_cacheOfSize); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_3_boundaryTop); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_4_boundaryLeft); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_5_boundaryWidth); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_6_boundaryHeight); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_7_width); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_8_height); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_9_cacheOfSavedSize); pos += 4;
|
||||
data[pos++] = field_10_compressionFlag;
|
||||
data[pos++] = field_11_filter;
|
||||
System.arraycopy(field_12_data, 0, data, pos, field_12_data.length); pos += field_12_data.length;
|
||||
|
||||
listener.afterRecordSerialize(pos, getRecordId(), pos - offset, this);
|
||||
return pos - offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes that are required to serialize this record.
|
||||
*
|
||||
* @return Number of bytes
|
||||
*/
|
||||
public int getRecordSize()
|
||||
{
|
||||
return 58 + field_12_data.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* The short name for this record
|
||||
*/
|
||||
public String getRecordName()
|
||||
{
|
||||
return "Blip";
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the secondary UID
|
||||
*/
|
||||
public byte[] getSecondaryUID()
|
||||
{
|
||||
return field_1_secondaryUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the secondary UID
|
||||
*/
|
||||
public void setSecondaryUID( byte[] field_1_secondaryUID )
|
||||
{
|
||||
this.field_1_secondaryUID = field_1_secondaryUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the cache of the metafile size
|
||||
*/
|
||||
public int getCacheOfSize()
|
||||
{
|
||||
return field_2_cacheOfSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cache of the metafile size
|
||||
*/
|
||||
public void setCacheOfSize( int field_2_cacheOfSize )
|
||||
{
|
||||
this.field_2_cacheOfSize = field_2_cacheOfSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the top boundary of the metafile drawing commands
|
||||
*/
|
||||
public int getBoundaryTop()
|
||||
{
|
||||
return field_3_boundaryTop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the top boundary of the metafile drawing commands
|
||||
*/
|
||||
public void setBoundaryTop( int field_3_boundaryTop )
|
||||
{
|
||||
this.field_3_boundaryTop = field_3_boundaryTop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the left boundary of the metafile drawing commands
|
||||
*/
|
||||
public int getBoundaryLeft()
|
||||
{
|
||||
return field_4_boundaryLeft;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the left boundary of the metafile drawing commands
|
||||
*/
|
||||
public void setBoundaryLeft( int field_4_boundaryLeft )
|
||||
{
|
||||
this.field_4_boundaryLeft = field_4_boundaryLeft;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the boundary width of the metafile drawing commands
|
||||
*/
|
||||
public int getBoundaryWidth()
|
||||
{
|
||||
return field_5_boundaryWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the boundary width of the metafile drawing commands
|
||||
*/
|
||||
public void setBoundaryWidth( int field_5_boundaryWidth )
|
||||
{
|
||||
this.field_5_boundaryWidth = field_5_boundaryWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the boundary height of the metafile drawing commands
|
||||
*/
|
||||
public int getBoundaryHeight()
|
||||
{
|
||||
return field_6_boundaryHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the boundary height of the metafile drawing commands
|
||||
*/
|
||||
public void setBoundaryHeight( int field_6_boundaryHeight )
|
||||
{
|
||||
this.field_6_boundaryHeight = field_6_boundaryHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the width of the metafile in EMU's (English Metric Units).
|
||||
*/
|
||||
public int getWidth()
|
||||
{
|
||||
return field_7_width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the width of the metafile in EMU's (English Metric Units).
|
||||
*/
|
||||
public void setWidth( int width )
|
||||
{
|
||||
this.field_7_width = width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the height of the metafile in EMU's (English Metric Units).
|
||||
*/
|
||||
public int getHeight()
|
||||
{
|
||||
return field_8_height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the height of the metafile in EMU's (English Metric Units).
|
||||
*/
|
||||
public void setHeight( int height )
|
||||
{
|
||||
this.field_8_height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the cache of the saved size
|
||||
*/
|
||||
public int getCacheOfSavedSize()
|
||||
{
|
||||
return field_9_cacheOfSavedSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cache of the saved size
|
||||
*/
|
||||
public void setCacheOfSavedSize( int field_9_cacheOfSavedSize )
|
||||
{
|
||||
this.field_9_cacheOfSavedSize = field_9_cacheOfSavedSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the contents of the blip compressed?
|
||||
*/
|
||||
public byte getCompressionFlag()
|
||||
{
|
||||
return field_10_compressionFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the contents of the blip is compressed
|
||||
*/
|
||||
public void setCompressionFlag( byte field_10_compressionFlag )
|
||||
{
|
||||
this.field_10_compressionFlag = field_10_compressionFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter should always be 0
|
||||
*/
|
||||
public byte getFilter()
|
||||
{
|
||||
return field_11_filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter should always be 0
|
||||
*/
|
||||
public void setFilter( byte field_11_filter )
|
||||
{
|
||||
this.field_11_filter = field_11_filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* The BLIP data
|
||||
*/
|
||||
public byte[] getData()
|
||||
{
|
||||
return field_12_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The BLIP data
|
||||
*/
|
||||
public void setData( byte[] field_12_data )
|
||||
{
|
||||
this.field_12_data = field_12_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The string representation of this record.
|
||||
*
|
||||
* @return A string
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
String nl = System.getProperty( "line.separator" );
|
||||
|
||||
String extraData;
|
||||
ByteArrayOutputStream b = new ByteArrayOutputStream();
|
||||
try
|
||||
{
|
||||
HexDump.dump( this.field_12_data, 0, b, 0 );
|
||||
extraData = b.toString();
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
extraData = e.toString();
|
||||
}
|
||||
return getClass().getName() + ":" + nl +
|
||||
" RecordId: 0x" + HexDump.toHex( getRecordId() ) + nl +
|
||||
" Options: 0x" + HexDump.toHex( getOptions() ) + nl +
|
||||
" Secondary UID: " + HexDump.toHex( field_1_secondaryUID ) + nl +
|
||||
" CacheOfSize: " + field_2_cacheOfSize + nl +
|
||||
" BoundaryTop: " + field_3_boundaryTop + nl +
|
||||
" BoundaryLeft: " + field_4_boundaryLeft + nl +
|
||||
" BoundaryWidth: " + field_5_boundaryWidth + nl +
|
||||
" BoundaryHeight: " + field_6_boundaryHeight + nl +
|
||||
" X: " + field_7_width + nl +
|
||||
" Y: " + field_8_height + nl +
|
||||
" CacheOfSavedSize: " + field_9_cacheOfSavedSize + nl +
|
||||
" CompressionFlag: " + field_10_compressionFlag + nl +
|
||||
" Filter: " + field_11_filter + nl +
|
||||
" Data:" + nl + extraData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress the contents of the provided array
|
||||
*
|
||||
* @param data An uncompressed byte array
|
||||
* @see DeflaterOutputStream#write(int b)
|
||||
*/
|
||||
public static byte[] compress( byte[] data )
|
||||
{
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream( out );
|
||||
try
|
||||
{
|
||||
for ( int i = 0; i < data.length; i++ )
|
||||
deflaterOutputStream.write( data[i] );
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
throw new RecordFormatException( e.toString() );
|
||||
}
|
||||
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompresses a byte array.
|
||||
*
|
||||
* @param data The compressed byte array
|
||||
* @param pos The starting position into the byte array
|
||||
* @param length The number of compressed bytes to decompress
|
||||
* @return An uncompressed byte array
|
||||
* @see InflaterInputStream#read
|
||||
*/
|
||||
public static byte[] decompress( byte[] data, int pos, int length )
|
||||
{
|
||||
byte[] compressedData = new byte[length];
|
||||
System.arraycopy( data, pos + 50, compressedData, 0, length );
|
||||
InputStream compressedInputStream = new ByteArrayInputStream( compressedData );
|
||||
InflaterInputStream inflaterInputStream = new InflaterInputStream( compressedInputStream );
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
int c;
|
||||
try
|
||||
{
|
||||
while ( ( c = inflaterInputStream.read() ) != -1 )
|
||||
out.write( c );
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
throw new RecordFormatException( e.toString() );
|
||||
}
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
}
|
|
@ -32,12 +32,12 @@ public class EscherBoolProperty
|
|||
/**
|
||||
* Create an instance of an escher boolean property.
|
||||
*
|
||||
* @param propertyNumber The property number
|
||||
* @param propertyNumber The property number (or id)
|
||||
* @param value The 32 bit value of this bool property
|
||||
*/
|
||||
public EscherBoolProperty( short propertyNumber, int value )
|
||||
{
|
||||
super( propertyNumber, false, false, value );
|
||||
super(propertyNumber, value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -154,7 +154,7 @@ public class EscherClientAnchorRecord
|
|||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
extraData = "error";
|
||||
extraData = "error\n";
|
||||
}
|
||||
return getClass().getName() + ":" + nl +
|
||||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + nl +
|
||||
|
|
|
@ -119,7 +119,7 @@ public class EscherClientDataRecord
|
|||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
extraData = "error";
|
||||
extraData = "error\n";
|
||||
}
|
||||
return getClass().getName() + ":" + nl +
|
||||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + nl +
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
|
||||
package org.apache.poi.ddf;
|
||||
|
||||
import org.apache.poi.hssf.record.RecordFormatException;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.hssf.record.RecordFormatException;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
|
@ -83,8 +82,8 @@ public class EscherDggRecord
|
|||
int field_2_numIdClusters = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_3_numShapesSaved = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_4_drawingsSaved = LittleEndian.getInt( data, pos + size );size+=4;
|
||||
field_5_fileIdClusters = new FileIdCluster[field_2_numIdClusters-1];
|
||||
for (int i = 0; i < field_2_numIdClusters-1; i++)
|
||||
field_5_fileIdClusters = new FileIdCluster[(bytesRemaining-size) / 8]; // Can't rely on field_2_numIdClusters
|
||||
for (int i = 0; i < field_5_fileIdClusters.length; i++)
|
||||
{
|
||||
field_5_fileIdClusters[i] = new FileIdCluster(LittleEndian.getInt( data, pos + size ), LittleEndian.getInt( data, pos + size + 4 ));
|
||||
size += 8;
|
||||
|
@ -114,6 +113,7 @@ public class EscherDggRecord
|
|||
LittleEndian.putShort( data, pos, getRecordId() ); pos += 2;
|
||||
int remainingBytes = getRecordSize() - 8;
|
||||
LittleEndian.putInt( data, pos, remainingBytes ); pos += 4;
|
||||
|
||||
LittleEndian.putInt( data, pos, field_1_shapeIdMax ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, getNumIdClusters() ); pos += 4;
|
||||
LittleEndian.putInt( data, pos, field_3_numShapesSaved ); pos += 4;
|
||||
|
@ -200,6 +200,9 @@ public class EscherDggRecord
|
|||
this.field_1_shapeIdMax = field_1_shapeIdMax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of id clusters + 1
|
||||
*/
|
||||
public int getNumIdClusters()
|
||||
{
|
||||
return field_5_fileIdClusters.length + 1;
|
||||
|
|
|
@ -26,7 +26,7 @@ package org.apache.poi.ddf;
|
|||
*/
|
||||
abstract public class EscherProperty
|
||||
{
|
||||
private short id;
|
||||
protected short id;
|
||||
|
||||
/**
|
||||
* The id is distinct from the actual property number. The id includes the property number the blip id
|
||||
|
|
|
@ -18,11 +18,10 @@
|
|||
package org.apache.poi.ddf;
|
||||
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.hssf.record.RecordFormatException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Generates a property given a reference into the byte array storing that property.
|
||||
|
@ -43,7 +42,7 @@ public class EscherPropertyFactory
|
|||
List results = new ArrayList();
|
||||
|
||||
int pos = offset;
|
||||
int complexBytes = 0;
|
||||
|
||||
// while ( bytesRemaining >= 6 )
|
||||
for (int i = 0; i < numProperties; i++)
|
||||
{
|
||||
|
@ -54,21 +53,18 @@ public class EscherPropertyFactory
|
|||
short propNumber = (short) ( propId & (short) 0x3FFF );
|
||||
boolean isComplex = ( propId & (short) 0x8000 ) != 0;
|
||||
boolean isBlipId = ( propId & (short) 0x4000 ) != 0;
|
||||
if ( isComplex )
|
||||
complexBytes = propData;
|
||||
else
|
||||
complexBytes = 0;
|
||||
|
||||
byte propertyType = EscherProperties.getPropertyType( (short) propNumber );
|
||||
if ( propertyType == EscherPropertyMetaData.TYPE_BOOLEAN )
|
||||
results.add( new EscherBoolProperty( propNumber, propData ) );
|
||||
results.add( new EscherBoolProperty( propId, propData ) );
|
||||
else if ( propertyType == EscherPropertyMetaData.TYPE_RGB )
|
||||
results.add( new EscherRGBProperty( propNumber, propData ) );
|
||||
results.add( new EscherRGBProperty( propId, propData ) );
|
||||
else if ( propertyType == EscherPropertyMetaData.TYPE_SHAPEPATH )
|
||||
results.add( new EscherShapePathProperty( propNumber, propData ) );
|
||||
results.add( new EscherShapePathProperty( propId, propData ) );
|
||||
else
|
||||
{
|
||||
if ( !isComplex )
|
||||
results.add( new EscherSimpleProperty( propNumber, propData ) );
|
||||
results.add( new EscherSimpleProperty( propId, propData ) );
|
||||
else
|
||||
{
|
||||
if ( propertyType == EscherPropertyMetaData.TYPE_ARRAY)
|
||||
|
|
|
@ -28,7 +28,7 @@ public class EscherRGBProperty
|
|||
|
||||
public EscherRGBProperty( short propertyNumber, int rgbColor )
|
||||
{
|
||||
super( propertyNumber, false, false, rgbColor );
|
||||
super( propertyNumber, rgbColor );
|
||||
}
|
||||
|
||||
public int getRgbColor()
|
||||
|
|
|
@ -111,6 +111,7 @@ public class EscherSimpleProperty extends EscherProperty
|
|||
public String toString()
|
||||
{
|
||||
return "propNum: " + getPropertyNumber()
|
||||
+ ", RAW: 0x" + HexDump.toHex( getId() )
|
||||
+ ", propName: " + EscherProperties.getPropertyName( getPropertyNumber() )
|
||||
+ ", complex: " + isComplex()
|
||||
+ ", blipId: " + isBlipId()
|
||||
|
|
|
@ -112,6 +112,23 @@ public class BiffViewer {
|
|||
in.read(data);
|
||||
loc += recsize;
|
||||
Record record = createRecord(rectype, recsize, data );
|
||||
// if (record.getSid() == DrawingGroupRecord.sid)
|
||||
// {
|
||||
// if (activeRecord.getRecord().getSid() == DrawingGroupRecord.sid)
|
||||
// {
|
||||
// DrawingGroupRecord dg = (DrawingGroupRecord) activeRecord.getRecord();
|
||||
// System.out.println( "Joined" );
|
||||
// dg.join( (AbstractEscherHolderRecord) record );
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// records.add(record);
|
||||
// if (activeRecord != null)
|
||||
// activeRecord.dump();
|
||||
// activeRecord = new RecordDetails(rectype, recsize, startloc, data, record);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
if (record.getSid() != ContinueRecord.sid)
|
||||
{
|
||||
records.add(record);
|
||||
|
@ -178,7 +195,6 @@ public class BiffViewer {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static void dumpUnknownRecord(byte[] data) throws IOException {
|
||||
// record hex dump it!
|
||||
System.out.println(
|
||||
|
@ -630,29 +646,40 @@ public class BiffViewer {
|
|||
*/
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
BiffViewer viewer = new BiffViewer(args);
|
||||
System.setProperty("poi.deserialize.escher", "true");
|
||||
|
||||
if ((args.length > 1) && args[1].equals("on")) {
|
||||
viewer.setDump(true);
|
||||
if (args.length == 0)
|
||||
{
|
||||
System.out.println( "Biff viewer needs a filename" );
|
||||
}
|
||||
if ((args.length > 1) && args[1].equals("bfd")) {
|
||||
POIFSFileSystem fs =
|
||||
new POIFSFileSystem(new FileInputStream(args[0]));
|
||||
InputStream stream =
|
||||
fs.createDocumentInputStream("Workbook");
|
||||
int size = stream.available();
|
||||
byte[] data = new byte[size];
|
||||
else
|
||||
{
|
||||
BiffViewer viewer = new BiffViewer(args);
|
||||
if ((args.length > 1) && args[1].equals("on")) {
|
||||
viewer.setDump(true);
|
||||
}
|
||||
if ((args.length > 1) && args[1].equals("bfd")) {
|
||||
POIFSFileSystem fs =
|
||||
new POIFSFileSystem(new FileInputStream(args[0]));
|
||||
InputStream stream =
|
||||
fs.createDocumentInputStream("Workbook");
|
||||
int size = stream.available();
|
||||
byte[] data = new byte[size];
|
||||
|
||||
stream.read(data);
|
||||
HexDump.dump(data, 0, System.out, 0);
|
||||
} else {
|
||||
viewer.run();
|
||||
stream.read(data);
|
||||
HexDump.dump(data, 0, System.out, 0);
|
||||
} else {
|
||||
viewer.run();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This record supports dumping of completed continue records.
|
||||
*/
|
||||
static class RecordDetails
|
||||
{
|
||||
short rectype, recsize;
|
||||
|
|
|
@ -34,7 +34,7 @@ public abstract class AbstractShape
|
|||
*/
|
||||
public static AbstractShape createShape( HSSFShape hssfShape, int shapeId )
|
||||
{
|
||||
AbstractShape shape = null;
|
||||
AbstractShape shape;
|
||||
if (hssfShape instanceof HSSFTextbox)
|
||||
{
|
||||
shape = new TextboxShape( (HSSFTextbox)hssfShape, shapeId );
|
||||
|
@ -48,6 +48,9 @@ public abstract class AbstractShape
|
|||
HSSFSimpleShape simpleShape = (HSSFSimpleShape) hssfShape;
|
||||
switch ( simpleShape.getShapeType() )
|
||||
{
|
||||
case HSSFSimpleShape.OBJECT_TYPE_PICTURE:
|
||||
shape = new PictureShape( simpleShape, shapeId );
|
||||
break;
|
||||
case HSSFSimpleShape.OBJECT_TYPE_LINE:
|
||||
shape = new LineShape( simpleShape, shapeId );
|
||||
break;
|
||||
|
|
|
@ -37,7 +37,7 @@ public class ConvertAnchor
|
|||
EscherClientAnchorRecord anchor = new EscherClientAnchorRecord();
|
||||
anchor.setRecordId( EscherClientAnchorRecord.RECORD_ID );
|
||||
anchor.setOptions( (short) 0x0000 );
|
||||
anchor.setFlag( (short) 0 );
|
||||
anchor.setFlag( (short) a.getAnchorType() );
|
||||
anchor.setCol1( (short) Math.min(a.getCol1(), a.getCol2()) );
|
||||
anchor.setDx1( (short) Math.min(a.getDx1(), a.getDx2()) );
|
||||
anchor.setRow1( (short) Math.min(a.getRow1(), a.getRow2()) );
|
||||
|
|
|
@ -19,17 +19,17 @@
|
|||
package org.apache.poi.hssf.model;
|
||||
|
||||
import org.apache.poi.hssf.record.*;
|
||||
import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
|
||||
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
|
||||
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
|
||||
import org.apache.poi.hssf.record.aggregates.ValueRecordsAggregate;
|
||||
import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
|
||||
import org.apache.poi.hssf.record.formula.Ptg;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.List; // normally I don't do this, buy we literally mean ALL
|
||||
|
||||
/**
|
||||
* Low level model implementation of a Sheet (one workbook contains many sheets)
|
||||
|
@ -768,6 +768,26 @@ public class Sheet implements Model
|
|||
}
|
||||
}
|
||||
|
||||
//// uncomment to test record sizes ////
|
||||
// System.out.println( record.getClass().getName() );
|
||||
// byte[] data2 = new byte[record.getRecordSize()];
|
||||
// record.serialize(0, data2 ); // rec.length;
|
||||
// if (LittleEndian.getUShort(data2, 2) != record.getRecordSize() - 4
|
||||
// && record instanceof RowRecordsAggregate == false
|
||||
// && record instanceof ValueRecordsAggregate == false
|
||||
// && record instanceof EscherAggregate == false)
|
||||
// {
|
||||
// throw new RuntimeException("Blah!!! Size off by " + ( LittleEndian.getUShort(data2, 2) - record.getRecordSize() - 4) + " records.");
|
||||
// }
|
||||
|
||||
//asd: int len = record.serialize(pos + offset, data );
|
||||
|
||||
///// DEBUG BEGIN /////
|
||||
//asd: if (len != record.getRecordSize())
|
||||
//asd: throw new IllegalStateException("Record size does not match serialized bytes. Serialized size = " + len + " but getRecordSize() returns " + record.getRecordSize() + ". Record object is " + record.getClass());
|
||||
///// DEBUG END /////
|
||||
|
||||
//asd: pos += len; // rec.length;
|
||||
|
||||
}
|
||||
if (log.check( POILogger.DEBUG ))
|
||||
|
@ -2023,9 +2043,9 @@ public class Sheet implements Model
|
|||
{
|
||||
int retval = 0;
|
||||
|
||||
for (int k = 0; k < records.size(); k++)
|
||||
for ( int k = 0; k < records.size(); k++ )
|
||||
{
|
||||
retval += (( Record ) records.get(k)).getRecordSize();
|
||||
retval += ( (Record) records.get( k ) ).getRecordSize();
|
||||
}
|
||||
//Add space for the IndexRecord
|
||||
if (rows != null) {
|
||||
|
@ -2430,7 +2450,7 @@ public class Sheet implements Model
|
|||
return margins;
|
||||
}
|
||||
|
||||
public int aggregateDrawingRecords(DrawingManager drawingManager)
|
||||
public int aggregateDrawingRecords(DrawingManager2 drawingManager)
|
||||
{
|
||||
int loc = findFirstRecordLocBySid(DrawingRecord.sid);
|
||||
boolean noDrawingRecordsFound = loc == -1;
|
||||
|
|
|
@ -29,7 +29,6 @@ import java.util.ArrayList;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
/**
|
||||
* Low level model implementation of a Workbook. Provides creational methods
|
||||
|
@ -99,7 +98,8 @@ public class Workbook implements Model
|
|||
protected int numfonts = 0; // hold the number of font records
|
||||
private short maxformatid = -1; // holds the max format id
|
||||
private boolean uses1904datewindowing = false; // whether 1904 date windowing is being used
|
||||
private DrawingManager drawingManager;
|
||||
private DrawingManager2 drawingManager;
|
||||
private List escherBSERecords = new ArrayList(); // EscherBSERecord
|
||||
|
||||
private static POILogger log = POILogFactory.getLogger(Workbook.class);
|
||||
|
||||
|
@ -748,7 +748,12 @@ public class Workbook implements Model
|
|||
{
|
||||
record = sst.createExtSSTRecord(sstPos + offset);
|
||||
}
|
||||
pos += record.serialize( pos + offset, data ); // rec.length;
|
||||
int len = record.serialize( pos + offset, data );
|
||||
///// DEBUG BEGIN /////
|
||||
// if (len != record.getRecordSize())
|
||||
// throw new IllegalStateException("Record size does not match serialized bytes. Serialized size = " + len + " but getRecordSize() returns " + record.getRecordSize());
|
||||
///// DEBUG END /////
|
||||
pos += len; // rec.length;
|
||||
}
|
||||
}
|
||||
if (log.check( POILogger.DEBUG ))
|
||||
|
@ -2104,13 +2109,12 @@ public class Workbook implements Model
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a drawing group record. If it already exists then it's left
|
||||
* alone.
|
||||
* Creates a drawing group record. If it already exists then it's modified.
|
||||
*/
|
||||
public void createDrawingGroup()
|
||||
{
|
||||
int dggLoc = findFirstRecordLocBySid(EscherContainerRecord.DGG_CONTAINER);
|
||||
if (dggLoc == -1)
|
||||
|
||||
if (drawingManager == null)
|
||||
{
|
||||
EscherContainerRecord dggContainer = new EscherContainerRecord();
|
||||
EscherDggRecord dgg = new EscherDggRecord();
|
||||
|
@ -2125,11 +2129,23 @@ public class Workbook implements Model
|
|||
dgg.setNumShapesSaved(0);
|
||||
dgg.setDrawingsSaved(0);
|
||||
dgg.setFileIdClusters(new EscherDggRecord.FileIdCluster[] {} );
|
||||
drawingManager = new DrawingManager(dgg);
|
||||
drawingManager = new DrawingManager2(dgg);
|
||||
EscherContainerRecord bstoreContainer = null;
|
||||
if (escherBSERecords.size() > 0)
|
||||
{
|
||||
bstoreContainer = new EscherContainerRecord();
|
||||
bstoreContainer.setRecordId( EscherContainerRecord.BSTORE_CONTAINER );
|
||||
bstoreContainer.setOptions( (short) ( (escherBSERecords.size() << 4) | 0xF ) );
|
||||
for ( Iterator iterator = escherBSERecords.iterator(); iterator.hasNext(); )
|
||||
{
|
||||
EscherRecord escherRecord = (EscherRecord) iterator.next();
|
||||
bstoreContainer.addChildRecord( escherRecord );
|
||||
}
|
||||
}
|
||||
opt.setRecordId((short) 0xF00B);
|
||||
opt.setOptions((short) 0x0033);
|
||||
opt.addEscherProperty( new EscherBoolProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 524296) );
|
||||
opt.addEscherProperty( new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, 134217737) );
|
||||
opt.addEscherProperty( new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, 0x08000041) );
|
||||
opt.addEscherProperty( new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, 134217792) );
|
||||
splitMenuColors.setRecordId((short) 0xF11E);
|
||||
splitMenuColors.setOptions((short) 0x0040);
|
||||
|
@ -2139,17 +2155,61 @@ public class Workbook implements Model
|
|||
splitMenuColors.setColor4(0x100000F7);
|
||||
|
||||
dggContainer.addChildRecord(dgg);
|
||||
if (bstoreContainer != null)
|
||||
dggContainer.addChildRecord( bstoreContainer );
|
||||
dggContainer.addChildRecord(opt);
|
||||
dggContainer.addChildRecord(splitMenuColors);
|
||||
|
||||
DrawingGroupRecord drawingGroup = new DrawingGroupRecord();
|
||||
drawingGroup.addEscherRecord(dggContainer);
|
||||
int loc = findFirstRecordLocBySid(CountryRecord.sid);
|
||||
getRecords().add(loc+1, drawingGroup);
|
||||
int dgLoc = findFirstRecordLocBySid(DrawingGroupRecord.sid);
|
||||
if (dgLoc == -1)
|
||||
{
|
||||
DrawingGroupRecord drawingGroup = new DrawingGroupRecord();
|
||||
drawingGroup.addEscherRecord(dggContainer);
|
||||
int loc = findFirstRecordLocBySid(CountryRecord.sid);
|
||||
|
||||
getRecords().add(loc+1, drawingGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawingGroupRecord drawingGroup = new DrawingGroupRecord();
|
||||
drawingGroup.addEscherRecord(dggContainer);
|
||||
getRecords().set(dgLoc, drawingGroup);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public DrawingManager getDrawingManager()
|
||||
public int addBSERecord(EscherBSERecord e)
|
||||
{
|
||||
createDrawingGroup();
|
||||
|
||||
// maybe we don't need that as an instance variable anymore
|
||||
escherBSERecords.add( e );
|
||||
|
||||
int dgLoc = findFirstRecordLocBySid(DrawingGroupRecord.sid);
|
||||
DrawingGroupRecord drawingGroup = (DrawingGroupRecord) getRecords().get( dgLoc );
|
||||
|
||||
EscherContainerRecord dggContainer = (EscherContainerRecord) drawingGroup.getEscherRecord( 0 );
|
||||
EscherContainerRecord bstoreContainer;
|
||||
if (dggContainer.getChild( 1 ).getRecordId() == EscherContainerRecord.BSTORE_CONTAINER )
|
||||
{
|
||||
bstoreContainer = (EscherContainerRecord) dggContainer.getChild( 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
bstoreContainer = new EscherContainerRecord();
|
||||
bstoreContainer.setRecordId( EscherContainerRecord.BSTORE_CONTAINER );
|
||||
dggContainer.getChildRecords().add( 1, bstoreContainer );
|
||||
}
|
||||
bstoreContainer.setOptions( (short) ( (escherBSERecords.size() << 4) | 0xF ) );
|
||||
|
||||
bstoreContainer.addChildRecord( e );
|
||||
|
||||
return escherBSERecords.size();
|
||||
}
|
||||
|
||||
public DrawingManager2 getDrawingManager()
|
||||
{
|
||||
return drawingManager;
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ public abstract class AbstractEscherHolderRecord
|
|||
{
|
||||
if (id != getSid())
|
||||
{
|
||||
throw new RecordFormatException("Not a Bar record");
|
||||
throw new RecordFormatException("Not an escher record");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,15 +102,20 @@ public abstract class AbstractEscherHolderRecord
|
|||
}
|
||||
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;
|
||||
}
|
||||
convertToEscherRecords( offset, size, data );
|
||||
}
|
||||
}
|
||||
|
||||
private void convertToEscherRecords( int offset, int size, byte[] data )
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,6 +125,8 @@ public abstract class AbstractEscherHolderRecord
|
|||
|
||||
final String nl = System.getProperty("line.separator");
|
||||
buffer.append('[' + getRecordName() + ']' + nl);
|
||||
if (escherRecords.size() == 0)
|
||||
buffer.append("No Escher Records Decoded" + nl);
|
||||
for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
|
||||
{
|
||||
EscherRecord r = (EscherRecord) iterator.next();
|
||||
|
@ -138,10 +145,16 @@ public abstract class AbstractEscherHolderRecord
|
|||
LittleEndian.putShort( data, 2 + offset, (short) ( getRecordSize() - 4 ) );
|
||||
if ( escherRecords.size() == 0 && rawData != null )
|
||||
{
|
||||
System.arraycopy( rawData, 0, data, offset + 4, rawData.length );
|
||||
LittleEndian.putShort(data, 0 + offset, getSid());
|
||||
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
|
||||
System.arraycopy( rawData, 0, data, 4 + offset, rawData.length);
|
||||
return rawData.length + 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
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(); )
|
||||
{
|
||||
|
@ -255,6 +268,45 @@ public abstract class AbstractEscherHolderRecord
|
|||
return (EscherRecord) escherRecords.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Big drawing group records are split but it's easier to deal with them
|
||||
* as a whole group so we need to join them together.
|
||||
*/
|
||||
public void join( AbstractEscherHolderRecord record )
|
||||
{
|
||||
int length = this.rawData.length + record.getRawData().length;
|
||||
byte[] data = new byte[length];
|
||||
System.arraycopy( rawData, 0, data, 0, rawData.length );
|
||||
System.arraycopy( record.getRawData(), 0, data, rawData.length, record.getRawData().length );
|
||||
rawData = data;
|
||||
}
|
||||
|
||||
public void processContinueRecord( byte[] record )
|
||||
{
|
||||
int length = this.rawData.length + record.length;
|
||||
byte[] data = new byte[length];
|
||||
System.arraycopy( rawData, 0, data, 0, rawData.length );
|
||||
System.arraycopy( record, 0, data, rawData.length, record.length );
|
||||
rawData = data;
|
||||
}
|
||||
|
||||
public byte[] getRawData()
|
||||
{
|
||||
return rawData;
|
||||
}
|
||||
|
||||
public void setRawData( byte[] rawData )
|
||||
{
|
||||
this.rawData = rawData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert raw data to escher records.
|
||||
*/
|
||||
public void decode()
|
||||
{
|
||||
convertToEscherRecords(0, rawData.length, rawData );
|
||||
}
|
||||
|
||||
} // END OF CLASS
|
||||
|
||||
|
|
|
@ -16,10 +16,22 @@
|
|||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.ddf.EscherRecord;
|
||||
import org.apache.poi.ddf.NullEscherSerializationListener;
|
||||
import org.apache.poi.util.ArrayUtil;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class DrawingGroupRecord extends AbstractEscherHolderRecord
|
||||
{
|
||||
public static final short sid = 0xEB;
|
||||
|
||||
static final int MAX_RECORD_SIZE = 8228;
|
||||
private static final int MAX_DATA_SIZE = MAX_RECORD_SIZE - 4;
|
||||
|
||||
public DrawingGroupRecord()
|
||||
{
|
||||
}
|
||||
|
@ -43,4 +55,92 @@ public class DrawingGroupRecord extends AbstractEscherHolderRecord
|
|||
{
|
||||
return sid;
|
||||
}
|
||||
|
||||
public int serialize(int offset, byte[] data)
|
||||
{
|
||||
byte[] rawData = getRawData();
|
||||
if (getEscherRecords().size() == 0 && rawData != null)
|
||||
{
|
||||
return writeData( offset, data, rawData );
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] buffer = new byte[getRawDataSize()];
|
||||
int pos = 0;
|
||||
for ( Iterator iterator = getEscherRecords().iterator(); iterator.hasNext(); )
|
||||
{
|
||||
EscherRecord r = (EscherRecord) iterator.next();
|
||||
pos += r.serialize(pos, buffer, new NullEscherSerializationListener() );
|
||||
}
|
||||
|
||||
return writeData( offset, data, buffer );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Size of record (including 4 byte headers for all sections)
|
||||
*/
|
||||
public int getRecordSize()
|
||||
{
|
||||
return grossSizeFromDataSize( getRawDataSize() );
|
||||
}
|
||||
|
||||
public int getRawDataSize()
|
||||
{
|
||||
List escherRecords = getEscherRecords();
|
||||
byte[] rawData = getRawData();
|
||||
if (escherRecords.size() == 0 && rawData != null)
|
||||
{
|
||||
return rawData.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
int size = 0;
|
||||
for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
|
||||
{
|
||||
EscherRecord r = (EscherRecord) iterator.next();
|
||||
size += r.getRecordSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
static int grossSizeFromDataSize(int dataSize)
|
||||
{
|
||||
return dataSize + ( (dataSize - 1) / MAX_DATA_SIZE + 1 ) * 4;
|
||||
}
|
||||
|
||||
private int writeData( int offset, byte[] data, byte[] rawData )
|
||||
{
|
||||
int writtenActualData = 0;
|
||||
int writtenRawData = 0;
|
||||
while (writtenRawData < rawData.length)
|
||||
{
|
||||
int segmentLength = Math.min( rawData.length - writtenRawData, MAX_DATA_SIZE);
|
||||
if (writtenRawData / MAX_DATA_SIZE >= 2)
|
||||
writeContinueHeader( data, offset, segmentLength );
|
||||
else
|
||||
writeHeader( data, offset, segmentLength );
|
||||
writtenActualData += 4;
|
||||
offset += 4;
|
||||
ArrayUtil.arraycopy( rawData, writtenRawData, data, offset, segmentLength );
|
||||
offset += segmentLength;
|
||||
writtenRawData += segmentLength;
|
||||
writtenActualData += segmentLength;
|
||||
}
|
||||
return writtenActualData;
|
||||
}
|
||||
|
||||
private void writeHeader( byte[] data, int offset, int sizeExcludingHeader )
|
||||
{
|
||||
LittleEndian.putShort(data, 0 + offset, getSid());
|
||||
LittleEndian.putShort(data, 2 + offset, (short) sizeExcludingHeader);
|
||||
}
|
||||
|
||||
private void writeContinueHeader( byte[] data, int offset, int sizeExcludingHeader )
|
||||
{
|
||||
LittleEndian.putShort(data, 0 + offset, ContinueRecord.sid);
|
||||
LittleEndian.putShort(data, 2 + offset, (short) sizeExcludingHeader);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -68,6 +68,14 @@ public class DrawingRecord extends Record
|
|||
recordData = data;
|
||||
}
|
||||
|
||||
public void processContinueRecord( byte[] record )
|
||||
{
|
||||
byte[] newBuffer = new byte[ recordData.length + record.length ];
|
||||
System.arraycopy( recordData, 0, newBuffer, 0, recordData.length );
|
||||
System.arraycopy( record, 0, newBuffer, recordData.length, record.length);
|
||||
recordData = newBuffer;
|
||||
}
|
||||
|
||||
public int serialize( int offset, byte[] data )
|
||||
{
|
||||
if (recordData == null)
|
||||
|
|
|
@ -20,7 +20,7 @@ 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.DrawingManager2;
|
||||
import org.apache.poi.hssf.model.ConvertAnchor;
|
||||
|
||||
import java.util.*;
|
||||
|
@ -256,10 +256,10 @@ public class EscherAggregate extends AbstractEscherHolderRecord
|
|||
|
||||
/** Maps shape container objects to their OBJ records */
|
||||
private Map shapeToObj = new HashMap();
|
||||
private DrawingManager drawingManager;
|
||||
private DrawingManager2 drawingManager;
|
||||
private short drawingGroupId;
|
||||
|
||||
public EscherAggregate( DrawingManager drawingManager )
|
||||
public EscherAggregate( DrawingManager2 drawingManager )
|
||||
{
|
||||
this.drawingManager = drawingManager;
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ public class EscherAggregate extends AbstractEscherHolderRecord
|
|||
/**
|
||||
* Collapses the drawing records into an aggregate.
|
||||
*/
|
||||
public static EscherAggregate createAggregate( List records, int locFirstDrawingRecord, DrawingManager drawingManager )
|
||||
public static EscherAggregate createAggregate( List records, int locFirstDrawingRecord, DrawingManager2 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.
|
||||
|
@ -571,6 +571,9 @@ public class EscherAggregate extends AbstractEscherHolderRecord
|
|||
escherParent.addChildRecord( shapeModel.getSpContainer() );
|
||||
}
|
||||
}
|
||||
// drawingManager.newCluster( (short)1 );
|
||||
// drawingManager.newCluster( (short)2 );
|
||||
|
||||
}
|
||||
|
||||
private void convertGroup( HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj )
|
||||
|
@ -678,7 +681,7 @@ public class EscherAggregate extends AbstractEscherHolderRecord
|
|||
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.setOptions( (short) 0x0001 ); // version
|
||||
spgr.setRectX1( patriarch.getX1() );
|
||||
spgr.setRectY1( patriarch.getY1() );
|
||||
spgr.setRectX2( patriarch.getX2() );
|
||||
|
|
|
@ -173,6 +173,14 @@ public class ObjRecord
|
|||
return subrecords.add( o );
|
||||
}
|
||||
|
||||
// made public to satisfy biffviewer
|
||||
|
||||
/* protected */
|
||||
public void processContinueRecord( byte[] record )
|
||||
{
|
||||
super.processContinueRecord( record );
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
ObjRecord rec = new ObjRecord();
|
||||
|
|
|
@ -148,6 +148,7 @@ public class RecordFactory
|
|||
{
|
||||
short rectype = 0;
|
||||
|
||||
DrawingRecord lastDrawingRecord = new DrawingRecord( );
|
||||
do
|
||||
{
|
||||
rectype = LittleEndian.readShort(in);
|
||||
|
@ -176,7 +177,13 @@ public class RecordFactory
|
|||
|
||||
if (record != null)
|
||||
{
|
||||
if (rectype == ContinueRecord.sid &&
|
||||
if (rectype == DrawingGroupRecord.sid
|
||||
&& last_record instanceof DrawingGroupRecord)
|
||||
{
|
||||
DrawingGroupRecord lastDGRecord = (DrawingGroupRecord) last_record;
|
||||
lastDGRecord.join((AbstractEscherHolderRecord) record);
|
||||
}
|
||||
else if (rectype == ContinueRecord.sid &&
|
||||
! (last_record instanceof ContinueRecord) && // include continuation records after
|
||||
! (last_record instanceof UnknownRecord) ) // unknown records or previous continuation records
|
||||
{
|
||||
|
@ -185,11 +192,18 @@ public class RecordFactory
|
|||
throw new RecordFormatException(
|
||||
"First record is a ContinueRecord??");
|
||||
}
|
||||
last_record.processContinueRecord(data);
|
||||
|
||||
// Drawing records have a very strange continue behaviour. There can actually be OBJ records mixed between the continues.
|
||||
if (last_record instanceof ObjRecord)
|
||||
lastDrawingRecord.processContinueRecord( data );
|
||||
else
|
||||
last_record.processContinueRecord(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
last_record = record;
|
||||
if (record instanceof DrawingRecord)
|
||||
lastDrawingRecord = (DrawingRecord) record;
|
||||
records.add(record);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import java.util.List;
|
|||
public class ColumnInfoRecordsAggregate
|
||||
extends Record
|
||||
{
|
||||
int size = 0;
|
||||
// int size = 0;
|
||||
List records = null;
|
||||
|
||||
public ColumnInfoRecordsAggregate()
|
||||
|
@ -40,6 +40,9 @@ public class ColumnInfoRecordsAggregate
|
|||
|
||||
public int getRecordSize()
|
||||
{
|
||||
int size = 0;
|
||||
for ( Iterator iterator = records.iterator(); iterator.hasNext(); )
|
||||
size += ( (ColumnInfoRecord) iterator.next() ).getRecordSize();
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -68,7 +71,6 @@ public class ColumnInfoRecordsAggregate
|
|||
*/
|
||||
public void insertColumn( ColumnInfoRecord col )
|
||||
{
|
||||
size += col.getRecordSize();
|
||||
records.add( col );
|
||||
}
|
||||
|
||||
|
@ -78,7 +80,6 @@ public class ColumnInfoRecordsAggregate
|
|||
*/
|
||||
public void insertColumn( int idx, ColumnInfoRecord col )
|
||||
{
|
||||
size += col.getRecordSize();
|
||||
records.add( idx, col );
|
||||
}
|
||||
|
||||
|
|
|
@ -228,7 +228,7 @@ public class RowRecordsAggregate
|
|||
|
||||
/**
|
||||
* called by the constructor, should set class level fields. Should throw
|
||||
* runtime exception for bad/icomplete data.
|
||||
* runtime exception for bad/incomplete data.
|
||||
*
|
||||
* @param data raw data
|
||||
* @param size size of data
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.ddf.EscherClientAnchorRecord;
|
||||
import org.apache.poi.ddf.EscherRecord;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -33,6 +32,7 @@ public class HSSFClientAnchor
|
|||
int row1;
|
||||
short col2;
|
||||
int row2;
|
||||
int anchorType;
|
||||
|
||||
/**
|
||||
* Creates a new client anchor and defaults all the anchor positions to 0.
|
||||
|
@ -213,6 +213,26 @@ public class HSSFClientAnchor
|
|||
return row1 > row2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the anchor type
|
||||
* <p>
|
||||
* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells.
|
||||
*/
|
||||
public int getAnchorType()
|
||||
{
|
||||
return anchorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the anchor type
|
||||
* <p>
|
||||
* 0 = Move and size with Cells, 2 = Move but don't size with cells, 3 = Don't move or size with cells.
|
||||
*/
|
||||
public void setAnchorType( int anchorType )
|
||||
{
|
||||
this.anchorType = anchorType;
|
||||
}
|
||||
|
||||
private void checkRange( int value, int minRange, int maxRange, String varName )
|
||||
{
|
||||
if (value < minRange || value > maxRange)
|
||||
|
|
|
@ -77,6 +77,23 @@ public class HSSFPatriarch
|
|||
return shape;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a picture.
|
||||
*
|
||||
* @param anchor the client anchor describes how this group is attached
|
||||
* to the sheet.
|
||||
* @return the newly created shape.
|
||||
*/
|
||||
public HSSFPicture createPicture(HSSFClientAnchor anchor, int pictureIndex)
|
||||
{
|
||||
HSSFPicture shape = new HSSFPicture(null, anchor);
|
||||
shape.setPictureIndex( pictureIndex );
|
||||
shape.anchor = anchor;
|
||||
shapes.add(shape);
|
||||
return shape;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a polygon
|
||||
*
|
||||
|
|
|
@ -1220,19 +1220,22 @@ public class HSSFSheet
|
|||
* Aggregates the drawing records and dumps the escher record hierarchy
|
||||
* to the standard output.
|
||||
*/
|
||||
public void dumpDrawingRecords()
|
||||
public void dumpDrawingRecords(boolean fat)
|
||||
{
|
||||
sheet.aggregateDrawingRecords(book.getDrawingManager());
|
||||
|
||||
EscherAggregate r = (EscherAggregate) getSheet().findFirstRecordBySid(EscherAggregate.sid);
|
||||
List escherRecords = r.getEscherRecords();
|
||||
PrintWriter w = new PrintWriter(System.out);
|
||||
for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
|
||||
{
|
||||
EscherRecord escherRecord = (EscherRecord) iterator.next();
|
||||
PrintWriter w = new PrintWriter(System.out);
|
||||
escherRecord.display(w, 0);
|
||||
w.close();
|
||||
if (fat)
|
||||
System.out.println(escherRecord.toString());
|
||||
else
|
||||
escherRecord.display(w, 0);
|
||||
}
|
||||
w.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,7 +34,7 @@ public class HSSFSimpleShape
|
|||
// 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_PICTURE = 8;
|
||||
// public final static short OBJECT_TYPE_POLYGON = 9;
|
||||
// public final static short OBJECT_TYPE_CHECKBOX = 11;
|
||||
// public final static short OBJECT_TYPE_OPTION_BUTTON = 12;
|
||||
|
@ -63,6 +63,7 @@ public class HSSFSimpleShape
|
|||
* @see #OBJECT_TYPE_LINE
|
||||
* @see #OBJECT_TYPE_OVAL
|
||||
* @see #OBJECT_TYPE_RECTANGLE
|
||||
* @see #OBJECT_TYPE_PICTURE
|
||||
*/
|
||||
public int getShapeType() { return shapeType; }
|
||||
|
||||
|
@ -74,6 +75,7 @@ public class HSSFSimpleShape
|
|||
* @see #OBJECT_TYPE_LINE
|
||||
* @see #OBJECT_TYPE_OVAL
|
||||
* @see #OBJECT_TYPE_RECTANGLE
|
||||
* @see #OBJECT_TYPE_PICTURE
|
||||
*/
|
||||
public void setShapeType( int shapeType ){ this.shapeType = shapeType; }
|
||||
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
*/
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.ddf.EscherBSERecord;
|
||||
import org.apache.poi.ddf.EscherBitmapBlip;
|
||||
import org.apache.poi.ddf.EscherRecord;
|
||||
import org.apache.poi.hssf.eventmodel.EventRecordFactory;
|
||||
import org.apache.poi.hssf.model.Sheet;
|
||||
import org.apache.poi.hssf.model.Workbook;
|
||||
|
@ -38,6 +41,7 @@ import java.io.ByteArrayInputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
@ -57,7 +61,6 @@ import java.util.Stack;
|
|||
*/
|
||||
|
||||
public class HSSFWorkbook
|
||||
extends java.lang.Object
|
||||
{
|
||||
private static final int DEBUG = POILogger.DEBUG;
|
||||
|
||||
|
@ -108,13 +111,31 @@ public class HSSFWorkbook
|
|||
*/
|
||||
private HSSFDataFormat formatter;
|
||||
|
||||
|
||||
/// NOT YET SUPPORTED:
|
||||
/** Extended windows meta file */
|
||||
//public static final int PICTURE_TYPE_EMF = 2;
|
||||
/** Windows Meta File */
|
||||
//public static final int PICTURE_TYPE_WMF = 3;
|
||||
/** Mac PICT format */
|
||||
//public static final int PICTURE_TYPE_PICT = 4;
|
||||
|
||||
/** JPEG format */
|
||||
public static final int PICTURE_TYPE_JPEG = 5;
|
||||
/** PNG format */
|
||||
public static final int PICTURE_TYPE_PNG = 6;
|
||||
/** Device independant bitmap */
|
||||
public static final int PICTURE_TYPE_DIB = 7;
|
||||
|
||||
|
||||
private static POILogger log = POILogFactory.getLogger(HSSFWorkbook.class);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates new HSSFWorkbook from scratch (start here!)
|
||||
*
|
||||
*/
|
||||
|
||||
public HSSFWorkbook()
|
||||
{
|
||||
this(Workbook.createWorkbook());
|
||||
|
@ -159,8 +180,6 @@ public class HSSFWorkbook
|
|||
|
||||
EventRecordFactory factory = new EventRecordFactory();
|
||||
|
||||
|
||||
|
||||
List records = RecordFactory.createRecords(stream);
|
||||
|
||||
workbook = Workbook.createWorkbook(records);
|
||||
|
@ -796,8 +815,9 @@ public class HSSFWorkbook
|
|||
|
||||
// byte[] sb = (byte[])sheetbytes.get(k);
|
||||
// System.arraycopy(sb, 0, retval, pos, sb.length);
|
||||
pos += ((HSSFSheet) sheets.get(k)).getSheet().serialize(pos,
|
||||
retval); // sb.length;
|
||||
int len = ((HSSFSheet) sheets.get(k)).getSheet().serialize(pos,
|
||||
retval);
|
||||
pos += len; // sb.length;
|
||||
}
|
||||
/* for (int k = pos; k < totalsize; k++)
|
||||
{
|
||||
|
@ -1067,6 +1087,68 @@ public class HSSFWorkbook
|
|||
workbook.getRecords().add(loc, r);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spits out a list of all the drawing records in the workbook.
|
||||
*/
|
||||
public void dumpDrawingGroupRecords(boolean fat)
|
||||
{
|
||||
DrawingGroupRecord r = (DrawingGroupRecord) workbook.findFirstRecordBySid( DrawingGroupRecord.sid );
|
||||
r.decode();
|
||||
List escherRecords = r.getEscherRecords();
|
||||
PrintWriter w = new PrintWriter(System.out);
|
||||
for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
|
||||
{
|
||||
EscherRecord escherRecord = (EscherRecord) iterator.next();
|
||||
if (fat)
|
||||
System.out.println(escherRecord.toString());
|
||||
else
|
||||
escherRecord.display(w, 0);
|
||||
}
|
||||
w.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a picture to the workbook.
|
||||
*
|
||||
* @param pictureData The bytes of the picture
|
||||
* @param format The format of the picture. One of <code>PICTURE_TYPE_*</code>
|
||||
*
|
||||
* @return the index to this picture (1 based).
|
||||
*/
|
||||
public int addPicture(byte[] pictureData, int format)
|
||||
{
|
||||
byte[] uid = newUID();
|
||||
EscherBitmapBlip blipRecord = new EscherBitmapBlip();
|
||||
blipRecord.setRecordId( (short) ( EscherBitmapBlip.RECORD_ID_START + format ) );
|
||||
if (format == HSSFWorkbook.PICTURE_TYPE_PNG)
|
||||
blipRecord.setOptions( (short) 0x6E00 ); // MSOBI
|
||||
else if (format == HSSFWorkbook.PICTURE_TYPE_JPEG)
|
||||
blipRecord.setOptions( (short) 0x46A0 ); // MSOBI
|
||||
else if (format == HSSFWorkbook.PICTURE_TYPE_DIB)
|
||||
blipRecord.setOptions( (short) 0x7A8 ); // MSOBI
|
||||
|
||||
blipRecord.setUID( uid );
|
||||
blipRecord.setMarker( (byte) 0xFF );
|
||||
blipRecord.setPictureData( pictureData );
|
||||
|
||||
EscherBSERecord r = new EscherBSERecord();
|
||||
r.setRecordId( EscherBSERecord.RECORD_ID );
|
||||
r.setOptions( (short) ( 0x0002 | ( format << 4 ) ) );
|
||||
r.setBlipTypeMacOS( (byte) format );
|
||||
r.setBlipTypeWin32( (byte) format );
|
||||
r.setUid( uid );
|
||||
r.setTag( (short) 0xFF );
|
||||
r.setSize( pictureData.length + 25 );
|
||||
r.setRef( 1 );
|
||||
r.setOffset( 0 );
|
||||
r.setBlipRecord( blipRecord );
|
||||
|
||||
return workbook.addBSERecord( r );
|
||||
}
|
||||
|
||||
private byte[] newUID()
|
||||
{
|
||||
byte[] bytes = new byte[16];
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,12 +17,11 @@
|
|||
|
||||
package org.apache.poi.util;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
|
@ -35,7 +34,15 @@ public class DrawingDump
|
|||
POIFSFileSystem fs =
|
||||
new POIFSFileSystem(new FileInputStream(args[0]));
|
||||
HSSFWorkbook wb = new HSSFWorkbook(fs);
|
||||
HSSFSheet sheet = wb.getSheetAt(0);
|
||||
sheet.dumpDrawingRecords();
|
||||
System.out.println( "Drawing group:" );
|
||||
wb.dumpDrawingGroupRecords(true);
|
||||
|
||||
for (int sheetNum = 1; sheetNum <= wb.getNumberOfSheets(); sheetNum++)
|
||||
{
|
||||
System.out.println( "Sheet " + sheetNum + ":" );
|
||||
HSSFSheet sheet = wb.getSheetAt(sheetNum - 1);
|
||||
sheet.dumpDrawingRecords(true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ public class HexDump
|
|||
{
|
||||
if (data.length == 0)
|
||||
{
|
||||
stream.write( "No Data".getBytes() );
|
||||
stream.write( ("No Data" + System.getProperty( "line.separator")).getBytes() );
|
||||
stream.flush();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -98,8 +98,9 @@ public class TestEscherBSERecord extends TestCase
|
|||
" Name: 5" + nl +
|
||||
" Unused2: 6" + nl +
|
||||
" Unused3: 7" + nl +
|
||||
" blipRecord: null" + nl +
|
||||
" Extra Data:" + nl +
|
||||
"No Data", record.toString() );
|
||||
"No Data" + nl, record.toString() );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import junit.framework.TestCase;
|
|||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.HexRead;
|
||||
|
||||
public class TestEscherBlipRecord extends TestCase
|
||||
public class TestEscherBlipWMFRecord extends TestCase
|
||||
{
|
||||
private String dataStr;
|
||||
private byte[] data;
|
||||
|
@ -37,7 +37,7 @@ public class TestEscherBlipRecord extends TestCase
|
|||
|
||||
public void testSerialize() throws Exception
|
||||
{
|
||||
EscherBlipRecord r = new EscherBlipRecord();
|
||||
EscherBlipWMFRecord r = new EscherBlipWMFRecord();
|
||||
r.setBoundaryLeft(1);
|
||||
r.setBoundaryHeight(2);
|
||||
r.setBoundaryTop(3);
|
||||
|
@ -52,7 +52,7 @@ public class TestEscherBlipRecord extends TestCase
|
|||
(byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, });
|
||||
r.setWidth(10);
|
||||
r.setHeight(11);
|
||||
r.setRecordId(EscherBlipRecord.RECORD_ID_START);
|
||||
r.setRecordId(EscherBlipWMFRecord.RECORD_ID_START);
|
||||
r.setOptions((short)5420);
|
||||
r.setData(new byte[] { (byte)0x01, (byte)0x02 } );
|
||||
|
||||
|
@ -79,10 +79,10 @@ public class TestEscherBlipRecord extends TestCase
|
|||
|
||||
public void testFillFields() throws Exception
|
||||
{
|
||||
EscherBlipRecord r = new EscherBlipRecord();
|
||||
EscherBlipWMFRecord r = new EscherBlipWMFRecord();
|
||||
r.fillFields( data, 0, new DefaultEscherRecordFactory());
|
||||
|
||||
assertEquals( EscherBlipRecord.RECORD_ID_START, r.getRecordId() );
|
||||
assertEquals( EscherBlipWMFRecord.RECORD_ID_START, r.getRecordId() );
|
||||
assertEquals( 1, r.getBoundaryLeft() );
|
||||
assertEquals( 2, r.getBoundaryHeight() );
|
||||
assertEquals( 3, r.getBoundaryTop() );
|
||||
|
@ -100,12 +100,12 @@ public class TestEscherBlipRecord extends TestCase
|
|||
|
||||
public void testToString() throws Exception
|
||||
{
|
||||
EscherBlipRecord r = new EscherBlipRecord();
|
||||
EscherBlipWMFRecord r = new EscherBlipWMFRecord();
|
||||
r.fillFields( data, 0, new DefaultEscherRecordFactory() );
|
||||
|
||||
String nl = System.getProperty("line.separator");
|
||||
|
||||
assertEquals( "org.apache.poi.ddf.EscherBlipRecord:" + nl +
|
||||
assertEquals( "org.apache.poi.ddf.EscherBlipWMFRecord:" + nl +
|
||||
" RecordId: 0xF018" + nl +
|
||||
" Options: 0x152C" + nl +
|
||||
" Secondary UID: [01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, ]" + nl +
|
|
@ -24,7 +24,7 @@ public class TestEscherBoolProperty extends TestCase
|
|||
public void testToString() throws Exception
|
||||
{
|
||||
EscherBoolProperty p = new EscherBoolProperty((short)1, 1);
|
||||
assertEquals("propNum: 1, propName: unknown, complex: false, blipId: false, value: 1 (0x00000001)", p.toString());
|
||||
assertEquals("propNum: 1, RAW: 0x0001, propName: unknown, complex: false, blipId: false, value: 1 (0x00000001)", p.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ public class TestEscherClientDataRecord extends TestCase
|
|||
" RecordId: 0xF011" + nl +
|
||||
" Options: 0x0002" + nl +
|
||||
" Extra Data:" + nl +
|
||||
"No Data" ;
|
||||
"No Data" + nl ;
|
||||
assertEquals( expected, createRecord().toString() );
|
||||
}
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ public class TestEscherOptRecord extends TestCase
|
|||
" recordId: 0x" + HexDump.toHex(EscherOptRecord.RECORD_ID) + nl +
|
||||
" numchildren: 0" + nl +
|
||||
" properties:" + nl +
|
||||
" propNum: 1, propName: unknown, complex: false, blipId: false, value: 1 (0x00000001)" + nl;
|
||||
" propNum: 1, RAW: 0x0001, propName: unknown, complex: false, blipId: false, value: 1 (0x00000001)" + nl;
|
||||
assertEquals( expected, r.toString());
|
||||
}
|
||||
|
||||
|
|
|
@ -19,16 +19,14 @@
|
|||
package org.apache.poi.hssf.model;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.hssf.record.BOFRecord;
|
||||
import org.apache.poi.hssf.record.EOFRecord;
|
||||
import org.apache.poi.hssf.record.DimensionsRecord;
|
||||
import org.apache.poi.hssf.record.*;
|
||||
import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
|
||||
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
|
||||
import org.apache.poi.hssf.record.aggregates.ValueRecordsAggregate;
|
||||
import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Unit test for the Sheet class.
|
||||
|
@ -55,4 +53,232 @@ public class TestSheet extends TestCase
|
|||
assertTrue( sheet.records.get(pos++) instanceof EOFRecord );
|
||||
}
|
||||
|
||||
public void testAddMergedRegion()
|
||||
{
|
||||
Sheet sheet = Sheet.createSheet();
|
||||
int regionsToAdd = 4096;
|
||||
int startRecords = sheet.getRecords().size();
|
||||
|
||||
//simple test that adds a load of regions
|
||||
for (int n = 0; n < regionsToAdd; n++)
|
||||
{
|
||||
int index = sheet.addMergedRegion(0, (short) 0, 1, (short) 1);
|
||||
assertTrue("Merged region index expected to be " + n + " got " + index, index == n);
|
||||
}
|
||||
|
||||
//test all the regions were indeed added
|
||||
assertTrue(sheet.getNumMergedRegions() == regionsToAdd);
|
||||
|
||||
//test that the regions were spread out over the appropriate number of records
|
||||
int recordsAdded = sheet.getRecords().size() - startRecords;
|
||||
int recordsExpected = regionsToAdd/1027;
|
||||
if ((regionsToAdd % 1027) != 0)
|
||||
recordsExpected++;
|
||||
assertTrue("The " + regionsToAdd + " merged regions should have been spread out over " + recordsExpected + " records, not " + recordsAdded, recordsAdded == recordsExpected);
|
||||
}
|
||||
|
||||
public void testRemoveMergedRegion()
|
||||
{
|
||||
Sheet sheet = Sheet.createSheet();
|
||||
int regionsToAdd = 4096;
|
||||
|
||||
for (int n = 0; n < regionsToAdd; n++)
|
||||
sheet.addMergedRegion(0, (short) 0, 1, (short) 1);
|
||||
|
||||
int records = sheet.getRecords().size();
|
||||
|
||||
//remove a third from the beginning
|
||||
for (int n = 0; n < regionsToAdd/3; n++)
|
||||
{
|
||||
sheet.removeMergedRegion(0);
|
||||
//assert they have been deleted
|
||||
assertTrue("Num of regions should be " + (regionsToAdd - n - 1) + " not " + sheet.getNumMergedRegions(), sheet.getNumMergedRegions() == regionsToAdd - n - 1);
|
||||
}
|
||||
|
||||
//assert any record removing was done
|
||||
int recordsRemoved = (regionsToAdd/3)/1027; //doesn't work for particular values of regionsToAdd
|
||||
assertTrue("Expected " + recordsRemoved + " record to be removed from the starting " + records + ". Currently there are " + sheet.getRecords().size() + " records", records - sheet.getRecords().size() == recordsRemoved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bug: 22922 (Reported by Xuemin Guan)
|
||||
* <p>
|
||||
* Remove mergedregion fails when a sheet loses records after an initial CreateSheet
|
||||
* fills up the records.
|
||||
*
|
||||
*/
|
||||
public void testMovingMergedRegion() {
|
||||
List records = new ArrayList();
|
||||
|
||||
MergeCellsRecord merged = new MergeCellsRecord();
|
||||
merged.addArea(0, (short)0, 1, (short)2);
|
||||
records.add(new RowRecord());
|
||||
records.add(new RowRecord());
|
||||
records.add(new RowRecord());
|
||||
records.add(merged);
|
||||
|
||||
Sheet sheet = Sheet.createSheet(records, 0);
|
||||
sheet.records.remove(0);
|
||||
|
||||
//stub object to throw off list INDEX operations
|
||||
sheet.removeMergedRegion(0);
|
||||
assertEquals("Should be no more merged regions", 0, sheet.getNumMergedRegions());
|
||||
}
|
||||
|
||||
public void testGetMergedRegionAt()
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
public void testGetNumMergedRegions()
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure all rows registered for this sheet are aggregated, they were being skipped
|
||||
*
|
||||
*/
|
||||
public void testRowAggregation() {
|
||||
List records = new ArrayList();
|
||||
RowRecord row = new RowRecord();
|
||||
row.setRowNumber(0);
|
||||
records.add(row);
|
||||
|
||||
row = new RowRecord();
|
||||
row.setRowNumber(1);
|
||||
records.add(row);
|
||||
|
||||
records.add(new StringRecord());
|
||||
|
||||
row = new RowRecord();
|
||||
row.setRowNumber(2);
|
||||
records.add(row);
|
||||
|
||||
|
||||
Sheet sheet = Sheet.createSheet(records, 0);
|
||||
assertNotNull("Row [2] was skipped", sheet.getRow(2));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure page break functionality works (in memory)
|
||||
*
|
||||
*/
|
||||
public void testRowPageBreaks(){
|
||||
short colFrom = 0;
|
||||
short colTo = 255;
|
||||
|
||||
Sheet sheet = Sheet.createSheet();
|
||||
sheet.setRowBreak(0, colFrom, colTo);
|
||||
|
||||
assertTrue("no row break at 0", sheet.isRowBroken(0));
|
||||
assertEquals("1 row break available", 1, sheet.getNumRowBreaks());
|
||||
|
||||
sheet.setRowBreak(0, colFrom, colTo);
|
||||
sheet.setRowBreak(0, colFrom, colTo);
|
||||
|
||||
assertTrue("no row break at 0", sheet.isRowBroken(0));
|
||||
assertEquals("1 row break available", 1, sheet.getNumRowBreaks());
|
||||
|
||||
sheet.setRowBreak(10, colFrom, colTo);
|
||||
sheet.setRowBreak(11, colFrom, colTo);
|
||||
|
||||
assertTrue("no row break at 10", sheet.isRowBroken(10));
|
||||
assertTrue("no row break at 11", sheet.isRowBroken(11));
|
||||
assertEquals("3 row break available", 3, sheet.getNumRowBreaks());
|
||||
|
||||
|
||||
boolean is10 = false;
|
||||
boolean is0 = false;
|
||||
boolean is11 = false;
|
||||
|
||||
Iterator iterator = sheet.getRowBreaks();
|
||||
while (iterator.hasNext()) {
|
||||
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
|
||||
int main = (int)breakItem.main;
|
||||
if (main != 0 && main != 10 && main != 11) fail("Invalid page break");
|
||||
if (main == 0) is0 = true;
|
||||
if (main == 10) is10= true;
|
||||
if (main == 11) is11 = true;
|
||||
}
|
||||
|
||||
assertTrue("one of the breaks didnt make it", is0 && is10 && is11);
|
||||
|
||||
sheet.removeRowBreak(11);
|
||||
assertFalse("row should be removed", sheet.isRowBroken(11));
|
||||
|
||||
sheet.removeRowBreak(0);
|
||||
assertFalse("row should be removed", sheet.isRowBroken(0));
|
||||
|
||||
sheet.removeRowBreak(10);
|
||||
assertFalse("row should be removed", sheet.isRowBroken(10));
|
||||
|
||||
assertEquals("no more breaks", 0, sheet.getNumRowBreaks());
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure column pag breaks works properly (in-memory)
|
||||
*
|
||||
*/
|
||||
public void testColPageBreaks(){
|
||||
short rowFrom = 0;
|
||||
short rowTo = (short)65535;
|
||||
|
||||
Sheet sheet = Sheet.createSheet();
|
||||
sheet.setColumnBreak((short)0, rowFrom, rowTo);
|
||||
|
||||
assertTrue("no col break at 0", sheet.isColumnBroken((short)0));
|
||||
assertEquals("1 col break available", 1, sheet.getNumColumnBreaks());
|
||||
|
||||
sheet.setColumnBreak((short)0, rowFrom, rowTo);
|
||||
|
||||
assertTrue("no col break at 0", sheet.isColumnBroken((short)0));
|
||||
assertEquals("1 col break available", 1, sheet.getNumColumnBreaks());
|
||||
|
||||
sheet.setColumnBreak((short)1, rowFrom, rowTo);
|
||||
sheet.setColumnBreak((short)10, rowFrom, rowTo);
|
||||
sheet.setColumnBreak((short)15, rowFrom, rowTo);
|
||||
|
||||
assertTrue("no col break at 1", sheet.isColumnBroken((short)1));
|
||||
assertTrue("no col break at 10", sheet.isColumnBroken((short)10));
|
||||
assertTrue("no col break at 15", sheet.isColumnBroken((short)15));
|
||||
assertEquals("4 col break available", 4, sheet.getNumColumnBreaks());
|
||||
|
||||
boolean is10 = false;
|
||||
boolean is0 = false;
|
||||
boolean is1 = false;
|
||||
boolean is15 = false;
|
||||
|
||||
Iterator iterator = sheet.getColumnBreaks();
|
||||
while (iterator.hasNext()) {
|
||||
PageBreakRecord.Break breakItem = (PageBreakRecord.Break)iterator.next();
|
||||
int main = (int)breakItem.main;
|
||||
if (main != 0 && main != 1 && main != 10 && main != 15) fail("Invalid page break");
|
||||
if (main == 0) is0 = true;
|
||||
if (main == 1) is1 = true;
|
||||
if (main == 10) is10= true;
|
||||
if (main == 15) is15 = true;
|
||||
}
|
||||
|
||||
assertTrue("one of the breaks didnt make it", is0 && is1 && is10 && is15);
|
||||
|
||||
sheet.removeColumnBreak((short)15);
|
||||
assertFalse("column break should not be there", sheet.isColumnBroken((short)15));
|
||||
|
||||
sheet.removeColumnBreak((short)0);
|
||||
assertFalse("column break should not be there", sheet.isColumnBroken((short)0));
|
||||
|
||||
sheet.removeColumnBreak((short)1);
|
||||
assertFalse("column break should not be there", sheet.isColumnBroken((short)1));
|
||||
|
||||
sheet.removeColumnBreak((short)10);
|
||||
assertFalse("column break should not be there", sheet.isColumnBroken((short)10));
|
||||
|
||||
assertEquals("no more breaks", 0, sheet.getNumColumnBreaks());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,9 @@ import org.apache.poi.util.HexDump;
|
|||
|
||||
public class TestDrawingGroupRecord extends TestCase
|
||||
{
|
||||
static final int MAX_RECORD_SIZE = 8228;
|
||||
private static final int MAX_DATA_SIZE = MAX_RECORD_SIZE - 4;
|
||||
|
||||
public void testGetRecordSize()
|
||||
throws Exception
|
||||
{
|
||||
|
@ -48,5 +51,93 @@ public class TestDrawingGroupRecord extends TestCase
|
|||
assertEquals(28, size);
|
||||
|
||||
assertEquals(24, dggContainer.getRecordSize());
|
||||
|
||||
|
||||
r = new DrawingGroupRecord( );
|
||||
r.setRawData( new byte[MAX_DATA_SIZE] );
|
||||
assertEquals( MAX_RECORD_SIZE, r.getRecordSize() );
|
||||
r.setRawData( new byte[MAX_DATA_SIZE+1] );
|
||||
assertEquals( MAX_RECORD_SIZE + 5, r.getRecordSize() );
|
||||
r.setRawData( new byte[MAX_DATA_SIZE*2] );
|
||||
assertEquals( MAX_RECORD_SIZE * 2, r.getRecordSize() );
|
||||
r.setRawData( new byte[MAX_DATA_SIZE*2 + 1] );
|
||||
assertEquals( MAX_RECORD_SIZE * 2 + 5, r.getRecordSize() );
|
||||
}
|
||||
|
||||
public void testSerialize() throws Exception
|
||||
{
|
||||
// Check under max record size
|
||||
DrawingGroupRecord r = new DrawingGroupRecord();
|
||||
byte[] rawData = new byte[100];
|
||||
rawData[0] = 100;
|
||||
rawData[99] = (byte) 200;
|
||||
r.setRawData( rawData );
|
||||
byte[] buffer = new byte[r.getRecordSize()];
|
||||
int size = r.serialize( 0, buffer );
|
||||
assertEquals( 104, size );
|
||||
assertEquals("[EB, 00, 64, 00, 64, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, C8, ]", HexDump.toHex(buffer));
|
||||
|
||||
// check at max record size
|
||||
rawData = new byte[MAX_DATA_SIZE];
|
||||
r.setRawData( rawData );
|
||||
buffer = new byte[r.getRecordSize()];
|
||||
size = r.serialize( 0, buffer );
|
||||
assertEquals( MAX_RECORD_SIZE, size );
|
||||
|
||||
// check over max record size
|
||||
rawData = new byte[MAX_DATA_SIZE+1];
|
||||
rawData[rawData.length-1] = (byte) 255;
|
||||
r.setRawData( rawData );
|
||||
buffer = new byte[r.getRecordSize()];
|
||||
size = r.serialize( 0, buffer );
|
||||
assertEquals( MAX_RECORD_SIZE + 5, size );
|
||||
assertEquals( "[EB, 00, 20, 20, ]", HexDump.toHex(cut(buffer, 0, 4) ));
|
||||
assertEquals( "[00, EB, 00, 01, 00, FF, ]", HexDump.toHex(cut(buffer, MAX_RECORD_SIZE - 1, MAX_RECORD_SIZE + 5) ));
|
||||
|
||||
// check continue record
|
||||
rawData = new byte[MAX_DATA_SIZE * 2 + 1];
|
||||
rawData[rawData.length-1] = (byte) 255;
|
||||
r.setRawData( rawData );
|
||||
buffer = new byte[r.getRecordSize()];
|
||||
size = r.serialize( 0, buffer );
|
||||
assertEquals( MAX_RECORD_SIZE * 2 + 5, size );
|
||||
assertEquals( MAX_RECORD_SIZE * 2 + 5, r.getRecordSize() );
|
||||
assertEquals( "[EB, 00, 20, 20, ]", HexDump.toHex(cut(buffer, 0, 4) ));
|
||||
assertEquals( "[EB, 00, 20, 20, ]", HexDump.toHex(cut(buffer, MAX_RECORD_SIZE, MAX_RECORD_SIZE + 4) ));
|
||||
assertEquals( "[3C, 00, 01, 00, FF, ]", HexDump.toHex(cut(buffer, MAX_RECORD_SIZE * 2, MAX_RECORD_SIZE * 2 + 5) ));
|
||||
|
||||
// check continue record
|
||||
rawData = new byte[664532];
|
||||
r.setRawData( rawData );
|
||||
buffer = new byte[r.getRecordSize()];
|
||||
size = r.serialize( 0, buffer );
|
||||
assertEquals( 664856, size );
|
||||
assertEquals( 664856, r.getRecordSize() );
|
||||
}
|
||||
|
||||
private byte[] cut( byte[] data, int fromInclusive, int toExclusive )
|
||||
{
|
||||
int length = toExclusive - fromInclusive;
|
||||
byte[] result = new byte[length];
|
||||
System.arraycopy( data, fromInclusive, result, 0, length);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void testGrossSizeFromDataSize() throws Exception
|
||||
{
|
||||
for (int i = 0; i < MAX_RECORD_SIZE * 4; i += 11)
|
||||
{
|
||||
System.out.print( "data size = " + i + ", gross size = " + DrawingGroupRecord.grossSizeFromDataSize( i ) );
|
||||
System.out.println( " Diff: " + (DrawingGroupRecord.grossSizeFromDataSize( i ) - i) );
|
||||
}
|
||||
|
||||
assertEquals( 4, DrawingGroupRecord.grossSizeFromDataSize( 0 ) );
|
||||
assertEquals( 5, DrawingGroupRecord.grossSizeFromDataSize( 1 ) );
|
||||
assertEquals( MAX_RECORD_SIZE, DrawingGroupRecord.grossSizeFromDataSize( MAX_DATA_SIZE ) );
|
||||
assertEquals( MAX_RECORD_SIZE + 5, DrawingGroupRecord.grossSizeFromDataSize( MAX_DATA_SIZE + 1 ) );
|
||||
assertEquals( MAX_RECORD_SIZE * 2, DrawingGroupRecord.grossSizeFromDataSize( MAX_DATA_SIZE * 2 ) );
|
||||
assertEquals( MAX_RECORD_SIZE * 2 + 5, DrawingGroupRecord.grossSizeFromDataSize( MAX_DATA_SIZE * 2 + 1 ) );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -17,14 +17,13 @@
|
|||
package org.apache.poi.hssf.record;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.poi.util.HexRead;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.ddf.EscherContainerRecord;
|
||||
import org.apache.poi.ddf.EscherSpRecord;
|
||||
import org.apache.poi.ddf.EscherClientDataRecord;
|
||||
import org.apache.poi.ddf.EscherContainerRecord;
|
||||
import org.apache.poi.ddf.EscherDggRecord;
|
||||
import org.apache.poi.hssf.model.DrawingManager;
|
||||
import org.apache.poi.hssf.model.Sheet;
|
||||
import org.apache.poi.ddf.EscherSpRecord;
|
||||
import org.apache.poi.hssf.model.DrawingManager2;
|
||||
import org.apache.poi.util.HexDump;
|
||||
import org.apache.poi.util.HexRead;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -82,7 +81,7 @@ public class TestEscherAggregate extends TestCase
|
|||
records.add( d2 );
|
||||
records.add( r2 );
|
||||
|
||||
DrawingManager drawingManager = new DrawingManager(new EscherDggRecord() );
|
||||
DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord() );
|
||||
EscherAggregate aggregate = EscherAggregate.createAggregate( records, 0, drawingManager );
|
||||
|
||||
assertEquals( 1, aggregate.getEscherRecords().size() );
|
||||
|
|
|
@ -23,6 +23,7 @@ import junit.framework.*;
|
|||
import java.io.*;
|
||||
|
||||
/**
|
||||
* @author Glen Stampoultzis (glens at apache.org)
|
||||
* @author Marc Johnson (mjohnson at apache dot org)
|
||||
*/
|
||||
|
||||
|
@ -281,7 +282,8 @@ public class TestHexDump
|
|||
// verify proper behaviour with empty byte array
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream( );
|
||||
HexDump.dump( new byte[0], 0, os, 0 );
|
||||
assertEquals( "No Data", os.toString() );
|
||||
assertEquals( "No Data" + System.getProperty( "line.separator"), os.toString() );
|
||||
|
||||
}
|
||||
|
||||
public void testToHex()
|
||||
|
@ -289,7 +291,7 @@ public class TestHexDump
|
|||
{
|
||||
assertEquals( "000A", HexDump.toHex((short)0xA));
|
||||
assertEquals( "0A", HexDump.toHex((byte)0xA));
|
||||
assertEquals( "0000000A", HexDump.toHex((int)0xA));
|
||||
assertEquals( "0000000A", HexDump.toHex(0xA));
|
||||
|
||||
assertEquals( "FFFF", HexDump.toHex((short)0xFFFF));
|
||||
|
||||
|
|
|
@ -18,11 +18,12 @@
|
|||
|
||||
package org.apache.poi.util;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.apache.poi.util.LittleEndian.BufferUnderrunException;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import junit.framework.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Class to test LittleEndian functionality
|
||||
|
@ -39,7 +40,6 @@ public class TestLittleEndian
|
|||
*
|
||||
* @param name
|
||||
*/
|
||||
|
||||
public TestLittleEndian(String name)
|
||||
{
|
||||
super(name);
|
||||
|
|
Loading…
Reference in New Issue