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}">
|
<copy todir="${main.output.dir}">
|
||||||
<fileset dir="${main.resource1.dir}"/>
|
<fileset dir="${main.resource1.dir}"/>
|
||||||
</copy>
|
</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"/>
|
<classpath refid="main.classpath"/>
|
||||||
</javac>
|
</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>
|
<classpath>
|
||||||
<path refid="main.classpath"/>
|
<path refid="main.classpath"/>
|
||||||
<pathelement location="${main.output.dir}"/>
|
<pathelement location="${main.output.dir}"/>
|
||||||
|
@ -269,10 +269,10 @@
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="compile-scratchpad" depends="init">
|
<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"/>
|
<classpath refid="scratchpad.classpath"/>
|
||||||
</javac>
|
</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>
|
<classpath>
|
||||||
<path refid="scratchpad.classpath"/>
|
<path refid="scratchpad.classpath"/>
|
||||||
<pathelement location="${scratchpad.output.dir}"/>
|
<pathelement location="${scratchpad.output.dir}"/>
|
||||||
|
@ -282,10 +282,10 @@
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="compile-contrib" depends="init">
|
<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"/>
|
<classpath refid="contrib.classpath"/>
|
||||||
</javac>
|
</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>
|
<classpath>
|
||||||
<path refid="contrib.classpath"/>
|
<path refid="contrib.classpath"/>
|
||||||
<pathelement location="${contrib.output.dir}"/>
|
<pathelement location="${contrib.output.dir}"/>
|
||||||
|
|
|
@ -31,20 +31,21 @@
|
||||||
<li><link href="#CustomColors">Custom colors</link></li>
|
<li><link href="#CustomColors">Custom colors</link></li>
|
||||||
<li><link href="#ReadWriteWorkbook">Reading and writing</link></li>
|
<li><link href="#ReadWriteWorkbook">Reading and writing</link></li>
|
||||||
<li><link href="#NewLinesInCells">Use newlines in cells.</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="#FitTo">Fit Sheet to One Page</link></li>
|
||||||
<li><link href="#PrintArea2">Set print area for a sheet.</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="#FooterPageNumbers">Set page numbers on the footer of a sheet</link></li>
|
||||||
<li><link href="#ShiftRows">Shift rows.</link></li>
|
<li><link href="#ShiftRows">Shift rows</link></li>
|
||||||
<li><link href="#SelectSheet">Set a sheet as selected.</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="#Zoom">Set the zoom magnification for a sheet</link></li>
|
||||||
<li><link href="#Splits">Create split and freeze panes.</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="#Repeating">Repeating rows and columns</link></li>
|
||||||
<li><link href="#HeaderFooter">Headers and Footers.</link></li>
|
<li><link href="#HeaderFooter">Headers and Footers</link></li>
|
||||||
<li><link href="#DrawingShapes">Drawing Shapes.</link></li>
|
<li><link href="#DrawingShapes">Drawing Shapes</link></li>
|
||||||
<li><link href="#StylingShapes">Styling Shapes.</link></li>
|
<li><link href="#StylingShapes">Styling Shapes</link></li>
|
||||||
<li><link href="#Graphics2d">Shapes and Graphics2d.</link></li>
|
<li><link href="#Graphics2d">Shapes and Graphics2d</link></li>
|
||||||
<li><link href="#Outlining">Outlining.</link></li>
|
<li><link href="#Outlining">Outlining</link></li>
|
||||||
|
<li><link href="#Images">Images</link></li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
<section><title>Features</title>
|
<section><title>Features</title>
|
||||||
|
@ -940,5 +941,34 @@
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</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>
|
</body>
|
||||||
</document>
|
</document>
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
<release version="unreleased" date="???">
|
<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="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>
|
||||||
|
|
||||||
<release version="2.5.1-FINAL" date="29 Feburary 2004">
|
<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 org.apache.poi.hssf.usermodel.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Demonstrates how to use the office drawing capabilities of POI.
|
* Demonstrates how to use the office drawing capabilities of POI.
|
||||||
|
@ -39,12 +37,14 @@ public class OfficeDrawing
|
||||||
HSSFSheet sheet2 = wb.createSheet("second sheet");
|
HSSFSheet sheet2 = wb.createSheet("second sheet");
|
||||||
HSSFSheet sheet3 = wb.createSheet("third sheet");
|
HSSFSheet sheet3 = wb.createSheet("third sheet");
|
||||||
HSSFSheet sheet4 = wb.createSheet("fourth sheet");
|
HSSFSheet sheet4 = wb.createSheet("fourth sheet");
|
||||||
|
HSSFSheet sheet5 = wb.createSheet("fifth sheet");
|
||||||
|
|
||||||
// Draw stuff in them
|
// Draw stuff in them
|
||||||
drawSheet1( sheet1 );
|
drawSheet1( sheet1 );
|
||||||
drawSheet2( sheet2 );
|
drawSheet2( sheet2 );
|
||||||
drawSheet3( sheet3 );
|
drawSheet3( sheet3 );
|
||||||
drawSheet4( sheet4, wb );
|
drawSheet4( sheet4, wb );
|
||||||
|
drawSheet5( sheet5, wb );
|
||||||
|
|
||||||
// Write the file out.
|
// Write the file out.
|
||||||
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
|
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
|
||||||
|
@ -143,6 +143,53 @@ public class OfficeDrawing
|
||||||
textbox3.setNoFill(true); // make it transparent
|
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 )
|
private static void drawOval( HSSFPatriarch patriarch )
|
||||||
{
|
{
|
||||||
// Create an oval and style to taste.
|
// 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 )
|
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.setRecordId( header.getRecordId() );
|
||||||
r.setOptions( header.getOptions() );
|
r.setOptions( header.getOptions() );
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -17,15 +17,15 @@
|
||||||
|
|
||||||
package org.apache.poi.ddf;
|
package org.apache.poi.ddf;
|
||||||
|
|
||||||
import org.apache.poi.util.LittleEndian;
|
|
||||||
import org.apache.poi.util.HexDump;
|
import org.apache.poi.util.HexDump;
|
||||||
|
import org.apache.poi.util.LittleEndian;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.PrintWriter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The BSE record is related closely to the <code>EscherBlipRecord</code> and stores
|
* 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
|
* @author Glen Stampoultzis
|
||||||
* @see EscherBlipRecord
|
* @see EscherBlipRecord
|
||||||
|
@ -56,6 +56,7 @@ public class EscherBSERecord
|
||||||
private byte field_9_name;
|
private byte field_9_name;
|
||||||
private byte field_10_unused2;
|
private byte field_10_unused2;
|
||||||
private byte field_11_unused3;
|
private byte field_11_unused3;
|
||||||
|
private EscherBlipRecord field_12_blipRecord;
|
||||||
|
|
||||||
private byte[] remainingData;
|
private byte[] remainingData;
|
||||||
|
|
||||||
|
@ -85,9 +86,28 @@ public class EscherBSERecord
|
||||||
field_10_unused2 = data[pos + 34];
|
field_10_unused2 = data[pos + 34];
|
||||||
field_11_unused3 = data[pos + 35];
|
field_11_unused3 = data[pos + 35];
|
||||||
bytesRemaining -= 36;
|
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];
|
remainingData = new byte[bytesRemaining];
|
||||||
System.arraycopy( data, pos + 36, remainingData, 0, bytesRemaining );
|
System.arraycopy( data, pos, remainingData, 0, bytesRemaining );
|
||||||
return bytesRemaining + 8 + 36;
|
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 );
|
listener.beforeRecordSerialize( offset, getRecordId(), this );
|
||||||
|
|
||||||
|
if (remainingData == null)
|
||||||
|
remainingData = new byte[0];
|
||||||
|
|
||||||
LittleEndian.putShort( data, offset, getOptions() );
|
LittleEndian.putShort( data, offset, getOptions() );
|
||||||
LittleEndian.putShort( data, offset + 2, getRecordId() );
|
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 );
|
LittleEndian.putInt( data, offset + 4, remainingBytes );
|
||||||
|
|
||||||
data[offset + 8] = field_1_blipTypeWin32;
|
data[offset + 8] = field_1_blipTypeWin32;
|
||||||
|
@ -121,8 +146,15 @@ public class EscherBSERecord
|
||||||
data[offset + 41] = field_9_name;
|
data[offset + 41] = field_9_name;
|
||||||
data[offset + 42] = field_10_unused2;
|
data[offset + 42] = field_10_unused2;
|
||||||
data[offset + 43] = field_11_unused3;
|
data[offset + 43] = field_11_unused3;
|
||||||
System.arraycopy( remainingData, 0, data, offset + 44, remainingData.length );
|
int bytesWritten = 0;
|
||||||
int pos = offset + 8 + 36 + remainingData.length;
|
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);
|
listener.afterRecordSerialize(pos, getRecordId(), pos - offset, this);
|
||||||
return pos - offset;
|
return pos - offset;
|
||||||
|
@ -135,7 +167,7 @@ public class EscherBSERecord
|
||||||
*/
|
*/
|
||||||
public int getRecordSize()
|
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;
|
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.
|
* Any remaining data in this record.
|
||||||
*/
|
*/
|
||||||
|
@ -360,9 +402,8 @@ public class EscherBSERecord
|
||||||
" Name: " + field_9_name + nl +
|
" Name: " + field_9_name + nl +
|
||||||
" Unused2: " + field_10_unused2 + nl +
|
" Unused2: " + field_10_unused2 + nl +
|
||||||
" Unused3: " + field_11_unused3 + nl +
|
" Unused3: " + field_11_unused3 + nl +
|
||||||
|
" blipRecord: " + field_12_blipRecord + nl +
|
||||||
" Extra Data:" + nl + extraData;
|
" Extra Data:" + nl + extraData;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,24 +17,14 @@
|
||||||
|
|
||||||
package org.apache.poi.ddf;
|
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.LittleEndian;
|
||||||
|
import org.apache.poi.util.HexDump;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
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
|
* @author Glen Stampoultzis
|
||||||
* @see java.util.zip.Inflater
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class EscherBlipRecord
|
public class EscherBlipRecord
|
||||||
extends EscherRecord
|
extends EscherRecord
|
||||||
|
@ -42,21 +32,14 @@ public class EscherBlipRecord
|
||||||
public static final short RECORD_ID_START = (short) 0xF018;
|
public static final short RECORD_ID_START = (short) 0xF018;
|
||||||
public static final short RECORD_ID_END = (short) 0xF117;
|
public static final short RECORD_ID_END = (short) 0xF117;
|
||||||
public static final String RECORD_DESCRIPTION = "msofbtBlip";
|
public static final String RECORD_DESCRIPTION = "msofbtBlip";
|
||||||
|
|
||||||
private static final int HEADER_SIZE = 8;
|
private static final int HEADER_SIZE = 8;
|
||||||
|
|
||||||
private byte[] field_1_secondaryUID;
|
protected byte[] field_pictureData;
|
||||||
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;
|
|
||||||
|
|
||||||
|
public EscherBlipRecord()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method deserializes the record from a byte array.
|
* 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.
|
* @param recordFactory May be null since this is not a container record.
|
||||||
* @return The number of bytes read from the byte array.
|
* @return The number of bytes read from the byte array.
|
||||||
*/
|
*/
|
||||||
public int fillFields( byte[] data, int offset,
|
public int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory )
|
||||||
EscherRecordFactory recordFactory
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
int bytesAfterHeader = readHeader( data, offset );
|
int bytesAfterHeader = readHeader( data, offset );
|
||||||
int pos = offset + HEADER_SIZE;
|
int pos = offset + HEADER_SIZE;
|
||||||
|
|
||||||
int size = 0;
|
field_pictureData = new byte[bytesAfterHeader];
|
||||||
field_1_secondaryUID = new byte[16];
|
System.arraycopy(data, pos, field_pictureData, 0, bytesAfterHeader);
|
||||||
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;
|
return bytesAfterHeader + 8;
|
||||||
field_12_data = new byte[bytesRemaining];
|
|
||||||
System.arraycopy(data, pos + size, field_12_data, 0, bytesRemaining);
|
|
||||||
|
|
||||||
return bytesRemaining + HEADER_SIZE + bytesAfterHeader;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 offset the offset within the byte array
|
||||||
* @param data The byte array to serialize to.
|
* @param data the data array to serialize to
|
||||||
* @param listener A listener to retrieve start and end callbacks. Use a <code>NullEscherSerailizationListener</code> to ignore these events.
|
* @param listener a listener for begin and end serialization events. This
|
||||||
* @return The number of bytes written.
|
* is useful because the serialization is
|
||||||
*
|
* hierarchical/recursive and sometimes you need to be able
|
||||||
* @see NullEscherSerializationListener
|
* break into that.
|
||||||
|
* @return the number of bytes written.
|
||||||
*/
|
*/
|
||||||
public int serialize( int offset, byte[] data, EscherSerializationListener listener )
|
public int serialize( int offset, byte[] data, EscherSerializationListener listener )
|
||||||
{
|
{
|
||||||
|
@ -111,25 +77,11 @@ public class EscherBlipRecord
|
||||||
|
|
||||||
LittleEndian.putShort( data, offset, getOptions() );
|
LittleEndian.putShort( data, offset, getOptions() );
|
||||||
LittleEndian.putShort( data, offset + 2, getRecordId() );
|
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_pictureData, 0, data, offset + 4, field_pictureData.length );
|
||||||
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);
|
listener.afterRecordSerialize(offset + 4 + field_pictureData.length, getRecordId(), field_pictureData.length + 4, this);
|
||||||
return pos - offset;
|
return field_pictureData.length + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,7 +91,7 @@ public class EscherBlipRecord
|
||||||
*/
|
*/
|
||||||
public int getRecordSize()
|
public int getRecordSize()
|
||||||
{
|
{
|
||||||
return 58 + field_12_data.length;
|
return field_pictureData.length + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,203 +102,6 @@ public class EscherBlipRecord
|
||||||
return "Blip";
|
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()
|
public String toString()
|
||||||
{
|
{
|
||||||
String nl = System.getProperty( "line.separator" );
|
String nl = System.getProperty( "line.separator" );
|
||||||
|
@ -355,7 +110,7 @@ public class EscherBlipRecord
|
||||||
ByteArrayOutputStream b = new ByteArrayOutputStream();
|
ByteArrayOutputStream b = new ByteArrayOutputStream();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HexDump.dump( this.field_12_data, 0, b, 0 );
|
HexDump.dump( this.field_pictureData, 0, b, 0 );
|
||||||
extraData = b.toString();
|
extraData = b.toString();
|
||||||
}
|
}
|
||||||
catch ( Exception e )
|
catch ( Exception e )
|
||||||
|
@ -365,70 +120,7 @@ public class EscherBlipRecord
|
||||||
return getClass().getName() + ":" + nl +
|
return getClass().getName() + ":" + nl +
|
||||||
" RecordId: 0x" + HexDump.toHex( getRecordId() ) + nl +
|
" RecordId: 0x" + HexDump.toHex( getRecordId() ) + nl +
|
||||||
" Options: 0x" + HexDump.toHex( getOptions() ) + nl +
|
" Options: 0x" + HexDump.toHex( getOptions() ) + nl +
|
||||||
" Secondary UID: " + HexDump.toHex( field_1_secondaryUID ) + nl +
|
" Extra Data:" + nl + extraData;
|
||||||
" 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* 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
|
* @param value The 32 bit value of this bool property
|
||||||
*/
|
*/
|
||||||
public EscherBoolProperty( short propertyNumber, int value )
|
public EscherBoolProperty( short propertyNumber, int value )
|
||||||
{
|
{
|
||||||
super( propertyNumber, false, false, value );
|
super(propertyNumber, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -154,7 +154,7 @@ public class EscherClientAnchorRecord
|
||||||
}
|
}
|
||||||
catch ( Exception e )
|
catch ( Exception e )
|
||||||
{
|
{
|
||||||
extraData = "error";
|
extraData = "error\n";
|
||||||
}
|
}
|
||||||
return getClass().getName() + ":" + nl +
|
return getClass().getName() + ":" + nl +
|
||||||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + nl +
|
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + nl +
|
||||||
|
|
|
@ -119,7 +119,7 @@ public class EscherClientDataRecord
|
||||||
}
|
}
|
||||||
catch ( Exception e )
|
catch ( Exception e )
|
||||||
{
|
{
|
||||||
extraData = "error";
|
extraData = "error\n";
|
||||||
}
|
}
|
||||||
return getClass().getName() + ":" + nl +
|
return getClass().getName() + ":" + nl +
|
||||||
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + nl +
|
" RecordId: 0x" + HexDump.toHex(RECORD_ID) + nl +
|
||||||
|
|
|
@ -17,11 +17,10 @@
|
||||||
|
|
||||||
package org.apache.poi.ddf;
|
package org.apache.poi.ddf;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.record.RecordFormatException;
|
||||||
import org.apache.poi.util.HexDump;
|
import org.apache.poi.util.HexDump;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.hssf.record.RecordFormatException;
|
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -83,8 +82,8 @@ public class EscherDggRecord
|
||||||
int field_2_numIdClusters = LittleEndian.getInt( data, pos + size );size+=4;
|
int field_2_numIdClusters = LittleEndian.getInt( data, pos + size );size+=4;
|
||||||
field_3_numShapesSaved = 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_4_drawingsSaved = LittleEndian.getInt( data, pos + size );size+=4;
|
||||||
field_5_fileIdClusters = new FileIdCluster[field_2_numIdClusters-1];
|
field_5_fileIdClusters = new FileIdCluster[(bytesRemaining-size) / 8]; // Can't rely on field_2_numIdClusters
|
||||||
for (int i = 0; i < field_2_numIdClusters-1; i++)
|
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 ));
|
field_5_fileIdClusters[i] = new FileIdCluster(LittleEndian.getInt( data, pos + size ), LittleEndian.getInt( data, pos + size + 4 ));
|
||||||
size += 8;
|
size += 8;
|
||||||
|
@ -114,6 +113,7 @@ public class EscherDggRecord
|
||||||
LittleEndian.putShort( data, pos, getRecordId() ); pos += 2;
|
LittleEndian.putShort( data, pos, getRecordId() ); pos += 2;
|
||||||
int remainingBytes = getRecordSize() - 8;
|
int remainingBytes = getRecordSize() - 8;
|
||||||
LittleEndian.putInt( data, pos, remainingBytes ); pos += 4;
|
LittleEndian.putInt( data, pos, remainingBytes ); pos += 4;
|
||||||
|
|
||||||
LittleEndian.putInt( data, pos, field_1_shapeIdMax ); pos += 4;
|
LittleEndian.putInt( data, pos, field_1_shapeIdMax ); pos += 4;
|
||||||
LittleEndian.putInt( data, pos, getNumIdClusters() ); pos += 4;
|
LittleEndian.putInt( data, pos, getNumIdClusters() ); pos += 4;
|
||||||
LittleEndian.putInt( data, pos, field_3_numShapesSaved ); 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;
|
this.field_1_shapeIdMax = field_1_shapeIdMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of id clusters + 1
|
||||||
|
*/
|
||||||
public int getNumIdClusters()
|
public int getNumIdClusters()
|
||||||
{
|
{
|
||||||
return field_5_fileIdClusters.length + 1;
|
return field_5_fileIdClusters.length + 1;
|
||||||
|
|
|
@ -26,7 +26,7 @@ package org.apache.poi.ddf;
|
||||||
*/
|
*/
|
||||||
abstract public class EscherProperty
|
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
|
* 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;
|
package org.apache.poi.ddf;
|
||||||
|
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.hssf.record.RecordFormatException;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a property given a reference into the byte array storing that property.
|
* Generates a property given a reference into the byte array storing that property.
|
||||||
|
@ -43,7 +42,7 @@ public class EscherPropertyFactory
|
||||||
List results = new ArrayList();
|
List results = new ArrayList();
|
||||||
|
|
||||||
int pos = offset;
|
int pos = offset;
|
||||||
int complexBytes = 0;
|
|
||||||
// while ( bytesRemaining >= 6 )
|
// while ( bytesRemaining >= 6 )
|
||||||
for (int i = 0; i < numProperties; i++)
|
for (int i = 0; i < numProperties; i++)
|
||||||
{
|
{
|
||||||
|
@ -54,21 +53,18 @@ public class EscherPropertyFactory
|
||||||
short propNumber = (short) ( propId & (short) 0x3FFF );
|
short propNumber = (short) ( propId & (short) 0x3FFF );
|
||||||
boolean isComplex = ( propId & (short) 0x8000 ) != 0;
|
boolean isComplex = ( propId & (short) 0x8000 ) != 0;
|
||||||
boolean isBlipId = ( propId & (short) 0x4000 ) != 0;
|
boolean isBlipId = ( propId & (short) 0x4000 ) != 0;
|
||||||
if ( isComplex )
|
|
||||||
complexBytes = propData;
|
|
||||||
else
|
|
||||||
complexBytes = 0;
|
|
||||||
byte propertyType = EscherProperties.getPropertyType( (short) propNumber );
|
byte propertyType = EscherProperties.getPropertyType( (short) propNumber );
|
||||||
if ( propertyType == EscherPropertyMetaData.TYPE_BOOLEAN )
|
if ( propertyType == EscherPropertyMetaData.TYPE_BOOLEAN )
|
||||||
results.add( new EscherBoolProperty( propNumber, propData ) );
|
results.add( new EscherBoolProperty( propId, propData ) );
|
||||||
else if ( propertyType == EscherPropertyMetaData.TYPE_RGB )
|
else if ( propertyType == EscherPropertyMetaData.TYPE_RGB )
|
||||||
results.add( new EscherRGBProperty( propNumber, propData ) );
|
results.add( new EscherRGBProperty( propId, propData ) );
|
||||||
else if ( propertyType == EscherPropertyMetaData.TYPE_SHAPEPATH )
|
else if ( propertyType == EscherPropertyMetaData.TYPE_SHAPEPATH )
|
||||||
results.add( new EscherShapePathProperty( propNumber, propData ) );
|
results.add( new EscherShapePathProperty( propId, propData ) );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( !isComplex )
|
if ( !isComplex )
|
||||||
results.add( new EscherSimpleProperty( propNumber, propData ) );
|
results.add( new EscherSimpleProperty( propId, propData ) );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( propertyType == EscherPropertyMetaData.TYPE_ARRAY)
|
if ( propertyType == EscherPropertyMetaData.TYPE_ARRAY)
|
||||||
|
|
|
@ -28,7 +28,7 @@ public class EscherRGBProperty
|
||||||
|
|
||||||
public EscherRGBProperty( short propertyNumber, int rgbColor )
|
public EscherRGBProperty( short propertyNumber, int rgbColor )
|
||||||
{
|
{
|
||||||
super( propertyNumber, false, false, rgbColor );
|
super( propertyNumber, rgbColor );
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRgbColor()
|
public int getRgbColor()
|
||||||
|
|
|
@ -111,6 +111,7 @@ public class EscherSimpleProperty extends EscherProperty
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return "propNum: " + getPropertyNumber()
|
return "propNum: " + getPropertyNumber()
|
||||||
|
+ ", RAW: 0x" + HexDump.toHex( getId() )
|
||||||
+ ", propName: " + EscherProperties.getPropertyName( getPropertyNumber() )
|
+ ", propName: " + EscherProperties.getPropertyName( getPropertyNumber() )
|
||||||
+ ", complex: " + isComplex()
|
+ ", complex: " + isComplex()
|
||||||
+ ", blipId: " + isBlipId()
|
+ ", blipId: " + isBlipId()
|
||||||
|
|
|
@ -112,6 +112,23 @@ public class BiffViewer {
|
||||||
in.read(data);
|
in.read(data);
|
||||||
loc += recsize;
|
loc += recsize;
|
||||||
Record record = createRecord(rectype, recsize, data );
|
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)
|
if (record.getSid() != ContinueRecord.sid)
|
||||||
{
|
{
|
||||||
records.add(record);
|
records.add(record);
|
||||||
|
@ -178,7 +195,6 @@ public class BiffViewer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void dumpUnknownRecord(byte[] data) throws IOException {
|
private static void dumpUnknownRecord(byte[] data) throws IOException {
|
||||||
// record hex dump it!
|
// record hex dump it!
|
||||||
System.out.println(
|
System.out.println(
|
||||||
|
@ -630,29 +646,40 @@ public class BiffViewer {
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
try {
|
try {
|
||||||
BiffViewer viewer = new BiffViewer(args);
|
System.setProperty("poi.deserialize.escher", "true");
|
||||||
|
|
||||||
if ((args.length > 1) && args[1].equals("on")) {
|
if (args.length == 0)
|
||||||
viewer.setDump(true);
|
{
|
||||||
|
System.out.println( "Biff viewer needs a filename" );
|
||||||
}
|
}
|
||||||
if ((args.length > 1) && args[1].equals("bfd")) {
|
else
|
||||||
POIFSFileSystem fs =
|
{
|
||||||
new POIFSFileSystem(new FileInputStream(args[0]));
|
BiffViewer viewer = new BiffViewer(args);
|
||||||
InputStream stream =
|
if ((args.length > 1) && args[1].equals("on")) {
|
||||||
fs.createDocumentInputStream("Workbook");
|
viewer.setDump(true);
|
||||||
int size = stream.available();
|
}
|
||||||
byte[] data = new byte[size];
|
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);
|
stream.read(data);
|
||||||
HexDump.dump(data, 0, System.out, 0);
|
HexDump.dump(data, 0, System.out, 0);
|
||||||
} else {
|
} else {
|
||||||
viewer.run();
|
viewer.run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This record supports dumping of completed continue records.
|
||||||
|
*/
|
||||||
static class RecordDetails
|
static class RecordDetails
|
||||||
{
|
{
|
||||||
short rectype, recsize;
|
short rectype, recsize;
|
||||||
|
|
|
@ -34,7 +34,7 @@ public abstract class AbstractShape
|
||||||
*/
|
*/
|
||||||
public static AbstractShape createShape( HSSFShape hssfShape, int shapeId )
|
public static AbstractShape createShape( HSSFShape hssfShape, int shapeId )
|
||||||
{
|
{
|
||||||
AbstractShape shape = null;
|
AbstractShape shape;
|
||||||
if (hssfShape instanceof HSSFTextbox)
|
if (hssfShape instanceof HSSFTextbox)
|
||||||
{
|
{
|
||||||
shape = new TextboxShape( (HSSFTextbox)hssfShape, shapeId );
|
shape = new TextboxShape( (HSSFTextbox)hssfShape, shapeId );
|
||||||
|
@ -48,6 +48,9 @@ public abstract class AbstractShape
|
||||||
HSSFSimpleShape simpleShape = (HSSFSimpleShape) hssfShape;
|
HSSFSimpleShape simpleShape = (HSSFSimpleShape) hssfShape;
|
||||||
switch ( simpleShape.getShapeType() )
|
switch ( simpleShape.getShapeType() )
|
||||||
{
|
{
|
||||||
|
case HSSFSimpleShape.OBJECT_TYPE_PICTURE:
|
||||||
|
shape = new PictureShape( simpleShape, shapeId );
|
||||||
|
break;
|
||||||
case HSSFSimpleShape.OBJECT_TYPE_LINE:
|
case HSSFSimpleShape.OBJECT_TYPE_LINE:
|
||||||
shape = new LineShape( simpleShape, shapeId );
|
shape = new LineShape( simpleShape, shapeId );
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class ConvertAnchor
|
||||||
EscherClientAnchorRecord anchor = new EscherClientAnchorRecord();
|
EscherClientAnchorRecord anchor = new EscherClientAnchorRecord();
|
||||||
anchor.setRecordId( EscherClientAnchorRecord.RECORD_ID );
|
anchor.setRecordId( EscherClientAnchorRecord.RECORD_ID );
|
||||||
anchor.setOptions( (short) 0x0000 );
|
anchor.setOptions( (short) 0x0000 );
|
||||||
anchor.setFlag( (short) 0 );
|
anchor.setFlag( (short) a.getAnchorType() );
|
||||||
anchor.setCol1( (short) Math.min(a.getCol1(), a.getCol2()) );
|
anchor.setCol1( (short) Math.min(a.getCol1(), a.getCol2()) );
|
||||||
anchor.setDx1( (short) Math.min(a.getDx1(), a.getDx2()) );
|
anchor.setDx1( (short) Math.min(a.getDx1(), a.getDx2()) );
|
||||||
anchor.setRow1( (short) Math.min(a.getRow1(), a.getRow2()) );
|
anchor.setRow1( (short) Math.min(a.getRow1(), a.getRow2()) );
|
||||||
|
|
|
@ -19,17 +19,17 @@
|
||||||
package org.apache.poi.hssf.model;
|
package org.apache.poi.hssf.model;
|
||||||
|
|
||||||
import org.apache.poi.hssf.record.*;
|
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.FormulaRecordAggregate;
|
||||||
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
|
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
|
||||||
import org.apache.poi.hssf.record.aggregates.ValueRecordsAggregate;
|
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.hssf.record.formula.Ptg;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
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)
|
* 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 ))
|
if (log.check( POILogger.DEBUG ))
|
||||||
|
@ -2023,9 +2043,9 @@ public class Sheet implements Model
|
||||||
{
|
{
|
||||||
int retval = 0;
|
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
|
//Add space for the IndexRecord
|
||||||
if (rows != null) {
|
if (rows != null) {
|
||||||
|
@ -2430,7 +2450,7 @@ public class Sheet implements Model
|
||||||
return margins;
|
return margins;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int aggregateDrawingRecords(DrawingManager drawingManager)
|
public int aggregateDrawingRecords(DrawingManager2 drawingManager)
|
||||||
{
|
{
|
||||||
int loc = findFirstRecordLocBySid(DrawingRecord.sid);
|
int loc = findFirstRecordLocBySid(DrawingRecord.sid);
|
||||||
boolean noDrawingRecordsFound = loc == -1;
|
boolean noDrawingRecordsFound = loc == -1;
|
||||||
|
|
|
@ -29,7 +29,6 @@ import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Low level model implementation of a Workbook. Provides creational methods
|
* 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
|
protected int numfonts = 0; // hold the number of font records
|
||||||
private short maxformatid = -1; // holds the max format id
|
private short maxformatid = -1; // holds the max format id
|
||||||
private boolean uses1904datewindowing = false; // whether 1904 date windowing is being used
|
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);
|
private static POILogger log = POILogFactory.getLogger(Workbook.class);
|
||||||
|
|
||||||
|
@ -748,7 +748,12 @@ public class Workbook implements Model
|
||||||
{
|
{
|
||||||
record = sst.createExtSSTRecord(sstPos + offset);
|
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 ))
|
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
|
* Creates a drawing group record. If it already exists then it's modified.
|
||||||
* alone.
|
|
||||||
*/
|
*/
|
||||||
public void createDrawingGroup()
|
public void createDrawingGroup()
|
||||||
{
|
{
|
||||||
int dggLoc = findFirstRecordLocBySid(EscherContainerRecord.DGG_CONTAINER);
|
|
||||||
if (dggLoc == -1)
|
if (drawingManager == null)
|
||||||
{
|
{
|
||||||
EscherContainerRecord dggContainer = new EscherContainerRecord();
|
EscherContainerRecord dggContainer = new EscherContainerRecord();
|
||||||
EscherDggRecord dgg = new EscherDggRecord();
|
EscherDggRecord dgg = new EscherDggRecord();
|
||||||
|
@ -2125,11 +2129,23 @@ public class Workbook implements Model
|
||||||
dgg.setNumShapesSaved(0);
|
dgg.setNumShapesSaved(0);
|
||||||
dgg.setDrawingsSaved(0);
|
dgg.setDrawingsSaved(0);
|
||||||
dgg.setFileIdClusters(new EscherDggRecord.FileIdCluster[] {} );
|
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.setRecordId((short) 0xF00B);
|
||||||
opt.setOptions((short) 0x0033);
|
opt.setOptions((short) 0x0033);
|
||||||
opt.addEscherProperty( new EscherBoolProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 524296) );
|
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) );
|
opt.addEscherProperty( new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, 134217792) );
|
||||||
splitMenuColors.setRecordId((short) 0xF11E);
|
splitMenuColors.setRecordId((short) 0xF11E);
|
||||||
splitMenuColors.setOptions((short) 0x0040);
|
splitMenuColors.setOptions((short) 0x0040);
|
||||||
|
@ -2139,17 +2155,61 @@ public class Workbook implements Model
|
||||||
splitMenuColors.setColor4(0x100000F7);
|
splitMenuColors.setColor4(0x100000F7);
|
||||||
|
|
||||||
dggContainer.addChildRecord(dgg);
|
dggContainer.addChildRecord(dgg);
|
||||||
|
if (bstoreContainer != null)
|
||||||
|
dggContainer.addChildRecord( bstoreContainer );
|
||||||
dggContainer.addChildRecord(opt);
|
dggContainer.addChildRecord(opt);
|
||||||
dggContainer.addChildRecord(splitMenuColors);
|
dggContainer.addChildRecord(splitMenuColors);
|
||||||
|
|
||||||
DrawingGroupRecord drawingGroup = new DrawingGroupRecord();
|
int dgLoc = findFirstRecordLocBySid(DrawingGroupRecord.sid);
|
||||||
drawingGroup.addEscherRecord(dggContainer);
|
if (dgLoc == -1)
|
||||||
int loc = findFirstRecordLocBySid(CountryRecord.sid);
|
{
|
||||||
getRecords().add(loc+1, drawingGroup);
|
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;
|
return drawingManager;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ public abstract class AbstractEscherHolderRecord
|
||||||
{
|
{
|
||||||
if (id != getSid())
|
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
|
else
|
||||||
{
|
{
|
||||||
EscherRecordFactory recordFactory = new DefaultEscherRecordFactory();
|
convertToEscherRecords( offset, size, data );
|
||||||
int pos = offset;
|
}
|
||||||
while ( pos < offset + size )
|
}
|
||||||
{
|
|
||||||
EscherRecord r = recordFactory.createRecord(data, pos);
|
private void convertToEscherRecords( int offset, int size, byte[] data )
|
||||||
int bytesRead = r.fillFields(data, pos, recordFactory );
|
{
|
||||||
escherRecords.add(r);
|
EscherRecordFactory recordFactory = new DefaultEscherRecordFactory();
|
||||||
pos += bytesRead;
|
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");
|
final String nl = System.getProperty("line.separator");
|
||||||
buffer.append('[' + getRecordName() + ']' + nl);
|
buffer.append('[' + getRecordName() + ']' + nl);
|
||||||
|
if (escherRecords.size() == 0)
|
||||||
|
buffer.append("No Escher Records Decoded" + nl);
|
||||||
for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
|
for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
|
||||||
{
|
{
|
||||||
EscherRecord r = (EscherRecord) iterator.next();
|
EscherRecord r = (EscherRecord) iterator.next();
|
||||||
|
@ -138,10 +145,16 @@ public abstract class AbstractEscherHolderRecord
|
||||||
LittleEndian.putShort( data, 2 + offset, (short) ( getRecordSize() - 4 ) );
|
LittleEndian.putShort( data, 2 + offset, (short) ( getRecordSize() - 4 ) );
|
||||||
if ( escherRecords.size() == 0 && rawData != null )
|
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
|
else
|
||||||
{
|
{
|
||||||
|
LittleEndian.putShort(data, 0 + offset, getSid());
|
||||||
|
LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
|
||||||
|
|
||||||
int pos = offset + 4;
|
int pos = offset + 4;
|
||||||
for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
|
for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
|
||||||
{
|
{
|
||||||
|
@ -255,6 +268,45 @@ public abstract class AbstractEscherHolderRecord
|
||||||
return (EscherRecord) escherRecords.get(index);
|
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
|
} // END OF CLASS
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,22 @@
|
||||||
|
|
||||||
package org.apache.poi.hssf.record;
|
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 class DrawingGroupRecord extends AbstractEscherHolderRecord
|
||||||
{
|
{
|
||||||
public static final short sid = 0xEB;
|
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()
|
public DrawingGroupRecord()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -43,4 +55,92 @@ public class DrawingGroupRecord extends AbstractEscherHolderRecord
|
||||||
{
|
{
|
||||||
return sid;
|
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;
|
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 )
|
public int serialize( int offset, byte[] data )
|
||||||
{
|
{
|
||||||
if (recordData == null)
|
if (recordData == null)
|
||||||
|
|
|
@ -20,7 +20,7 @@ import org.apache.poi.ddf.*;
|
||||||
import org.apache.poi.hssf.usermodel.*;
|
import org.apache.poi.hssf.usermodel.*;
|
||||||
import org.apache.poi.hssf.model.AbstractShape;
|
import org.apache.poi.hssf.model.AbstractShape;
|
||||||
import org.apache.poi.hssf.model.TextboxShape;
|
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 org.apache.poi.hssf.model.ConvertAnchor;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -256,10 +256,10 @@ public class EscherAggregate extends AbstractEscherHolderRecord
|
||||||
|
|
||||||
/** Maps shape container objects to their OBJ records */
|
/** Maps shape container objects to their OBJ records */
|
||||||
private Map shapeToObj = new HashMap();
|
private Map shapeToObj = new HashMap();
|
||||||
private DrawingManager drawingManager;
|
private DrawingManager2 drawingManager;
|
||||||
private short drawingGroupId;
|
private short drawingGroupId;
|
||||||
|
|
||||||
public EscherAggregate( DrawingManager drawingManager )
|
public EscherAggregate( DrawingManager2 drawingManager )
|
||||||
{
|
{
|
||||||
this.drawingManager = drawingManager;
|
this.drawingManager = drawingManager;
|
||||||
}
|
}
|
||||||
|
@ -305,7 +305,7 @@ public class EscherAggregate extends AbstractEscherHolderRecord
|
||||||
/**
|
/**
|
||||||
* Collapses the drawing records into an aggregate.
|
* 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.
|
// 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.
|
// Textbox objects are also treated as shape objects.
|
||||||
|
@ -571,6 +571,9 @@ public class EscherAggregate extends AbstractEscherHolderRecord
|
||||||
escherParent.addChildRecord( shapeModel.getSpContainer() );
|
escherParent.addChildRecord( shapeModel.getSpContainer() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// drawingManager.newCluster( (short)1 );
|
||||||
|
// drawingManager.newCluster( (short)2 );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void convertGroup( HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj )
|
private void convertGroup( HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj )
|
||||||
|
@ -678,7 +681,7 @@ public class EscherAggregate extends AbstractEscherHolderRecord
|
||||||
spContainer1.setRecordId( EscherContainerRecord.SP_CONTAINER );
|
spContainer1.setRecordId( EscherContainerRecord.SP_CONTAINER );
|
||||||
spContainer1.setOptions( (short) 0x000F );
|
spContainer1.setOptions( (short) 0x000F );
|
||||||
spgr.setRecordId( EscherSpgrRecord.RECORD_ID );
|
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.setRectX1( patriarch.getX1() );
|
||||||
spgr.setRectY1( patriarch.getY1() );
|
spgr.setRectY1( patriarch.getY1() );
|
||||||
spgr.setRectX2( patriarch.getX2() );
|
spgr.setRectX2( patriarch.getX2() );
|
||||||
|
|
|
@ -173,6 +173,14 @@ public class ObjRecord
|
||||||
return subrecords.add( o );
|
return subrecords.add( o );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// made public to satisfy biffviewer
|
||||||
|
|
||||||
|
/* protected */
|
||||||
|
public void processContinueRecord( byte[] record )
|
||||||
|
{
|
||||||
|
super.processContinueRecord( record );
|
||||||
|
}
|
||||||
|
|
||||||
public Object clone()
|
public Object clone()
|
||||||
{
|
{
|
||||||
ObjRecord rec = new ObjRecord();
|
ObjRecord rec = new ObjRecord();
|
||||||
|
|
|
@ -148,6 +148,7 @@ public class RecordFactory
|
||||||
{
|
{
|
||||||
short rectype = 0;
|
short rectype = 0;
|
||||||
|
|
||||||
|
DrawingRecord lastDrawingRecord = new DrawingRecord( );
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
rectype = LittleEndian.readShort(in);
|
rectype = LittleEndian.readShort(in);
|
||||||
|
@ -176,7 +177,13 @@ public class RecordFactory
|
||||||
|
|
||||||
if (record != null)
|
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 ContinueRecord) && // include continuation records after
|
||||||
! (last_record instanceof UnknownRecord) ) // unknown records or previous continuation records
|
! (last_record instanceof UnknownRecord) ) // unknown records or previous continuation records
|
||||||
{
|
{
|
||||||
|
@ -185,11 +192,18 @@ public class RecordFactory
|
||||||
throw new RecordFormatException(
|
throw new RecordFormatException(
|
||||||
"First record is a ContinueRecord??");
|
"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
|
else
|
||||||
{
|
{
|
||||||
last_record = record;
|
last_record = record;
|
||||||
|
if (record instanceof DrawingRecord)
|
||||||
|
lastDrawingRecord = (DrawingRecord) record;
|
||||||
records.add(record);
|
records.add(record);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import java.util.List;
|
||||||
public class ColumnInfoRecordsAggregate
|
public class ColumnInfoRecordsAggregate
|
||||||
extends Record
|
extends Record
|
||||||
{
|
{
|
||||||
int size = 0;
|
// int size = 0;
|
||||||
List records = null;
|
List records = null;
|
||||||
|
|
||||||
public ColumnInfoRecordsAggregate()
|
public ColumnInfoRecordsAggregate()
|
||||||
|
@ -40,6 +40,9 @@ public class ColumnInfoRecordsAggregate
|
||||||
|
|
||||||
public int getRecordSize()
|
public int getRecordSize()
|
||||||
{
|
{
|
||||||
|
int size = 0;
|
||||||
|
for ( Iterator iterator = records.iterator(); iterator.hasNext(); )
|
||||||
|
size += ( (ColumnInfoRecord) iterator.next() ).getRecordSize();
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +71,6 @@ public class ColumnInfoRecordsAggregate
|
||||||
*/
|
*/
|
||||||
public void insertColumn( ColumnInfoRecord col )
|
public void insertColumn( ColumnInfoRecord col )
|
||||||
{
|
{
|
||||||
size += col.getRecordSize();
|
|
||||||
records.add( col );
|
records.add( col );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +80,6 @@ public class ColumnInfoRecordsAggregate
|
||||||
*/
|
*/
|
||||||
public void insertColumn( int idx, ColumnInfoRecord col )
|
public void insertColumn( int idx, ColumnInfoRecord col )
|
||||||
{
|
{
|
||||||
size += col.getRecordSize();
|
|
||||||
records.add( idx, col );
|
records.add( idx, col );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -228,7 +228,7 @@ public class RowRecordsAggregate
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* called by the constructor, should set class level fields. Should throw
|
* 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 data raw data
|
||||||
* @param size size of data
|
* @param size size of data
|
||||||
|
|
|
@ -16,8 +16,7 @@
|
||||||
|
|
||||||
package org.apache.poi.hssf.usermodel;
|
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;
|
int row1;
|
||||||
short col2;
|
short col2;
|
||||||
int row2;
|
int row2;
|
||||||
|
int anchorType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new client anchor and defaults all the anchor positions to 0.
|
* Creates a new client anchor and defaults all the anchor positions to 0.
|
||||||
|
@ -213,6 +213,26 @@ public class HSSFClientAnchor
|
||||||
return row1 > row2;
|
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 )
|
private void checkRange( int value, int minRange, int maxRange, String varName )
|
||||||
{
|
{
|
||||||
if (value < minRange || value > maxRange)
|
if (value < minRange || value > maxRange)
|
||||||
|
|
|
@ -77,6 +77,23 @@ public class HSSFPatriarch
|
||||||
return shape;
|
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
|
* Creates a polygon
|
||||||
*
|
*
|
||||||
|
|
|
@ -1220,19 +1220,22 @@ public class HSSFSheet
|
||||||
* Aggregates the drawing records and dumps the escher record hierarchy
|
* Aggregates the drawing records and dumps the escher record hierarchy
|
||||||
* to the standard output.
|
* to the standard output.
|
||||||
*/
|
*/
|
||||||
public void dumpDrawingRecords()
|
public void dumpDrawingRecords(boolean fat)
|
||||||
{
|
{
|
||||||
sheet.aggregateDrawingRecords(book.getDrawingManager());
|
sheet.aggregateDrawingRecords(book.getDrawingManager());
|
||||||
|
|
||||||
EscherAggregate r = (EscherAggregate) getSheet().findFirstRecordBySid(EscherAggregate.sid);
|
EscherAggregate r = (EscherAggregate) getSheet().findFirstRecordBySid(EscherAggregate.sid);
|
||||||
List escherRecords = r.getEscherRecords();
|
List escherRecords = r.getEscherRecords();
|
||||||
|
PrintWriter w = new PrintWriter(System.out);
|
||||||
for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
|
for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
|
||||||
{
|
{
|
||||||
EscherRecord escherRecord = (EscherRecord) iterator.next();
|
EscherRecord escherRecord = (EscherRecord) iterator.next();
|
||||||
PrintWriter w = new PrintWriter(System.out);
|
if (fat)
|
||||||
escherRecord.display(w, 0);
|
System.out.println(escherRecord.toString());
|
||||||
w.close();
|
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_CHART = 5;
|
||||||
// public final static short OBJECT_TYPE_TEXT = 6;
|
// public final static short OBJECT_TYPE_TEXT = 6;
|
||||||
// public final static short OBJECT_TYPE_BUTTON = 7;
|
// 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_POLYGON = 9;
|
||||||
// public final static short OBJECT_TYPE_CHECKBOX = 11;
|
// public final static short OBJECT_TYPE_CHECKBOX = 11;
|
||||||
// public final static short OBJECT_TYPE_OPTION_BUTTON = 12;
|
// public final static short OBJECT_TYPE_OPTION_BUTTON = 12;
|
||||||
|
@ -63,6 +63,7 @@ public class HSSFSimpleShape
|
||||||
* @see #OBJECT_TYPE_LINE
|
* @see #OBJECT_TYPE_LINE
|
||||||
* @see #OBJECT_TYPE_OVAL
|
* @see #OBJECT_TYPE_OVAL
|
||||||
* @see #OBJECT_TYPE_RECTANGLE
|
* @see #OBJECT_TYPE_RECTANGLE
|
||||||
|
* @see #OBJECT_TYPE_PICTURE
|
||||||
*/
|
*/
|
||||||
public int getShapeType() { return shapeType; }
|
public int getShapeType() { return shapeType; }
|
||||||
|
|
||||||
|
@ -74,6 +75,7 @@ public class HSSFSimpleShape
|
||||||
* @see #OBJECT_TYPE_LINE
|
* @see #OBJECT_TYPE_LINE
|
||||||
* @see #OBJECT_TYPE_OVAL
|
* @see #OBJECT_TYPE_OVAL
|
||||||
* @see #OBJECT_TYPE_RECTANGLE
|
* @see #OBJECT_TYPE_RECTANGLE
|
||||||
|
* @see #OBJECT_TYPE_PICTURE
|
||||||
*/
|
*/
|
||||||
public void setShapeType( int shapeType ){ this.shapeType = shapeType; }
|
public void setShapeType( int shapeType ){ this.shapeType = shapeType; }
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.poi.hssf.usermodel;
|
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.eventmodel.EventRecordFactory;
|
||||||
import org.apache.poi.hssf.model.Sheet;
|
import org.apache.poi.hssf.model.Sheet;
|
||||||
import org.apache.poi.hssf.model.Workbook;
|
import org.apache.poi.hssf.model.Workbook;
|
||||||
|
@ -38,6 +41,7 @@ import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -57,7 +61,6 @@ import java.util.Stack;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class HSSFWorkbook
|
public class HSSFWorkbook
|
||||||
extends java.lang.Object
|
|
||||||
{
|
{
|
||||||
private static final int DEBUG = POILogger.DEBUG;
|
private static final int DEBUG = POILogger.DEBUG;
|
||||||
|
|
||||||
|
@ -108,13 +111,31 @@ public class HSSFWorkbook
|
||||||
*/
|
*/
|
||||||
private HSSFDataFormat formatter;
|
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);
|
private static POILogger log = POILogFactory.getLogger(HSSFWorkbook.class);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new HSSFWorkbook from scratch (start here!)
|
* Creates new HSSFWorkbook from scratch (start here!)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public HSSFWorkbook()
|
public HSSFWorkbook()
|
||||||
{
|
{
|
||||||
this(Workbook.createWorkbook());
|
this(Workbook.createWorkbook());
|
||||||
|
@ -159,8 +180,6 @@ public class HSSFWorkbook
|
||||||
|
|
||||||
EventRecordFactory factory = new EventRecordFactory();
|
EventRecordFactory factory = new EventRecordFactory();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
List records = RecordFactory.createRecords(stream);
|
List records = RecordFactory.createRecords(stream);
|
||||||
|
|
||||||
workbook = Workbook.createWorkbook(records);
|
workbook = Workbook.createWorkbook(records);
|
||||||
|
@ -796,8 +815,9 @@ public class HSSFWorkbook
|
||||||
|
|
||||||
// byte[] sb = (byte[])sheetbytes.get(k);
|
// byte[] sb = (byte[])sheetbytes.get(k);
|
||||||
// System.arraycopy(sb, 0, retval, pos, sb.length);
|
// System.arraycopy(sb, 0, retval, pos, sb.length);
|
||||||
pos += ((HSSFSheet) sheets.get(k)).getSheet().serialize(pos,
|
int len = ((HSSFSheet) sheets.get(k)).getSheet().serialize(pos,
|
||||||
retval); // sb.length;
|
retval);
|
||||||
|
pos += len; // sb.length;
|
||||||
}
|
}
|
||||||
/* for (int k = pos; k < totalsize; k++)
|
/* for (int k = pos; k < totalsize; k++)
|
||||||
{
|
{
|
||||||
|
@ -1067,6 +1087,68 @@ public class HSSFWorkbook
|
||||||
workbook.getRecords().add(loc, r);
|
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;
|
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.HSSFSheet;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,7 +34,15 @@ public class DrawingDump
|
||||||
POIFSFileSystem fs =
|
POIFSFileSystem fs =
|
||||||
new POIFSFileSystem(new FileInputStream(args[0]));
|
new POIFSFileSystem(new FileInputStream(args[0]));
|
||||||
HSSFWorkbook wb = new HSSFWorkbook(fs);
|
HSSFWorkbook wb = new HSSFWorkbook(fs);
|
||||||
HSSFSheet sheet = wb.getSheetAt(0);
|
System.out.println( "Drawing group:" );
|
||||||
sheet.dumpDrawingRecords();
|
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)
|
if (data.length == 0)
|
||||||
{
|
{
|
||||||
stream.write( "No Data".getBytes() );
|
stream.write( ("No Data" + System.getProperty( "line.separator")).getBytes() );
|
||||||
stream.flush();
|
stream.flush();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,8 +98,9 @@ public class TestEscherBSERecord extends TestCase
|
||||||
" Name: 5" + nl +
|
" Name: 5" + nl +
|
||||||
" Unused2: 6" + nl +
|
" Unused2: 6" + nl +
|
||||||
" Unused3: 7" + nl +
|
" Unused3: 7" + nl +
|
||||||
|
" blipRecord: null" + nl +
|
||||||
" Extra Data:" + 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.HexDump;
|
||||||
import org.apache.poi.util.HexRead;
|
import org.apache.poi.util.HexRead;
|
||||||
|
|
||||||
public class TestEscherBlipRecord extends TestCase
|
public class TestEscherBlipWMFRecord extends TestCase
|
||||||
{
|
{
|
||||||
private String dataStr;
|
private String dataStr;
|
||||||
private byte[] data;
|
private byte[] data;
|
||||||
|
@ -37,7 +37,7 @@ public class TestEscherBlipRecord extends TestCase
|
||||||
|
|
||||||
public void testSerialize() throws Exception
|
public void testSerialize() throws Exception
|
||||||
{
|
{
|
||||||
EscherBlipRecord r = new EscherBlipRecord();
|
EscherBlipWMFRecord r = new EscherBlipWMFRecord();
|
||||||
r.setBoundaryLeft(1);
|
r.setBoundaryLeft(1);
|
||||||
r.setBoundaryHeight(2);
|
r.setBoundaryHeight(2);
|
||||||
r.setBoundaryTop(3);
|
r.setBoundaryTop(3);
|
||||||
|
@ -52,7 +52,7 @@ public class TestEscherBlipRecord extends TestCase
|
||||||
(byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, });
|
(byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, });
|
||||||
r.setWidth(10);
|
r.setWidth(10);
|
||||||
r.setHeight(11);
|
r.setHeight(11);
|
||||||
r.setRecordId(EscherBlipRecord.RECORD_ID_START);
|
r.setRecordId(EscherBlipWMFRecord.RECORD_ID_START);
|
||||||
r.setOptions((short)5420);
|
r.setOptions((short)5420);
|
||||||
r.setData(new byte[] { (byte)0x01, (byte)0x02 } );
|
r.setData(new byte[] { (byte)0x01, (byte)0x02 } );
|
||||||
|
|
||||||
|
@ -79,10 +79,10 @@ public class TestEscherBlipRecord extends TestCase
|
||||||
|
|
||||||
public void testFillFields() throws Exception
|
public void testFillFields() throws Exception
|
||||||
{
|
{
|
||||||
EscherBlipRecord r = new EscherBlipRecord();
|
EscherBlipWMFRecord r = new EscherBlipWMFRecord();
|
||||||
r.fillFields( data, 0, new DefaultEscherRecordFactory());
|
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( 1, r.getBoundaryLeft() );
|
||||||
assertEquals( 2, r.getBoundaryHeight() );
|
assertEquals( 2, r.getBoundaryHeight() );
|
||||||
assertEquals( 3, r.getBoundaryTop() );
|
assertEquals( 3, r.getBoundaryTop() );
|
||||||
|
@ -100,12 +100,12 @@ public class TestEscherBlipRecord extends TestCase
|
||||||
|
|
||||||
public void testToString() throws Exception
|
public void testToString() throws Exception
|
||||||
{
|
{
|
||||||
EscherBlipRecord r = new EscherBlipRecord();
|
EscherBlipWMFRecord r = new EscherBlipWMFRecord();
|
||||||
r.fillFields( data, 0, new DefaultEscherRecordFactory() );
|
r.fillFields( data, 0, new DefaultEscherRecordFactory() );
|
||||||
|
|
||||||
String nl = System.getProperty("line.separator");
|
String nl = System.getProperty("line.separator");
|
||||||
|
|
||||||
assertEquals( "org.apache.poi.ddf.EscherBlipRecord:" + nl +
|
assertEquals( "org.apache.poi.ddf.EscherBlipWMFRecord:" + nl +
|
||||||
" RecordId: 0xF018" + nl +
|
" RecordId: 0xF018" + nl +
|
||||||
" Options: 0x152C" + nl +
|
" Options: 0x152C" + nl +
|
||||||
" Secondary UID: [01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, 01, ]" + 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
|
public void testToString() throws Exception
|
||||||
{
|
{
|
||||||
EscherBoolProperty p = new EscherBoolProperty((short)1, 1);
|
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 +
|
" RecordId: 0xF011" + nl +
|
||||||
" Options: 0x0002" + nl +
|
" Options: 0x0002" + nl +
|
||||||
" Extra Data:" + nl +
|
" Extra Data:" + nl +
|
||||||
"No Data" ;
|
"No Data" + nl ;
|
||||||
assertEquals( expected, createRecord().toString() );
|
assertEquals( expected, createRecord().toString() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ public class TestEscherOptRecord extends TestCase
|
||||||
" recordId: 0x" + HexDump.toHex(EscherOptRecord.RECORD_ID) + nl +
|
" recordId: 0x" + HexDump.toHex(EscherOptRecord.RECORD_ID) + nl +
|
||||||
" numchildren: 0" + nl +
|
" numchildren: 0" + nl +
|
||||||
" properties:" + 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());
|
assertEquals( expected, r.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,16 +19,14 @@
|
||||||
package org.apache.poi.hssf.model;
|
package org.apache.poi.hssf.model;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
import org.apache.poi.hssf.record.*;
|
||||||
import org.apache.poi.hssf.record.BOFRecord;
|
import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
|
||||||
import org.apache.poi.hssf.record.EOFRecord;
|
|
||||||
import org.apache.poi.hssf.record.DimensionsRecord;
|
|
||||||
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
|
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
|
||||||
import org.apache.poi.hssf.record.aggregates.ValueRecordsAggregate;
|
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.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit test for the Sheet class.
|
* Unit test for the Sheet class.
|
||||||
|
@ -55,4 +53,232 @@ public class TestSheet extends TestCase
|
||||||
assertTrue( sheet.records.get(pos++) instanceof EOFRecord );
|
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
|
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()
|
public void testGetRecordSize()
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
|
@ -48,5 +51,93 @@ public class TestDrawingGroupRecord extends TestCase
|
||||||
assertEquals(28, size);
|
assertEquals(28, size);
|
||||||
|
|
||||||
assertEquals(24, dggContainer.getRecordSize());
|
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;
|
package org.apache.poi.hssf.record;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
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.EscherClientDataRecord;
|
||||||
|
import org.apache.poi.ddf.EscherContainerRecord;
|
||||||
import org.apache.poi.ddf.EscherDggRecord;
|
import org.apache.poi.ddf.EscherDggRecord;
|
||||||
import org.apache.poi.hssf.model.DrawingManager;
|
import org.apache.poi.ddf.EscherSpRecord;
|
||||||
import org.apache.poi.hssf.model.Sheet;
|
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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -82,7 +81,7 @@ public class TestEscherAggregate extends TestCase
|
||||||
records.add( d2 );
|
records.add( d2 );
|
||||||
records.add( r2 );
|
records.add( r2 );
|
||||||
|
|
||||||
DrawingManager drawingManager = new DrawingManager(new EscherDggRecord() );
|
DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord() );
|
||||||
EscherAggregate aggregate = EscherAggregate.createAggregate( records, 0, drawingManager );
|
EscherAggregate aggregate = EscherAggregate.createAggregate( records, 0, drawingManager );
|
||||||
|
|
||||||
assertEquals( 1, aggregate.getEscherRecords().size() );
|
assertEquals( 1, aggregate.getEscherRecords().size() );
|
||||||
|
|
|
@ -23,6 +23,7 @@ import junit.framework.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @author Glen Stampoultzis (glens at apache.org)
|
||||||
* @author Marc Johnson (mjohnson at apache dot org)
|
* @author Marc Johnson (mjohnson at apache dot org)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -281,7 +282,8 @@ public class TestHexDump
|
||||||
// verify proper behaviour with empty byte array
|
// verify proper behaviour with empty byte array
|
||||||
ByteArrayOutputStream os = new ByteArrayOutputStream( );
|
ByteArrayOutputStream os = new ByteArrayOutputStream( );
|
||||||
HexDump.dump( new byte[0], 0, os, 0 );
|
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()
|
public void testToHex()
|
||||||
|
@ -289,7 +291,7 @@ public class TestHexDump
|
||||||
{
|
{
|
||||||
assertEquals( "000A", HexDump.toHex((short)0xA));
|
assertEquals( "000A", HexDump.toHex((short)0xA));
|
||||||
assertEquals( "0A", HexDump.toHex((byte)0xA));
|
assertEquals( "0A", HexDump.toHex((byte)0xA));
|
||||||
assertEquals( "0000000A", HexDump.toHex((int)0xA));
|
assertEquals( "0000000A", HexDump.toHex(0xA));
|
||||||
|
|
||||||
assertEquals( "FFFF", HexDump.toHex((short)0xFFFF));
|
assertEquals( "FFFF", HexDump.toHex((short)0xFFFF));
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,12 @@
|
||||||
|
|
||||||
package org.apache.poi.util;
|
package org.apache.poi.util;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
import org.apache.poi.util.LittleEndian.BufferUnderrunException;
|
import org.apache.poi.util.LittleEndian.BufferUnderrunException;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import junit.framework.*;
|
import java.io.InputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to test LittleEndian functionality
|
* Class to test LittleEndian functionality
|
||||||
|
@ -39,7 +40,6 @@ public class TestLittleEndian
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public TestLittleEndian(String name)
|
public TestLittleEndian(String name)
|
||||||
{
|
{
|
||||||
super(name);
|
super(name);
|
||||||
|
|
Loading…
Reference in New Issue