Model for drawing format support
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/branches/REL_2_BRANCH@353496 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
104093d45e
commit
3df231642a
126
src/java/org/apache/poi/hssf/model/AbstractShape.java
Normal file
126
src/java/org/apache/poi/hssf/model/AbstractShape.java
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
package org.apache.poi.hssf.model;
|
||||||
|
|
||||||
|
import org.apache.poi.ddf.*;
|
||||||
|
import org.apache.poi.hssf.record.ObjRecord;
|
||||||
|
import org.apache.poi.hssf.usermodel.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract shape is the lowlevel model for a shape.
|
||||||
|
*
|
||||||
|
* @author Glen Stampoultzis (glens at apache.org)
|
||||||
|
*/
|
||||||
|
public abstract class AbstractShape
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a new shape object used to create the escher records.
|
||||||
|
*
|
||||||
|
* @param hssfShape The simple shape this is based on.
|
||||||
|
*/
|
||||||
|
public static AbstractShape createShape( HSSFShape hssfShape, int shapeId )
|
||||||
|
{
|
||||||
|
AbstractShape shape = null;
|
||||||
|
if (hssfShape instanceof HSSFTextbox)
|
||||||
|
{
|
||||||
|
shape = new TextboxShape( (HSSFTextbox)hssfShape, shapeId );
|
||||||
|
}
|
||||||
|
else if (hssfShape instanceof HSSFPolygon)
|
||||||
|
{
|
||||||
|
shape = new PolygonShape( (HSSFPolygon) hssfShape, shapeId );
|
||||||
|
}
|
||||||
|
else if (hssfShape instanceof HSSFSimpleShape)
|
||||||
|
{
|
||||||
|
HSSFSimpleShape simpleShape = (HSSFSimpleShape) hssfShape;
|
||||||
|
switch ( simpleShape.getShapeType() )
|
||||||
|
{
|
||||||
|
case HSSFSimpleShape.OBJECT_TYPE_LINE:
|
||||||
|
shape = new LineShape( simpleShape, shapeId );
|
||||||
|
break;
|
||||||
|
case HSSFSimpleShape.OBJECT_TYPE_OVAL:
|
||||||
|
case HSSFSimpleShape.OBJECT_TYPE_RECTANGLE:
|
||||||
|
shape = new SimpleFilledShape( simpleShape, shapeId );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Do not know how to handle this type of shape");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Unknown shape type");
|
||||||
|
}
|
||||||
|
EscherSpRecord sp = shape.getSpContainer().getChildById(EscherSpRecord.RECORD_ID);
|
||||||
|
if (hssfShape.getParent() != null)
|
||||||
|
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_CHILD);
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbstractShape()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The shape container and it's children that can represent this
|
||||||
|
* shape.
|
||||||
|
*/
|
||||||
|
public abstract EscherContainerRecord getSpContainer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The object record that is associated with this shape.
|
||||||
|
*/
|
||||||
|
public abstract ObjRecord getObjRecord();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an escher anchor record from a HSSFAnchor.
|
||||||
|
*
|
||||||
|
* @param userAnchor The high level anchor to convert.
|
||||||
|
* @return An escher anchor record.
|
||||||
|
*/
|
||||||
|
protected EscherRecord createAnchor( HSSFAnchor userAnchor )
|
||||||
|
{
|
||||||
|
return ConvertAnchor.createAnchor(userAnchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add standard properties to the opt record. These properties effect
|
||||||
|
* all records.
|
||||||
|
*
|
||||||
|
* @param shape The user model shape.
|
||||||
|
* @param opt The opt record to add the properties to.
|
||||||
|
* @return The number of options added.
|
||||||
|
*/
|
||||||
|
protected int addStandardOptions( HSSFShape shape, EscherOptRecord opt )
|
||||||
|
{
|
||||||
|
opt.addEscherProperty( new EscherBoolProperty( EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x080000 ) );
|
||||||
|
// opt.addEscherProperty( new EscherBoolProperty( EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x080008 ) );
|
||||||
|
if ( shape.isNoFill() )
|
||||||
|
{
|
||||||
|
// Wonderful... none of the spec's give any clue as to what these constants mean.
|
||||||
|
opt.addEscherProperty( new EscherBoolProperty( EscherProperties.FILL__NOFILLHITTEST, 0x00110000 ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
opt.addEscherProperty( new EscherBoolProperty( EscherProperties.FILL__NOFILLHITTEST, 0x00010000 ) );
|
||||||
|
}
|
||||||
|
opt.addEscherProperty( new EscherRGBProperty( EscherProperties.FILL__FILLCOLOR, shape.getFillColor() ) );
|
||||||
|
opt.addEscherProperty( new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x080000 ) );
|
||||||
|
opt.addEscherProperty( new EscherRGBProperty( EscherProperties.LINESTYLE__COLOR, shape.getLineStyleColor() ) );
|
||||||
|
int options = 5;
|
||||||
|
if (shape.getLineWidth() != HSSFShape.LINEWIDTH_DEFAULT)
|
||||||
|
{
|
||||||
|
opt.addEscherProperty( new EscherSimpleProperty( EscherProperties.LINESTYLE__LINEWIDTH, shape.getLineWidth()));
|
||||||
|
options++;
|
||||||
|
}
|
||||||
|
if (shape.getLineStyle() != HSSFShape.LINESTYLE_SOLID)
|
||||||
|
{
|
||||||
|
opt.addEscherProperty( new EscherSimpleProperty( EscherProperties.LINESTYLE__LINEDASHING, shape.getLineStyle()));
|
||||||
|
opt.addEscherProperty( new EscherSimpleProperty( EscherProperties.LINESTYLE__LINEENDCAPSTYLE, 0));
|
||||||
|
if (shape.getLineStyle() == HSSFShape.LINESTYLE_NONE)
|
||||||
|
opt.addEscherProperty( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080000));
|
||||||
|
else
|
||||||
|
opt.addEscherProperty( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080008));
|
||||||
|
options += 3;
|
||||||
|
}
|
||||||
|
opt.sortProperties();
|
||||||
|
return options; // # options added
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
50
src/java/org/apache/poi/hssf/model/ConvertAnchor.java
Normal file
50
src/java/org/apache/poi/hssf/model/ConvertAnchor.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package org.apache.poi.hssf.model;
|
||||||
|
|
||||||
|
import org.apache.poi.ddf.EscherRecord;
|
||||||
|
import org.apache.poi.ddf.EscherClientAnchorRecord;
|
||||||
|
import org.apache.poi.ddf.EscherChildAnchorRecord;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFAnchor;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFChildAnchor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
public class ConvertAnchor
|
||||||
|
{
|
||||||
|
public static EscherRecord createAnchor( HSSFAnchor userAnchor )
|
||||||
|
{
|
||||||
|
if (userAnchor instanceof HSSFClientAnchor)
|
||||||
|
{
|
||||||
|
HSSFClientAnchor a = (HSSFClientAnchor) userAnchor;
|
||||||
|
|
||||||
|
EscherClientAnchorRecord anchor = new EscherClientAnchorRecord();
|
||||||
|
anchor.setRecordId( EscherClientAnchorRecord.RECORD_ID );
|
||||||
|
anchor.setOptions( (short) 0x0000 );
|
||||||
|
anchor.setFlag( (short) 0 );
|
||||||
|
anchor.setCol1( (short) Math.min(a.getCol1(), a.getCol2()) );
|
||||||
|
anchor.setDx1( (short) Math.min(a.getDx1(), a.getDx2()) );
|
||||||
|
anchor.setRow1( (short) Math.min(a.getRow1(), a.getRow2()) );
|
||||||
|
anchor.setDy1( (short) Math.min(a.getDy1(), a.getDy2()) );
|
||||||
|
|
||||||
|
anchor.setCol2( (short) Math.max(a.getCol1(), a.getCol2()) );
|
||||||
|
anchor.setDx2( (short) Math.max(a.getDx1(), a.getDx2()) );
|
||||||
|
anchor.setRow2( (short) Math.max(a.getRow1(), a.getRow2()) );
|
||||||
|
anchor.setDy2( (short) Math.max(a.getDy1(), a.getDy2() ) );
|
||||||
|
return anchor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HSSFChildAnchor a = (HSSFChildAnchor) userAnchor;
|
||||||
|
EscherChildAnchorRecord anchor = new EscherChildAnchorRecord();
|
||||||
|
anchor.setRecordId( EscherChildAnchorRecord.RECORD_ID );
|
||||||
|
anchor.setOptions( (short) 0x0000 );
|
||||||
|
anchor.setDx1( (short) Math.min(a.getDx1(), a.getDx2()) );
|
||||||
|
anchor.setDy1( (short) Math.min(a.getDy1(), a.getDy2()) );
|
||||||
|
anchor.setDx2( (short) Math.max(a.getDx2(), a.getDx1()) );
|
||||||
|
anchor.setDy2( (short) Math.max(a.getDy2(), a.getDy1()) );
|
||||||
|
return anchor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
136
src/java/org/apache/poi/hssf/model/DrawingManager.java
Normal file
136
src/java/org/apache/poi/hssf/model/DrawingManager.java
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
package org.apache.poi.hssf.model;
|
||||||
|
|
||||||
|
import org.apache.poi.ddf.EscherDggRecord;
|
||||||
|
import org.apache.poi.ddf.EscherDgRecord;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides utilities to manage drawing groups.
|
||||||
|
*
|
||||||
|
* @author Glen Stampoultzis (glens at apache.org)
|
||||||
|
*/
|
||||||
|
public class DrawingManager
|
||||||
|
{
|
||||||
|
EscherDggRecord dgg;
|
||||||
|
Map dgMap = new HashMap(); // key = Short(drawingId), value=EscherDgRecord
|
||||||
|
|
||||||
|
public DrawingManager( EscherDggRecord dgg )
|
||||||
|
{
|
||||||
|
this.dgg = dgg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscherDgRecord createDgRecord()
|
||||||
|
{
|
||||||
|
EscherDgRecord dg = new EscherDgRecord();
|
||||||
|
dg.setRecordId( EscherDgRecord.RECORD_ID );
|
||||||
|
short dgId = findNewDrawingGroupId();
|
||||||
|
dg.setOptions( (short) ( dgId << 4 ) );
|
||||||
|
dg.setNumShapes( 0 );
|
||||||
|
dg.setLastMSOSPID( -1 );
|
||||||
|
dgg.addCluster( dgId, 0 );
|
||||||
|
dgg.setDrawingsSaved( dgg.getDrawingsSaved() + 1 );
|
||||||
|
dgMap.put( new Short( dgId ), dg );
|
||||||
|
return dg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates new shape id for the new drawing group id.
|
||||||
|
*
|
||||||
|
* @return a new shape id.
|
||||||
|
*/
|
||||||
|
public int allocateShapeId(short drawingGroupId)
|
||||||
|
{
|
||||||
|
// Get the last shape id for this drawing group.
|
||||||
|
EscherDgRecord dg = (EscherDgRecord) dgMap.get(new Short(drawingGroupId));
|
||||||
|
int lastShapeId = dg.getLastMSOSPID();
|
||||||
|
|
||||||
|
|
||||||
|
// Have we run out of shapes for this cluster?
|
||||||
|
int newShapeId = 0;
|
||||||
|
if (lastShapeId % 1024 == 1023)
|
||||||
|
{
|
||||||
|
// Yes:
|
||||||
|
// Find the starting shape id of the next free cluster
|
||||||
|
newShapeId = findFreeSPIDBlock();
|
||||||
|
// Create a new cluster in the dgg record.
|
||||||
|
dgg.addCluster(drawingGroupId, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No:
|
||||||
|
// Find the cluster for this drawing group with free space.
|
||||||
|
for (int i = 0; i < dgg.getFileIdClusters().length; i++)
|
||||||
|
{
|
||||||
|
EscherDggRecord.FileIdCluster c = dgg.getFileIdClusters()[i];
|
||||||
|
if (c.getDrawingGroupId() == drawingGroupId)
|
||||||
|
{
|
||||||
|
if (c.getNumShapeIdsUsed() != 1024)
|
||||||
|
{
|
||||||
|
// Increment the number of shapes used for this cluster.
|
||||||
|
c.incrementShapeId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the last shape id = -1 then we know to find a free block;
|
||||||
|
if (dg.getLastMSOSPID() == -1)
|
||||||
|
{
|
||||||
|
newShapeId = findFreeSPIDBlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The new shape id to be the last shapeid of this cluster + 1
|
||||||
|
newShapeId = dg.getLastMSOSPID() + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Increment the total number of shapes used in the dgg.
|
||||||
|
dgg.setNumShapesSaved(dgg.getNumShapesSaved() + 1);
|
||||||
|
// Is the new shape id >= max shape id for dgg?
|
||||||
|
if (newShapeId >= dgg.getShapeIdMax())
|
||||||
|
{
|
||||||
|
// Yes:
|
||||||
|
// Set the max shape id = new shape id + 1
|
||||||
|
dgg.setShapeIdMax(newShapeId + 1);
|
||||||
|
}
|
||||||
|
// Set last shape id for this drawing group.
|
||||||
|
dg.setLastMSOSPID(newShapeId);
|
||||||
|
// Increased the number of shapes used for this drawing group.
|
||||||
|
dg.incrementShapeCount();
|
||||||
|
|
||||||
|
|
||||||
|
return newShapeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////// Non-public methods /////////////
|
||||||
|
short findNewDrawingGroupId()
|
||||||
|
{
|
||||||
|
short dgId = 1;
|
||||||
|
while ( drawingGroupExists( dgId ) )
|
||||||
|
dgId++;
|
||||||
|
return dgId;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean drawingGroupExists( short dgId )
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < dgg.getFileIdClusters().length; i++ )
|
||||||
|
{
|
||||||
|
if ( dgg.getFileIdClusters()[i].getDrawingGroupId() == dgId )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int findFreeSPIDBlock()
|
||||||
|
{
|
||||||
|
int max = dgg.getShapeIdMax();
|
||||||
|
int next = ( ( max / 1024 ) + 1 ) * 1024;
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscherDggRecord getDgg()
|
||||||
|
{
|
||||||
|
return dgg;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
105
src/java/org/apache/poi/hssf/model/LineShape.java
Normal file
105
src/java/org/apache/poi/hssf/model/LineShape.java
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package org.apache.poi.hssf.model;
|
||||||
|
|
||||||
|
import org.apache.poi.ddf.*;
|
||||||
|
import org.apache.poi.hssf.record.*;
|
||||||
|
import org.apache.poi.hssf.usermodel.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a line shape and creates all the line specific low level records.
|
||||||
|
*
|
||||||
|
* @author Glen Stampoultzis (glens at apache.org)
|
||||||
|
*/
|
||||||
|
public class LineShape
|
||||||
|
extends AbstractShape
|
||||||
|
{
|
||||||
|
private EscherContainerRecord spContainer;
|
||||||
|
private ObjRecord objRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the line shape from the highlevel user shape. All low level
|
||||||
|
* records are created at this point.
|
||||||
|
*
|
||||||
|
* @param hssfShape The user model shape.
|
||||||
|
* @param shapeId The identifier to use for this shape.
|
||||||
|
*/
|
||||||
|
LineShape( HSSFSimpleShape hssfShape, int shapeId )
|
||||||
|
{
|
||||||
|
spContainer = createSpContainer(hssfShape, shapeId);
|
||||||
|
objRecord = createObjRecord(hssfShape, shapeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the lowerlevel escher records for this shape.
|
||||||
|
*/
|
||||||
|
private EscherContainerRecord createSpContainer(HSSFSimpleShape hssfShape, int shapeId)
|
||||||
|
{
|
||||||
|
HSSFShape shape = hssfShape;
|
||||||
|
|
||||||
|
EscherContainerRecord spContainer = new EscherContainerRecord();
|
||||||
|
EscherSpRecord sp = new EscherSpRecord();
|
||||||
|
EscherOptRecord opt = new EscherOptRecord();
|
||||||
|
EscherRecord anchor = new EscherClientAnchorRecord();
|
||||||
|
EscherClientDataRecord clientData = new EscherClientDataRecord();
|
||||||
|
|
||||||
|
spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
|
||||||
|
spContainer.setOptions( (short) 0x000F );
|
||||||
|
sp.setRecordId( EscherSpRecord.RECORD_ID );
|
||||||
|
sp.setOptions( (short) ( (EscherAggregate.ST_LINE << 4) | 0x2 ) );
|
||||||
|
|
||||||
|
sp.setShapeId( shapeId );
|
||||||
|
sp.setFlags( EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE );
|
||||||
|
opt.setRecordId( EscherOptRecord.RECORD_ID );
|
||||||
|
opt.addEscherProperty( new EscherShapePathProperty( EscherProperties.GEOMETRY__SHAPEPATH, EscherShapePathProperty.COMPLEX ) );
|
||||||
|
opt.addEscherProperty( new EscherBoolProperty( EscherProperties.LINESTYLE__NOLINEDRAWDASH, 1048592 ) );
|
||||||
|
addStandardOptions(shape, opt);
|
||||||
|
HSSFAnchor userAnchor = shape.getAnchor();
|
||||||
|
if (userAnchor.isHorizontallyFlipped())
|
||||||
|
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ);
|
||||||
|
if (userAnchor.isVerticallyFlipped())
|
||||||
|
sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT);
|
||||||
|
anchor = createAnchor(userAnchor);
|
||||||
|
clientData.setRecordId( EscherClientDataRecord.RECORD_ID );
|
||||||
|
clientData.setOptions( (short) 0x0000 );
|
||||||
|
|
||||||
|
spContainer.addChildRecord(sp);
|
||||||
|
spContainer.addChildRecord(opt);
|
||||||
|
spContainer.addChildRecord(anchor);
|
||||||
|
spContainer.addChildRecord(clientData);
|
||||||
|
|
||||||
|
return spContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the low level OBJ record for this shape.
|
||||||
|
*/
|
||||||
|
private ObjRecord createObjRecord(HSSFShape hssfShape, int shapeId)
|
||||||
|
{
|
||||||
|
HSSFShape shape = hssfShape;
|
||||||
|
|
||||||
|
ObjRecord obj = new ObjRecord();
|
||||||
|
CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
|
||||||
|
c.setObjectType((short) ((HSSFSimpleShape)shape).getShapeType());
|
||||||
|
c.setObjectId((short) ( shapeId ));
|
||||||
|
c.setLocked(true);
|
||||||
|
c.setPrintable(true);
|
||||||
|
c.setAutofill(true);
|
||||||
|
c.setAutoline(true);
|
||||||
|
EndSubRecord e = new EndSubRecord();
|
||||||
|
|
||||||
|
obj.addSubRecord(c);
|
||||||
|
obj.addSubRecord(e);
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscherContainerRecord getSpContainer()
|
||||||
|
{
|
||||||
|
return spContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjRecord getObjRecord()
|
||||||
|
{
|
||||||
|
return objRecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
143
src/java/org/apache/poi/hssf/model/PolygonShape.java
Normal file
143
src/java/org/apache/poi/hssf/model/PolygonShape.java
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
package org.apache.poi.hssf.model;
|
||||||
|
|
||||||
|
import org.apache.poi.ddf.*;
|
||||||
|
import org.apache.poi.hssf.record.ObjRecord;
|
||||||
|
import org.apache.poi.hssf.record.EscherAggregate;
|
||||||
|
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
|
||||||
|
import org.apache.poi.hssf.record.EndSubRecord;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFSimpleShape;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFShape;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFPolygon;
|
||||||
|
import org.apache.poi.util.LittleEndian;
|
||||||
|
|
||||||
|
public class PolygonShape
|
||||||
|
extends AbstractShape
|
||||||
|
{
|
||||||
|
public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30;
|
||||||
|
|
||||||
|
private EscherContainerRecord spContainer;
|
||||||
|
private ObjRecord objRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the low evel records for an polygon.
|
||||||
|
*
|
||||||
|
* @param hssfShape The highlevel shape.
|
||||||
|
* @param shapeId The shape id to use for this shape.
|
||||||
|
*/
|
||||||
|
PolygonShape( HSSFPolygon hssfShape, int shapeId )
|
||||||
|
{
|
||||||
|
spContainer = createSpContainer( hssfShape, shapeId );
|
||||||
|
objRecord = createObjRecord( hssfShape, shapeId );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the shape records for this shape.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private EscherContainerRecord createSpContainer( HSSFPolygon hssfShape, int shapeId )
|
||||||
|
{
|
||||||
|
HSSFShape shape = hssfShape;
|
||||||
|
|
||||||
|
EscherContainerRecord spContainer = new EscherContainerRecord();
|
||||||
|
EscherSpRecord sp = new EscherSpRecord();
|
||||||
|
EscherOptRecord opt = new EscherOptRecord();
|
||||||
|
EscherClientDataRecord clientData = new EscherClientDataRecord();
|
||||||
|
|
||||||
|
spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
|
||||||
|
spContainer.setOptions( (short) 0x000F );
|
||||||
|
sp.setRecordId( EscherSpRecord.RECORD_ID );
|
||||||
|
sp.setOptions( (short) ( ( EscherAggregate.ST_DONUT << 4 ) | 0x2 ) );
|
||||||
|
sp.setShapeId( shapeId );
|
||||||
|
if (hssfShape.getParent() == null)
|
||||||
|
sp.setFlags( EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE );
|
||||||
|
else
|
||||||
|
sp.setFlags( EscherSpRecord.FLAG_CHILD | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE );
|
||||||
|
opt.setRecordId( EscherOptRecord.RECORD_ID );
|
||||||
|
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.TRANSFORM__ROTATION, false, false, 0));
|
||||||
|
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, false, false, hssfShape.getDrawAreaWidth()));
|
||||||
|
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, false, false, hssfShape.getDrawAreaHeight()));
|
||||||
|
opt.addEscherProperty(new EscherShapePathProperty(EscherProperties.GEOMETRY__SHAPEPATH, EscherShapePathProperty.COMPLEX));
|
||||||
|
EscherArrayProperty verticesProp = new EscherArrayProperty(EscherProperties.GEOMETRY__VERTICES, false, new byte[0] );
|
||||||
|
verticesProp.setNumberOfElementsInArray(hssfShape.getXPoints().length+1);
|
||||||
|
verticesProp.setNumberOfElementsInMemory(hssfShape.getXPoints().length+1);
|
||||||
|
verticesProp.setSizeOfElements(0xFFF0);
|
||||||
|
for (int i = 0; i < hssfShape.getXPoints().length; i++)
|
||||||
|
{
|
||||||
|
byte[] data = new byte[4];
|
||||||
|
LittleEndian.putShort(data, 0, (short)hssfShape.getXPoints()[i]);
|
||||||
|
LittleEndian.putShort(data, 2, (short)hssfShape.getYPoints()[i]);
|
||||||
|
verticesProp.setElement(i, data);
|
||||||
|
}
|
||||||
|
int point = hssfShape.getXPoints().length;
|
||||||
|
byte[] data = new byte[4];
|
||||||
|
LittleEndian.putShort(data, 0, (short)hssfShape.getXPoints()[0]);
|
||||||
|
LittleEndian.putShort(data, 2, (short)hssfShape.getYPoints()[0]);
|
||||||
|
verticesProp.setElement(point, data);
|
||||||
|
opt.addEscherProperty(verticesProp);
|
||||||
|
EscherArrayProperty segmentsProp = new EscherArrayProperty(EscherProperties.GEOMETRY__SEGMENTINFO, false, null );
|
||||||
|
segmentsProp.setSizeOfElements(0x0002);
|
||||||
|
segmentsProp.setNumberOfElementsInArray(hssfShape.getXPoints().length * 2 + 4);
|
||||||
|
segmentsProp.setNumberOfElementsInMemory(hssfShape.getXPoints().length * 2 + 4);
|
||||||
|
segmentsProp.setElement(0, new byte[] { (byte)0x00, (byte)0x40 } );
|
||||||
|
segmentsProp.setElement(1, new byte[] { (byte)0x00, (byte)0xAC } );
|
||||||
|
for (int i = 0; i < hssfShape.getXPoints().length; i++)
|
||||||
|
{
|
||||||
|
segmentsProp.setElement(2 + i * 2, new byte[] { (byte)0x01, (byte)0x00 } );
|
||||||
|
segmentsProp.setElement(3 + i * 2, new byte[] { (byte)0x00, (byte)0xAC } );
|
||||||
|
}
|
||||||
|
segmentsProp.setElement(segmentsProp.getNumberOfElementsInArray() - 2, new byte[] { (byte)0x01, (byte)0x60 } );
|
||||||
|
segmentsProp.setElement(segmentsProp.getNumberOfElementsInArray() - 1, new byte[] { (byte)0x00, (byte)0x80 } );
|
||||||
|
opt.addEscherProperty(segmentsProp);
|
||||||
|
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__FILLOK, false, false, 0x00010001));
|
||||||
|
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINESTARTARROWHEAD, false, false, 0x0));
|
||||||
|
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDARROWHEAD, false, false, 0x0));
|
||||||
|
opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDCAPSTYLE, false, false, 0x0));
|
||||||
|
|
||||||
|
addStandardOptions(shape, opt);
|
||||||
|
|
||||||
|
EscherRecord anchor = createAnchor( shape.getAnchor() );
|
||||||
|
clientData.setRecordId( EscherClientDataRecord.RECORD_ID );
|
||||||
|
clientData.setOptions( (short) 0x0000 );
|
||||||
|
|
||||||
|
spContainer.addChildRecord( sp );
|
||||||
|
spContainer.addChildRecord( opt );
|
||||||
|
spContainer.addChildRecord( anchor );
|
||||||
|
spContainer.addChildRecord( clientData );
|
||||||
|
|
||||||
|
return spContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the low level OBJ record for this shape.
|
||||||
|
*/
|
||||||
|
private ObjRecord createObjRecord( HSSFShape hssfShape, int shapeId )
|
||||||
|
{
|
||||||
|
HSSFShape shape = hssfShape;
|
||||||
|
|
||||||
|
ObjRecord obj = new ObjRecord();
|
||||||
|
CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
|
||||||
|
c.setObjectType( OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING );
|
||||||
|
c.setObjectId( (short) ( shapeId ) );
|
||||||
|
c.setLocked( true );
|
||||||
|
c.setPrintable( true );
|
||||||
|
c.setAutofill( true );
|
||||||
|
c.setAutoline( true );
|
||||||
|
EndSubRecord e = new EndSubRecord();
|
||||||
|
|
||||||
|
obj.addSubRecord( c );
|
||||||
|
obj.addSubRecord( e );
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscherContainerRecord getSpContainer()
|
||||||
|
{
|
||||||
|
return spContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjRecord getObjRecord()
|
||||||
|
{
|
||||||
|
return objRecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -55,16 +55,18 @@
|
|||||||
|
|
||||||
package org.apache.poi.hssf.model;
|
package org.apache.poi.hssf.model;
|
||||||
|
|
||||||
import java.util.List;
|
import org.apache.poi.hssf.record.*;
|
||||||
|
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
|
||||||
|
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
|
||||||
|
import org.apache.poi.hssf.record.aggregates.ValueRecordsAggregate;
|
||||||
|
import org.apache.poi.hssf.record.formula.Ptg;
|
||||||
|
import org.apache.poi.util.IntList;
|
||||||
|
import org.apache.poi.util.POILogFactory;
|
||||||
|
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 org.apache.poi.hssf
|
|
||||||
.record.*; // normally I don't do this, buy we literally mean ALL
|
|
||||||
import org.apache.poi.hssf.record.formula.Ptg;
|
|
||||||
import org.apache.poi.util.*;
|
|
||||||
import org.apache.poi.hssf.record
|
|
||||||
.aggregates.*; // 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)
|
||||||
@ -795,12 +797,17 @@ public class Sheet implements Model
|
|||||||
// System.arraycopy(rec, 0, data, offset + pos, rec.length);
|
// System.arraycopy(rec, 0, data, offset + pos, rec.length);
|
||||||
Record record = (( Record ) records.get(k));
|
Record record = (( Record ) records.get(k));
|
||||||
|
|
||||||
//uncomment to test record sizes
|
//// uncomment to test record sizes ////
|
||||||
|
// System.out.println( record.getClass().getName() );
|
||||||
// byte[] data2 = new byte[record.getRecordSize()];
|
// byte[] data2 = new byte[record.getRecordSize()];
|
||||||
// record.serialize(0, data2 ); // rec.length;
|
// record.serialize(0, data2 ); // rec.length;
|
||||||
// if (LittleEndian.getUShort(data2, 2) != record.getRecordSize() - 4
|
// if (LittleEndian.getUShort(data2, 2) != record.getRecordSize() - 4
|
||||||
// && record instanceof RowRecordsAggregate == false && record instanceof ValueRecordsAggregate == false)
|
// && record instanceof RowRecordsAggregate == false
|
||||||
// throw new RuntimeException("Blah!!!");
|
// && record instanceof ValueRecordsAggregate == false
|
||||||
|
// && record instanceof EscherAggregate == false)
|
||||||
|
// {
|
||||||
|
// throw new RuntimeException("Blah!!! Size off by " + ( LittleEndian.getUShort(data2, 2) - record.getRecordSize() - 4) + " records.");
|
||||||
|
// }
|
||||||
|
|
||||||
pos += record.serialize(pos + offset, data ); // rec.length;
|
pos += record.serialize(pos + offset, data ); // rec.length;
|
||||||
|
|
||||||
@ -2609,7 +2616,7 @@ public class Sheet implements Model
|
|||||||
* @return whether RowColHeadings are displayed
|
* @return whether RowColHeadings are displayed
|
||||||
*/
|
*/
|
||||||
public boolean isDisplayRowColHeadings() {
|
public boolean isDisplayRowColHeadings() {
|
||||||
return windowTwo.getDisplayRowColHeadings();
|
return windowTwo.getDisplayRowColHeadings();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2620,7 +2627,61 @@ public class Sheet implements Model
|
|||||||
protected Margin[] getMargins() {
|
protected Margin[] getMargins() {
|
||||||
if (margins == null)
|
if (margins == null)
|
||||||
margins = new Margin[4];
|
margins = new Margin[4];
|
||||||
return margins;
|
return margins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int aggregateDrawingRecords(DrawingManager drawingManager)
|
||||||
|
{
|
||||||
|
int loc = findFirstRecordLocBySid(DrawingRecord.sid);
|
||||||
|
boolean noDrawingRecordsFound = loc == -1;
|
||||||
|
if (noDrawingRecordsFound)
|
||||||
|
{
|
||||||
|
EscherAggregate aggregate = new EscherAggregate( drawingManager );
|
||||||
|
loc = findFirstRecordLocBySid(EscherAggregate.sid);
|
||||||
|
if (loc == -1)
|
||||||
|
{
|
||||||
|
loc = findFirstRecordLocBySid( WindowTwoRecord.sid );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
getRecords().remove(loc);
|
||||||
|
}
|
||||||
|
getRecords().add( loc, aggregate );
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List records = getRecords();
|
||||||
|
EscherAggregate r = EscherAggregate.createAggregate( records, loc, drawingManager );
|
||||||
|
int startloc = loc;
|
||||||
|
while ( loc + 1 < records.size()
|
||||||
|
&& records.get( loc ) instanceof DrawingRecord
|
||||||
|
&& records.get( loc + 1 ) instanceof ObjRecord )
|
||||||
|
{
|
||||||
|
loc += 2;
|
||||||
|
}
|
||||||
|
int endloc = loc-1;
|
||||||
|
for(int i = 0; i < (endloc - startloc + 1); i++)
|
||||||
|
records.remove(startloc);
|
||||||
|
records.add(startloc, r);
|
||||||
|
|
||||||
|
return startloc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform any work necessary before the sheet is about to be serialized.
|
||||||
|
* For instance the escher aggregates size needs to be calculated before
|
||||||
|
* serialization so that the dgg record (which occurs first) can be written.
|
||||||
|
*/
|
||||||
|
public void preSerialize()
|
||||||
|
{
|
||||||
|
for ( Iterator iterator = getRecords().iterator(); iterator.hasNext(); )
|
||||||
|
{
|
||||||
|
Record r = (Record) iterator.next();
|
||||||
|
if (r instanceof EscherAggregate)
|
||||||
|
r.getRecordSize(); // Trigger flatterning of user model and corresponding update of dgg record.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
111
src/java/org/apache/poi/hssf/model/SimpleFilledShape.java
Normal file
111
src/java/org/apache/poi/hssf/model/SimpleFilledShape.java
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
package org.apache.poi.hssf.model;
|
||||||
|
|
||||||
|
import org.apache.poi.ddf.*;
|
||||||
|
import org.apache.poi.hssf.record.ObjRecord;
|
||||||
|
import org.apache.poi.hssf.record.EscherAggregate;
|
||||||
|
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
|
||||||
|
import org.apache.poi.hssf.record.EndSubRecord;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFSimpleShape;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFShape;
|
||||||
|
|
||||||
|
public class SimpleFilledShape
|
||||||
|
extends AbstractShape
|
||||||
|
{
|
||||||
|
private EscherContainerRecord spContainer;
|
||||||
|
private ObjRecord objRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the low evel records for an oval.
|
||||||
|
*
|
||||||
|
* @param hssfShape The highlevel shape.
|
||||||
|
* @param shapeId The shape id to use for this shape.
|
||||||
|
*/
|
||||||
|
SimpleFilledShape( HSSFSimpleShape hssfShape, int shapeId )
|
||||||
|
{
|
||||||
|
spContainer = createSpContainer( hssfShape, shapeId );
|
||||||
|
objRecord = createObjRecord( hssfShape, shapeId );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the shape records for this shape.
|
||||||
|
*
|
||||||
|
* @param hssfShape
|
||||||
|
* @param shapeId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private EscherContainerRecord createSpContainer( HSSFSimpleShape hssfShape, int shapeId )
|
||||||
|
{
|
||||||
|
HSSFShape shape = hssfShape;
|
||||||
|
|
||||||
|
EscherContainerRecord spContainer = new EscherContainerRecord();
|
||||||
|
EscherSpRecord sp = new EscherSpRecord();
|
||||||
|
EscherOptRecord opt = new EscherOptRecord();
|
||||||
|
EscherClientDataRecord clientData = new EscherClientDataRecord();
|
||||||
|
|
||||||
|
spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
|
||||||
|
spContainer.setOptions( (short) 0x000F );
|
||||||
|
sp.setRecordId( EscherSpRecord.RECORD_ID );
|
||||||
|
short shapeType = objTypeToShapeType( hssfShape.getShapeType() );
|
||||||
|
sp.setOptions( (short) ( ( shapeType << 4 ) | 0x2 ) );
|
||||||
|
sp.setShapeId( shapeId );
|
||||||
|
sp.setFlags( EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE );
|
||||||
|
opt.setRecordId( EscherOptRecord.RECORD_ID );
|
||||||
|
addStandardOptions(shape, opt);
|
||||||
|
EscherRecord anchor = createAnchor( shape.getAnchor() );
|
||||||
|
clientData.setRecordId( EscherClientDataRecord.RECORD_ID );
|
||||||
|
clientData.setOptions( (short) 0x0000 );
|
||||||
|
|
||||||
|
spContainer.addChildRecord( sp );
|
||||||
|
spContainer.addChildRecord( opt );
|
||||||
|
spContainer.addChildRecord( anchor );
|
||||||
|
spContainer.addChildRecord( clientData );
|
||||||
|
|
||||||
|
return spContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private short objTypeToShapeType( int objType )
|
||||||
|
{
|
||||||
|
short shapeType;
|
||||||
|
if (objType == HSSFSimpleShape.OBJECT_TYPE_OVAL)
|
||||||
|
shapeType = EscherAggregate.ST_ELLIPSE;
|
||||||
|
else if (objType == HSSFSimpleShape.OBJECT_TYPE_RECTANGLE)
|
||||||
|
shapeType = EscherAggregate.ST_RECTANGLE;
|
||||||
|
else
|
||||||
|
throw new IllegalArgumentException("Unable to handle an object of this type");
|
||||||
|
return shapeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the low level OBJ record for this shape.
|
||||||
|
*/
|
||||||
|
private ObjRecord createObjRecord( HSSFShape hssfShape, int shapeId )
|
||||||
|
{
|
||||||
|
HSSFShape shape = hssfShape;
|
||||||
|
|
||||||
|
ObjRecord obj = new ObjRecord();
|
||||||
|
CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
|
||||||
|
c.setObjectType( (short) ( (HSSFSimpleShape) shape ).getShapeType() );
|
||||||
|
c.setObjectId( (short) ( shapeId ) );
|
||||||
|
c.setLocked( true );
|
||||||
|
c.setPrintable( true );
|
||||||
|
c.setAutofill( true );
|
||||||
|
c.setAutoline( true );
|
||||||
|
EndSubRecord e = new EndSubRecord();
|
||||||
|
|
||||||
|
obj.addSubRecord( c );
|
||||||
|
obj.addSubRecord( e );
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscherContainerRecord getSpContainer()
|
||||||
|
{
|
||||||
|
return spContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjRecord getObjRecord()
|
||||||
|
{
|
||||||
|
return objRecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
151
src/java/org/apache/poi/hssf/model/TextboxShape.java
Normal file
151
src/java/org/apache/poi/hssf/model/TextboxShape.java
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
package org.apache.poi.hssf.model;
|
||||||
|
|
||||||
|
import org.apache.poi.ddf.*;
|
||||||
|
import org.apache.poi.hssf.record.*;
|
||||||
|
import org.apache.poi.hssf.usermodel.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an textbox shape and converts between the highlevel records
|
||||||
|
* and lowlevel records for an oval.
|
||||||
|
*
|
||||||
|
* @author Glen Stampoultzis (glens at apache.org)
|
||||||
|
*/
|
||||||
|
public class TextboxShape
|
||||||
|
extends AbstractShape
|
||||||
|
{
|
||||||
|
private EscherContainerRecord spContainer;
|
||||||
|
private TextObjectRecord textObjectRecord;
|
||||||
|
private ObjRecord objRecord;
|
||||||
|
private EscherTextboxRecord escherTextbox;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the low evel records for an textbox.
|
||||||
|
*
|
||||||
|
* @param hssfShape The highlevel shape.
|
||||||
|
* @param shapeId The shape id to use for this shape.
|
||||||
|
*/
|
||||||
|
TextboxShape( HSSFTextbox hssfShape, int shapeId )
|
||||||
|
{
|
||||||
|
spContainer = createSpContainer( hssfShape, shapeId );
|
||||||
|
objRecord = createObjRecord( hssfShape, shapeId );
|
||||||
|
textObjectRecord = createTextObjectRecord( hssfShape, shapeId );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the low level OBJ record for this shape.
|
||||||
|
*/
|
||||||
|
private ObjRecord createObjRecord( HSSFTextbox hssfShape, int shapeId )
|
||||||
|
{
|
||||||
|
HSSFShape shape = hssfShape;
|
||||||
|
|
||||||
|
ObjRecord obj = new ObjRecord();
|
||||||
|
CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
|
||||||
|
c.setObjectType( (short) ( (HSSFSimpleShape) shape ).getShapeType() );
|
||||||
|
c.setObjectId( (short) ( shapeId ) );
|
||||||
|
c.setLocked( true );
|
||||||
|
c.setPrintable( true );
|
||||||
|
c.setAutofill( true );
|
||||||
|
c.setAutoline( true );
|
||||||
|
EndSubRecord e = new EndSubRecord();
|
||||||
|
|
||||||
|
obj.addSubRecord( c );
|
||||||
|
obj.addSubRecord( e );
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the escher shape records for this shape.
|
||||||
|
*
|
||||||
|
* @param hssfShape
|
||||||
|
* @param shapeId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private EscherContainerRecord createSpContainer( HSSFTextbox hssfShape, int shapeId )
|
||||||
|
{
|
||||||
|
HSSFTextbox shape = hssfShape;
|
||||||
|
|
||||||
|
EscherContainerRecord spContainer = new EscherContainerRecord();
|
||||||
|
EscherSpRecord sp = new EscherSpRecord();
|
||||||
|
EscherOptRecord opt = new EscherOptRecord();
|
||||||
|
EscherRecord anchor = new EscherClientAnchorRecord();
|
||||||
|
EscherClientDataRecord clientData = new EscherClientDataRecord();
|
||||||
|
escherTextbox = new EscherTextboxRecord();
|
||||||
|
|
||||||
|
spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
|
||||||
|
spContainer.setOptions( (short) 0x000F );
|
||||||
|
sp.setRecordId( EscherSpRecord.RECORD_ID );
|
||||||
|
sp.setOptions( (short) ( ( EscherAggregate.ST_TEXTBOX << 4 ) | 0x2 ) );
|
||||||
|
|
||||||
|
sp.setShapeId( shapeId );
|
||||||
|
sp.setFlags( EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE );
|
||||||
|
opt.setRecordId( EscherOptRecord.RECORD_ID );
|
||||||
|
// opt.addEscherProperty( new EscherBoolProperty( EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 262144 ) );
|
||||||
|
opt.addEscherProperty( new EscherSimpleProperty( EscherProperties.TEXT__TEXTID, 0 ) );
|
||||||
|
opt.addEscherProperty( new EscherSimpleProperty( EscherProperties.TEXT__TEXTLEFT, shape.getMarginLeft() ) );
|
||||||
|
opt.addEscherProperty( new EscherSimpleProperty( EscherProperties.TEXT__TEXTRIGHT, shape.getMarginRight() ) );
|
||||||
|
opt.addEscherProperty( new EscherSimpleProperty( EscherProperties.TEXT__TEXTBOTTOM, shape.getMarginBottom() ) );
|
||||||
|
opt.addEscherProperty( new EscherSimpleProperty( EscherProperties.TEXT__TEXTTOP, shape.getMarginTop() ) );
|
||||||
|
addStandardOptions( shape, opt );
|
||||||
|
HSSFAnchor userAnchor = shape.getAnchor();
|
||||||
|
// if (userAnchor.isHorizontallyFlipped())
|
||||||
|
// sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ);
|
||||||
|
// if (userAnchor.isVerticallyFlipped())
|
||||||
|
// sp.setFlags(sp.getFlags() | EscherSpRecord.FLAG_FLIPVERT);
|
||||||
|
anchor = createAnchor( userAnchor );
|
||||||
|
clientData.setRecordId( EscherClientDataRecord.RECORD_ID );
|
||||||
|
clientData.setOptions( (short) 0x0000 );
|
||||||
|
escherTextbox.setRecordId( EscherTextboxRecord.RECORD_ID );
|
||||||
|
escherTextbox.setOptions( (short) 0x0000 );
|
||||||
|
|
||||||
|
spContainer.addChildRecord( sp );
|
||||||
|
spContainer.addChildRecord( opt );
|
||||||
|
spContainer.addChildRecord( anchor );
|
||||||
|
spContainer.addChildRecord( clientData );
|
||||||
|
spContainer.addChildRecord( escherTextbox );
|
||||||
|
|
||||||
|
return spContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Textboxes also have an extra TXO record associated with them that most
|
||||||
|
* other shapes dont have.
|
||||||
|
*/
|
||||||
|
private TextObjectRecord createTextObjectRecord( HSSFTextbox hssfShape, int shapeId )
|
||||||
|
{
|
||||||
|
HSSFTextbox shape = hssfShape;
|
||||||
|
|
||||||
|
TextObjectRecord obj = new TextObjectRecord();
|
||||||
|
obj.setHorizontalTextAlignment( TextObjectRecord.HORIZONTAL_TEXT_ALIGNMENT_LEFT_ALIGNED );
|
||||||
|
obj.setVerticalTextAlignment( TextObjectRecord.VERTICAL_TEXT_ALIGNMENT_TOP );
|
||||||
|
obj.setTextLocked( true );
|
||||||
|
obj.setTextOrientation( TextObjectRecord.TEXT_ORIENTATION_NONE );
|
||||||
|
int frLength = ( shape.getString().numFormattingRuns() + 1 ) * 8;
|
||||||
|
obj.setFormattingRunLength( (short) frLength );
|
||||||
|
obj.setTextLength( (short) shape.getString().length() );
|
||||||
|
obj.setStr( shape.getString() );
|
||||||
|
obj.setReserved7( 0 );
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscherContainerRecord getSpContainer()
|
||||||
|
{
|
||||||
|
return spContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjRecord getObjRecord()
|
||||||
|
{
|
||||||
|
return objRecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextObjectRecord getTextObjectRecord()
|
||||||
|
{
|
||||||
|
return textObjectRecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EscherRecord getEscherTextbox()
|
||||||
|
{
|
||||||
|
return escherTextbox;
|
||||||
|
}
|
||||||
|
}
|
@ -58,8 +58,10 @@ package org.apache.poi.hssf.model;
|
|||||||
import org.apache.poi.hssf.record.*;
|
import org.apache.poi.hssf.record.*;
|
||||||
import org.apache.poi.hssf.util.HSSFColor;
|
import org.apache.poi.hssf.util.HSSFColor;
|
||||||
import org.apache.poi.hssf.util.SheetReferences;
|
import org.apache.poi.hssf.util.SheetReferences;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||||
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 org.apache.poi.ddf.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -91,7 +93,8 @@ import java.util.Locale;
|
|||||||
* @version 1.0-pre
|
* @version 1.0-pre
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Workbook implements Model {
|
public class Workbook implements Model
|
||||||
|
{
|
||||||
private static final int DEBUG = POILogger.DEBUG;
|
private static final int DEBUG = POILogger.DEBUG;
|
||||||
|
|
||||||
// public static Workbook currentBook = null;
|
// public static Workbook currentBook = null;
|
||||||
@ -133,6 +136,7 @@ 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 static POILogger log = POILogFactory.getLogger(Workbook.class);
|
private static POILogger log = POILogFactory.getLogger(Workbook.class);
|
||||||
|
|
||||||
@ -2081,6 +2085,56 @@ public class Workbook implements Model {
|
|||||||
return palette;
|
return palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a drawing group record. If it already exists then it's left
|
||||||
|
* alone.
|
||||||
|
*/
|
||||||
|
public void createDrawingGroup()
|
||||||
|
{
|
||||||
|
int dggLoc = findFirstRecordLocBySid(EscherContainerRecord.DGG_CONTAINER);
|
||||||
|
if (dggLoc == -1)
|
||||||
|
{
|
||||||
|
EscherContainerRecord dggContainer = new EscherContainerRecord();
|
||||||
|
EscherDggRecord dgg = new EscherDggRecord();
|
||||||
|
EscherOptRecord opt = new EscherOptRecord();
|
||||||
|
EscherSplitMenuColorsRecord splitMenuColors = new EscherSplitMenuColorsRecord();
|
||||||
|
|
||||||
|
dggContainer.setRecordId((short) 0xF000);
|
||||||
|
dggContainer.setOptions((short) 0x000F);
|
||||||
|
dgg.setRecordId(EscherDggRecord.RECORD_ID);
|
||||||
|
dgg.setOptions((short)0x0000);
|
||||||
|
dgg.setShapeIdMax(1024);
|
||||||
|
dgg.setNumShapesSaved(0);
|
||||||
|
dgg.setDrawingsSaved(0);
|
||||||
|
dgg.setFileIdClusters(new EscherDggRecord.FileIdCluster[] {} );
|
||||||
|
drawingManager = new DrawingManager(dgg);
|
||||||
|
opt.setRecordId((short) 0xF00B);
|
||||||
|
opt.setOptions((short) 0x0033);
|
||||||
|
opt.addEscherProperty( new EscherBoolProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 524296) );
|
||||||
|
opt.addEscherProperty( new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, 134217737) );
|
||||||
|
opt.addEscherProperty( new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, 134217792) );
|
||||||
|
splitMenuColors.setRecordId((short) 0xF11E);
|
||||||
|
splitMenuColors.setOptions((short) 0x0040);
|
||||||
|
splitMenuColors.setColor1(0x0800000D);
|
||||||
|
splitMenuColors.setColor2(0x0800000C);
|
||||||
|
splitMenuColors.setColor3(0x08000017);
|
||||||
|
splitMenuColors.setColor4(0x100000F7);
|
||||||
|
|
||||||
|
dggContainer.addChildRecord(dgg);
|
||||||
|
dggContainer.addChildRecord(opt);
|
||||||
|
dggContainer.addChildRecord(splitMenuColors);
|
||||||
|
|
||||||
|
DrawingGroupRecord drawingGroup = new DrawingGroupRecord();
|
||||||
|
drawingGroup.addEscherRecord(dggContainer);
|
||||||
|
int loc = findFirstRecordLocBySid(CountryRecord.sid);
|
||||||
|
getRecords().add(loc+1, drawingGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DrawingManager getDrawingManager()
|
||||||
|
{
|
||||||
|
return drawingManager;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user