Skip to content

Commit

Permalink
implemented work with existing shape groups and polygons
Browse files Browse the repository at this point in the history
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/gsoc2012@1355866 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
Evgeniy Berlog committed Jul 1, 2012
1 parent 43e8428 commit 4c43845
Show file tree
Hide file tree
Showing 16 changed files with 832 additions and 156 deletions.
2 changes: 1 addition & 1 deletion src/java/org/apache/poi/ddf/EscherSpRecord.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public String toString()
public String toXml(String tab) {
StringBuilder builder = new StringBuilder();
builder.append(tab).append(formatXmlRecordHeader(getClass().getSimpleName(), HexDump.toHex(getRecordId()), HexDump.toHex(getVersion()), HexDump.toHex(getInstance())))
.append(tab).append("\t").append("<ShapeType>").append(HexDump.toHex(getShapeType())).append("</ShapeType>\n")
.append(tab).append("\t").append("<ShapeType>0x").append(HexDump.toHex(getShapeType())).append("</ShapeType>\n")
.append(tab).append("\t").append("<ShapeId>").append(field_1_shapeId).append("</ShapeId>\n")
.append(tab).append("\t").append("<Flags>").append(decodeFlags(field_2_flags) + " (0x" + HexDump.toHex(field_2_flags) + ")").append("</Flags>\n");
builder.append(tab).append("</").append(getClass().getSimpleName()).append(">\n");
Expand Down
2 changes: 1 addition & 1 deletion src/java/org/apache/poi/hssf/model/PolygonShape.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ private EscherContainerRecord createSpContainer( HSSFPolygon hssfShape, int shap
spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
spContainer.setOptions( (short) 0x000F );
sp.setRecordId( EscherSpRecord.RECORD_ID );
sp.setOptions( (short) ( ( EscherAggregate.ST_DONUT << 4 ) | 0x2 ) );
sp.setOptions( (short) ( ( EscherAggregate.ST_NOT_PRIMATIVE << 4 ) | 0x2 ) );
sp.setShapeId( shapeId );
if (hssfShape.getParent() == null)
sp.setFlags( EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE );
Expand Down
5 changes: 0 additions & 5 deletions src/java/org/apache/poi/hssf/usermodel/HSSFComment.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@ public class HSSFComment extends HSSFTextbox implements Comment {
* It seems like HSSFRow should manage a collection of local HSSFComments
*/

private boolean _visible;
private int _row;
private int _col;
private String _author;

private NoteRecord _note;

public HSSFComment(EscherContainerRecord spContainer, ObjRecord objRecord, TextObjectRecord textObjectRecord, NoteRecord _note) {
Expand Down
2 changes: 2 additions & 0 deletions src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public HSSFShapeGroup createGroup(HSSFClientAnchor anchor)
HSSFShapeGroup group = new HSSFShapeGroup(null, anchor);
group.anchor = anchor;
addShape(group);
onCreate(group);
return group;
}

Expand Down Expand Up @@ -132,6 +133,7 @@ public HSSFPolygon createPolygon(HSSFClientAnchor anchor)
HSSFPolygon shape = new HSSFPolygon(null, anchor);
shape.anchor = anchor;
addShape(shape);
onCreate(shape);
return shape;
}

Expand Down
201 changes: 150 additions & 51 deletions src/java/org/apache/poi/hssf/usermodel/HSSFPolygon.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,87 +17,186 @@ Licensed to the Apache Software Foundation (ASF) under one or more

package org.apache.poi.hssf.usermodel;

import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherOptRecord;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.apache.poi.hssf.record.EndSubRecord;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.util.LittleEndian;

/**
* @author Glen Stampoultzis (glens at superlinksoftware.com)
*/
public class HSSFPolygon
extends HSSFShape
{
int[] xPoints;
int[] yPoints;
int drawAreaWidth = 100;
int drawAreaHeight = 100;

HSSFPolygon( HSSFShape parent, HSSFAnchor anchor )
{
super( parent, anchor );
public class HSSFPolygon extends HSSFShape {

public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 0x1E;

public HSSFPolygon(EscherContainerRecord spContainer, ObjRecord objRecord) {
super(spContainer, objRecord);
}

@Override
HSSFPolygon(HSSFShape parent, HSSFAnchor anchor) {
super(parent, anchor);
}

/**
* Generates the shape records for this shape.
*/
protected EscherContainerRecord createSpContainer() {
EscherContainerRecord spContainer = new EscherContainerRecord();
spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
spContainer.setOptions( (short) 0x000F );
EscherOptRecord optRecord = new EscherOptRecord();
optRecord.setRecordId(EscherOptRecord.RECORD_ID);
spContainer.addChildRecord(optRecord);
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_NOT_PRIMATIVE << 4) | 0x2));
if (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.setEscherProperty(new EscherSimpleProperty(EscherProperties.TRANSFORM__ROTATION, false, false, 0));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, false, false, 100));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, false, false, 100));
opt.setEscherProperty(new EscherShapePathProperty(EscherProperties.GEOMETRY__SHAPEPATH, EscherShapePathProperty.COMPLEX));

opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__FILLOK, false, false, 0x00010001));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINESTARTARROWHEAD, false, false, 0x0));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDARROWHEAD, false, false, 0x0));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEENDCAPSTYLE, false, false, 0x0));

opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID));
opt.setEscherProperty(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT));
opt.setEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT));
opt.setEscherProperty(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT));
opt.setEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0));

EscherRecord anchor = getAnchor().getEscherAnchor();
clientData.setRecordId(EscherClientDataRecord.RECORD_ID);
clientData.setOptions((short) 0x0000);

spContainer.addChildRecord(sp);
spContainer.addChildRecord(opt);
spContainer.addChildRecord(anchor);
spContainer.addChildRecord(clientData);

return spContainer;
}

@Override
/**
* Creates the low level OBJ record for this shape.
*/
protected ObjRecord createObjRecord() {
return null;
}

public int[] getXPoints()
{
return xPoints;
ObjRecord obj = new ObjRecord();
CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
c.setObjectType(OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING);
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 int[] getYPoints()
{
return yPoints;
public int[] getXPoints() {
EscherArrayProperty verticesProp = _optRecord.lookup(EscherProperties.GEOMETRY__VERTICES);
if (null == verticesProp){
return new int[]{};
}
int []array = new int[verticesProp.getNumberOfElementsInArray()-1];
for (int i=0; i< verticesProp.getNumberOfElementsInArray()-1; i++){
byte[] property = verticesProp.getElement(i);
short x = LittleEndian.getShort(property, 0);
array[i] = x;
}
return array;
}

public void setPoints(int[] xPoints, int[] yPoints)
{
this.xPoints = cloneArray(xPoints);
this.yPoints = cloneArray(yPoints);
public int[] getYPoints() {
EscherArrayProperty verticesProp = _optRecord.lookup(EscherProperties.GEOMETRY__VERTICES);
if (null == verticesProp){
return new int[]{};
}
int []array = new int[verticesProp.getNumberOfElementsInArray()-1];
for (int i=0; i< verticesProp.getNumberOfElementsInArray()-1; i++){
byte[] property = verticesProp.getElement(i);
short x = LittleEndian.getShort(property, 2);
array[i] = x;
}
return array;
}

private int[] cloneArray( int[] a )
{
int[] result = new int[a.length];
for ( int i = 0; i < a.length; i++ )
result[i] = a[i];

return result;
public void setPoints(int[] xPoints, int[] yPoints) {
if (xPoints.length != yPoints.length){
System.out.println("xPoint.length must be equal to yPoints.length");
return;
}
if (xPoints.length == 0){
System.out.println("HSSFPolygon must have at least one point");
}
EscherArrayProperty verticesProp = new EscherArrayProperty(EscherProperties.GEOMETRY__VERTICES, false, new byte[0] );
verticesProp.setNumberOfElementsInArray(xPoints.length+1);
verticesProp.setNumberOfElementsInMemory(xPoints.length+1);
verticesProp.setSizeOfElements(0xFFF0);
for (int i = 0; i < xPoints.length; i++)
{
byte[] data = new byte[4];
LittleEndian.putShort(data, 0, (short)xPoints[i]);
LittleEndian.putShort(data, 2, (short)yPoints[i]);
verticesProp.setElement(i, data);
}
int point = xPoints.length;
byte[] data = new byte[4];
LittleEndian.putShort(data, 0, (short)xPoints[0]);
LittleEndian.putShort(data, 2, (short)yPoints[0]);
verticesProp.setElement(point, data);
setPropertyValue(verticesProp);

EscherArrayProperty segmentsProp = new EscherArrayProperty(EscherProperties.GEOMETRY__SEGMENTINFO, false, null );
segmentsProp.setSizeOfElements(0x0002);
segmentsProp.setNumberOfElementsInArray(xPoints.length * 2 + 4);
segmentsProp.setNumberOfElementsInMemory(xPoints.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 < xPoints.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 } );
setPropertyValue(segmentsProp);
}

/**
* Defines the width and height of the points in the polygon
*
* @param width
* @param height
*/
public void setPolygonDrawArea( int width, int height )
{
this.drawAreaWidth = width;
this.drawAreaHeight = height;
public void setPolygonDrawArea(int width, int height) {
setPropertyValue(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, width));
setPropertyValue(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, height));
}

public int getDrawAreaWidth()
{
return drawAreaWidth;
public int getDrawAreaWidth() {
EscherSimpleProperty property = _optRecord.lookup(EscherProperties.GEOMETRY__RIGHT);
return property == null ? 100: property.getPropertyValue();
}

public int getDrawAreaHeight()
{
return drawAreaHeight;
public int getDrawAreaHeight() {
EscherSimpleProperty property = _optRecord.lookup(EscherProperties.GEOMETRY__BOTTOM);
return property == null ? 100: property.getPropertyValue();
}


@Override
void afterInsert(HSSFPatriarch patriarch) {
EscherAggregate agg = patriarch._getBoundAggregate();
agg.associateShapeToObjRecord(_escherContainer.getChildById(EscherClientDataRecord.RECORD_ID), getObjRecord());
}
}
9 changes: 0 additions & 9 deletions src/java/org/apache/poi/hssf/usermodel/HSSFShape.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ public HSSFShape(HSSFShape parent, HSSFAnchor anchor) {
this.anchor = anchor;
this._escherContainer = createSpContainer();
_optRecord = _escherContainer.getChildById(EscherOptRecord.RECORD_ID);
addStandardOptions(_optRecord);
_objRecord = createObjRecord();

}
Expand All @@ -87,14 +86,6 @@ void setShapeId(int shapeId){
CommonObjectDataSubRecord cod = (CommonObjectDataSubRecord) _objRecord.getSubRecords().get(0);
cod.setObjectId((short) (shapeId-1024));
}

private void addStandardOptions(EscherOptRecord optRecord){
setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEDASHING, LINESTYLE_SOLID));
setPropertyValue(new EscherSimpleProperty(EscherProperties.LINESTYLE__LINEWIDTH, LINEWIDTH_DEFAULT));
setPropertyValue(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, FILL__FILLCOLOR_DEFAULT));
setPropertyValue(new EscherRGBProperty(EscherProperties.LINESTYLE__COLOR, LINESTYLE__COLOR_DEFAULT));
setPropertyValue(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 0x0));
}

int getShapeId(){
return ((EscherSpRecord)_escherContainer.getChildById(EscherSpRecord.RECORD_ID)).getShapeId();
Expand Down
16 changes: 10 additions & 6 deletions src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@

package org.apache.poi.hssf.usermodel;

import org.apache.poi.ddf.EscherClientDataRecord;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.ddf.EscherSpgrRecord;
import org.apache.poi.ddf.EscherTextboxRecord;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.model.TextboxShape;
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
import org.apache.poi.hssf.record.EscherAggregate;
Expand Down Expand Up @@ -124,6 +119,15 @@ public static void createShapeTree(EscherContainerRecord container, EscherAggreg
case CommonObjectDataSubRecord.OBJECT_TYPE_RECTANGLE:
shape = new HSSFSimpleShape(container, objRecord);
break;
case CommonObjectDataSubRecord.OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING:
EscherOptRecord optRecord = container.getChildById(EscherOptRecord.RECORD_ID);
EscherProperty property = optRecord.lookup(EscherProperties.GEOMETRY__VERTICES);
if (null != property){
shape = new HSSFPolygon(container, objRecord);
} else {
shape = new HSSFSimpleShape(container, objRecord);
}
break;
case CommonObjectDataSubRecord.OBJECT_TYPE_TEXT:
shape = new HSSFTextbox(container, objRecord, txtRecord);
break;
Expand Down
Loading

0 comments on commit 4c43845

Please sign in to comment.