280 lines
9.3 KiB
Java
280 lines
9.3 KiB
Java
package jxl.biff.drawing;
|
|
|
|
import common.Assert;
|
|
import common.Logger;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import jxl.biff.ByteData;
|
|
import jxl.read.biff.Record;
|
|
import jxl.write.biff.File;
|
|
|
|
public class DrawingGroup implements EscherStream {
|
|
private static Logger logger = Logger.getLogger(DrawingGroup.class);
|
|
|
|
private byte[] drawingData;
|
|
|
|
private EscherContainer escherData;
|
|
|
|
private BStoreContainer bstoreContainer;
|
|
|
|
private boolean initialized;
|
|
|
|
private ArrayList drawings;
|
|
|
|
private int numBlips;
|
|
|
|
private int numCharts;
|
|
|
|
private int drawingGroupId;
|
|
|
|
private boolean drawingsOmitted;
|
|
|
|
private Origin origin;
|
|
|
|
private HashMap imageFiles;
|
|
|
|
private int maxObjectId;
|
|
|
|
private int maxShapeId;
|
|
|
|
public DrawingGroup(Origin o) {
|
|
this.origin = o;
|
|
this.initialized = (o == Origin.WRITE);
|
|
this.drawings = new ArrayList();
|
|
this.imageFiles = new HashMap();
|
|
this.drawingsOmitted = false;
|
|
this.maxObjectId = 1;
|
|
this.maxShapeId = 1024;
|
|
}
|
|
|
|
public DrawingGroup(DrawingGroup dg) {
|
|
this.drawingData = dg.drawingData;
|
|
this.escherData = dg.escherData;
|
|
this.bstoreContainer = dg.bstoreContainer;
|
|
this.initialized = dg.initialized;
|
|
this.drawingData = dg.drawingData;
|
|
this.escherData = dg.escherData;
|
|
this.bstoreContainer = dg.bstoreContainer;
|
|
this.numBlips = dg.numBlips;
|
|
this.numCharts = dg.numCharts;
|
|
this.drawingGroupId = dg.drawingGroupId;
|
|
this.drawingsOmitted = dg.drawingsOmitted;
|
|
this.origin = dg.origin;
|
|
this.imageFiles = (HashMap)dg.imageFiles.clone();
|
|
this.maxObjectId = dg.maxObjectId;
|
|
this.maxShapeId = dg.maxShapeId;
|
|
this.drawings = new ArrayList();
|
|
}
|
|
|
|
public void add(MsoDrawingGroupRecord mso) {
|
|
addData(mso.getData());
|
|
}
|
|
|
|
public void add(Record cont) {
|
|
addData(cont.getData());
|
|
}
|
|
|
|
private void addData(byte[] msodata) {
|
|
if (this.drawingData == null) {
|
|
this.drawingData = new byte[msodata.length];
|
|
System.arraycopy(msodata, 0, this.drawingData, 0, msodata.length);
|
|
return;
|
|
}
|
|
byte[] newdata = new byte[this.drawingData.length + msodata.length];
|
|
System.arraycopy(this.drawingData, 0, newdata, 0, this.drawingData.length);
|
|
System.arraycopy(msodata, 0, newdata, this.drawingData.length, msodata.length);
|
|
this.drawingData = newdata;
|
|
}
|
|
|
|
final void addDrawing(DrawingGroupObject d) {
|
|
this.drawings.add(d);
|
|
this.maxObjectId = Math.max(this.maxObjectId, d.getObjectId());
|
|
this.maxShapeId = Math.max(this.maxShapeId, d.getShapeId());
|
|
}
|
|
|
|
public void add(Chart c) {
|
|
this.numCharts++;
|
|
}
|
|
|
|
public void add(DrawingGroupObject d) {
|
|
if (this.origin == Origin.READ) {
|
|
this.origin = Origin.READ_WRITE;
|
|
BStoreContainer bsc = getBStoreContainer();
|
|
Dgg dgg = (Dgg)this.escherData.getChildren()[0];
|
|
this.drawingGroupId = (dgg.getCluster(1)).drawingGroupId - this.numBlips - 1;
|
|
this.numBlips = (bsc != null) ? bsc.getNumBlips() : 0;
|
|
if (bsc != null)
|
|
Assert.verify((this.numBlips == bsc.getNumBlips()));
|
|
}
|
|
if (!(d instanceof Drawing)) {
|
|
this.maxObjectId++;
|
|
this.maxShapeId++;
|
|
d.setDrawingGroup(this);
|
|
d.setObjectId(this.maxObjectId, this.numBlips + 1, this.maxShapeId);
|
|
if (this.drawings.size() > this.maxObjectId)
|
|
logger.warn("drawings length " + this.drawings.size() + " exceeds the max object id " + this.maxObjectId);
|
|
return;
|
|
}
|
|
Drawing drawing = (Drawing)d;
|
|
Drawing refImage = (Drawing)this.imageFiles.get(d.getImageFilePath());
|
|
if (refImage == null) {
|
|
this.maxObjectId++;
|
|
this.maxShapeId++;
|
|
this.drawings.add(drawing);
|
|
drawing.setDrawingGroup(this);
|
|
drawing.setObjectId(this.maxObjectId, this.numBlips + 1, this.maxShapeId);
|
|
this.numBlips++;
|
|
this.imageFiles.put(drawing.getImageFilePath(), drawing);
|
|
} else {
|
|
refImage.setReferenceCount(refImage.getReferenceCount() + 1);
|
|
drawing.setDrawingGroup(this);
|
|
drawing.setObjectId(refImage.getObjectId(), refImage.getBlipId(), refImage.getShapeId());
|
|
}
|
|
}
|
|
|
|
public void remove(DrawingGroupObject d) {
|
|
if (getBStoreContainer() == null)
|
|
return;
|
|
if (this.origin == Origin.READ) {
|
|
this.origin = Origin.READ_WRITE;
|
|
this.numBlips = getBStoreContainer().getNumBlips();
|
|
Dgg dgg = (Dgg)this.escherData.getChildren()[0];
|
|
this.drawingGroupId = (dgg.getCluster(1)).drawingGroupId - this.numBlips - 1;
|
|
}
|
|
EscherRecord[] children = getBStoreContainer().getChildren();
|
|
BlipStoreEntry bse = (BlipStoreEntry)children[d.getBlipId() - 1];
|
|
bse.dereference();
|
|
if (bse.getReferenceCount() == 0) {
|
|
getBStoreContainer().remove(bse);
|
|
for (Iterator i = this.drawings.iterator(); i.hasNext(); ) {
|
|
DrawingGroupObject drawing = i.next();
|
|
if (drawing.getBlipId() > d.getBlipId())
|
|
drawing.setObjectId(drawing.getObjectId(), drawing.getBlipId() - 1, drawing.getShapeId());
|
|
}
|
|
this.numBlips--;
|
|
}
|
|
}
|
|
|
|
private void initialize() {
|
|
EscherRecordData er = new EscherRecordData(this, 0);
|
|
Assert.verify(er.isContainer());
|
|
this.escherData = new EscherContainer(er);
|
|
Assert.verify((this.escherData.getLength() == this.drawingData.length));
|
|
Assert.verify((this.escherData.getType() == EscherRecordType.DGG_CONTAINER));
|
|
this.initialized = true;
|
|
}
|
|
|
|
private BStoreContainer getBStoreContainer() {
|
|
if (this.bstoreContainer == null) {
|
|
if (!this.initialized)
|
|
initialize();
|
|
EscherRecord[] children = this.escherData.getChildren();
|
|
if (children.length > 1 && children[1].getType() == EscherRecordType.BSTORE_CONTAINER)
|
|
this.bstoreContainer = (BStoreContainer)children[1];
|
|
}
|
|
return this.bstoreContainer;
|
|
}
|
|
|
|
public byte[] getData() {
|
|
return this.drawingData;
|
|
}
|
|
|
|
public void write(File outputFile) throws IOException {
|
|
if (this.origin == Origin.WRITE) {
|
|
DggContainer dggContainer = new DggContainer();
|
|
Dgg dgg = new Dgg(this.numBlips + this.numCharts + 1, this.numBlips);
|
|
dgg.addCluster(1, 0);
|
|
dgg.addCluster(this.numBlips + 1, 0);
|
|
dggContainer.add(dgg);
|
|
int drawingsAdded = 0;
|
|
BStoreContainer bstoreCont = new BStoreContainer();
|
|
for (Iterator i = this.drawings.iterator(); i.hasNext(); ) {
|
|
Object o = i.next();
|
|
if (o instanceof Drawing) {
|
|
Drawing d = (Drawing)o;
|
|
BlipStoreEntry bse = new BlipStoreEntry(d);
|
|
bstoreCont.add(bse);
|
|
drawingsAdded++;
|
|
}
|
|
}
|
|
if (drawingsAdded > 0) {
|
|
bstoreCont.setNumBlips(drawingsAdded);
|
|
dggContainer.add(bstoreCont);
|
|
}
|
|
Opt opt = new Opt();
|
|
dggContainer.add(opt);
|
|
SplitMenuColors splitMenuColors = new SplitMenuColors();
|
|
dggContainer.add(splitMenuColors);
|
|
this.drawingData = dggContainer.getData();
|
|
} else if (this.origin == Origin.READ_WRITE) {
|
|
DggContainer dggContainer = new DggContainer();
|
|
Dgg dgg = new Dgg(this.numBlips + this.numCharts + 1, this.numBlips);
|
|
dgg.addCluster(1, 0);
|
|
dgg.addCluster(this.drawingGroupId + this.numBlips + 1, 0);
|
|
dggContainer.add(dgg);
|
|
BStoreContainer bstoreCont = new BStoreContainer();
|
|
bstoreCont.setNumBlips(this.numBlips);
|
|
BStoreContainer readBStoreContainer = getBStoreContainer();
|
|
if (readBStoreContainer != null) {
|
|
EscherRecord[] children = readBStoreContainer.getChildren();
|
|
for (int j = 0; j < children.length; j++) {
|
|
BlipStoreEntry bse = (BlipStoreEntry)children[j];
|
|
bstoreCont.add(bse);
|
|
}
|
|
}
|
|
for (Iterator i = this.drawings.iterator(); i.hasNext(); ) {
|
|
DrawingGroupObject dgo = i.next();
|
|
if (dgo instanceof Drawing) {
|
|
Drawing d = (Drawing)dgo;
|
|
if (d.getOrigin() != Origin.READ) {
|
|
BlipStoreEntry bse = new BlipStoreEntry(d);
|
|
bstoreCont.add(bse);
|
|
}
|
|
}
|
|
}
|
|
dggContainer.add(bstoreCont);
|
|
Opt opt = new Opt();
|
|
opt.addProperty(191, false, false, 524296);
|
|
opt.addProperty(385, false, false, 134217737);
|
|
opt.addProperty(448, false, false, 134217792);
|
|
dggContainer.add(opt);
|
|
SplitMenuColors splitMenuColors = new SplitMenuColors();
|
|
dggContainer.add(splitMenuColors);
|
|
this.drawingData = dggContainer.getData();
|
|
}
|
|
MsoDrawingGroupRecord msodg = new MsoDrawingGroupRecord(this.drawingData);
|
|
outputFile.write((ByteData)msodg);
|
|
}
|
|
|
|
final int getNumberOfBlips() {
|
|
return this.numBlips;
|
|
}
|
|
|
|
byte[] getImageData(int blipId) {
|
|
this.numBlips = getBStoreContainer().getNumBlips();
|
|
Assert.verify((blipId <= this.numBlips));
|
|
Assert.verify((this.origin == Origin.READ || this.origin == Origin.READ_WRITE));
|
|
EscherRecord[] children = getBStoreContainer().getChildren();
|
|
BlipStoreEntry bse = (BlipStoreEntry)children[blipId - 1];
|
|
return bse.getImageData();
|
|
}
|
|
|
|
public void setDrawingsOmitted(MsoDrawingRecord mso, ObjRecord obj) {
|
|
this.drawingsOmitted = true;
|
|
if (obj != null)
|
|
this.maxObjectId = Math.max(this.maxObjectId, obj.getObjectId());
|
|
}
|
|
|
|
public boolean hasDrawingsOmitted() {
|
|
return this.drawingsOmitted;
|
|
}
|
|
|
|
public void updateData(DrawingGroup dg) {
|
|
this.drawingsOmitted = dg.drawingsOmitted;
|
|
this.maxObjectId = dg.maxObjectId;
|
|
this.maxShapeId = dg.maxShapeId;
|
|
}
|
|
}
|