first commit

This commit is contained in:
2025-07-28 13:56:49 +05:30
commit e9eb805edb
3438 changed files with 520990 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
package jxl.biff.drawing;
import common.Logger;
class BStoreContainer extends EscherContainer {
private static Logger logger = Logger.getLogger(BStoreContainer.class);
private int numBlips;
public BStoreContainer(EscherRecordData erd) {
super(erd);
this.numBlips = getInstance();
}
public BStoreContainer() {
super(EscherRecordType.BSTORE_CONTAINER);
}
void setNumBlips(int count) {
this.numBlips = count;
setInstance(this.numBlips);
}
public int getNumBlips() {
return this.numBlips;
}
public BlipStoreEntry getDrawing(int i) {
EscherRecord[] children = getChildren();
BlipStoreEntry bse = (BlipStoreEntry)children[i];
return bse;
}
}

View File

@@ -0,0 +1,84 @@
package jxl.biff.drawing;
import common.Assert;
import common.Logger;
import java.io.IOException;
import jxl.biff.IntegerHelper;
class BlipStoreEntry extends EscherAtom {
private static Logger logger = Logger.getLogger(BlipStoreEntry.class);
private BlipType type;
private byte[] data;
private int imageDataLength;
private int referenceCount;
private boolean write;
private static final int IMAGE_DATA_OFFSET = 61;
public BlipStoreEntry(EscherRecordData erd) {
super(erd);
this.type = BlipType.getType(getInstance());
this.write = false;
byte[] bytes = getBytes();
this.referenceCount = IntegerHelper.getInt(bytes[24], bytes[25], bytes[26], bytes[27]);
}
public BlipStoreEntry(Drawing d) throws IOException {
super(EscherRecordType.BSE);
this.type = BlipType.PNG;
setVersion(2);
setInstance(this.type.getValue());
byte[] imageData = d.getImageBytes();
this.imageDataLength = imageData.length;
this.data = new byte[this.imageDataLength + 61];
System.arraycopy(imageData, 0, this.data, 61, this.imageDataLength);
this.referenceCount = d.getReferenceCount();
this.write = true;
}
public BlipType getBlipType() {
return this.type;
}
public byte[] getData() {
if (this.write) {
this.data[0] = (byte)this.type.getValue();
this.data[1] = (byte)this.type.getValue();
IntegerHelper.getFourBytes(this.imageDataLength + 8 + 17, this.data, 20);
IntegerHelper.getFourBytes(this.referenceCount, this.data, 24);
IntegerHelper.getFourBytes(0, this.data, 28);
this.data[32] = 0;
this.data[33] = 0;
this.data[34] = 126;
this.data[35] = 1;
this.data[36] = 0;
this.data[37] = 110;
IntegerHelper.getTwoBytes(61470, this.data, 38);
IntegerHelper.getFourBytes(this.imageDataLength + 17, this.data, 40);
} else {
this.data = getBytes();
}
return setHeaderData(this.data);
}
void dereference() {
this.referenceCount--;
Assert.verify((this.referenceCount >= 0));
}
int getReferenceCount() {
return this.referenceCount;
}
byte[] getImageData() {
byte[] allData = getBytes();
byte[] imageData = new byte[allData.length - 61];
System.arraycopy(allData, 61, imageData, 0, imageData.length);
return imageData;
}
}

View File

@@ -0,0 +1,57 @@
package jxl.biff.drawing;
final class BlipType {
private int value;
private String desc;
private static BlipType[] types = new BlipType[0];
private BlipType(int val, String d) {
this.value = val;
this.desc = d;
BlipType[] newtypes = new BlipType[types.length + 1];
System.arraycopy(types, 0, newtypes, 0, types.length);
newtypes[types.length] = this;
types = newtypes;
}
public String getDescription() {
return this.desc;
}
public int getValue() {
return this.value;
}
public static BlipType getType(int val) {
BlipType type = UNKNOWN;
for (int i = 0; i < types.length; i++) {
if ((types[i]).value == val) {
type = types[i];
break;
}
}
return type;
}
public static final BlipType ERROR = new BlipType(0, "Error");
public static final BlipType UNKNOWN = new BlipType(1, "Unknown");
public static final BlipType EMF = new BlipType(2, "EMF");
public static final BlipType WMF = new BlipType(3, "WMF");
public static final BlipType PICT = new BlipType(4, "PICT");
public static final BlipType JPEG = new BlipType(5, "JPEG");
public static final BlipType PNG = new BlipType(6, "PNG");
public static final BlipType DIB = new BlipType(7, "DIB");
public static final BlipType FIRST_CLIENT = new BlipType(32, "FIRST");
public static final BlipType LAST_CLIENT = new BlipType(255, "LAST");
}

View File

@@ -0,0 +1,359 @@
package jxl.biff.drawing;
import common.Assert;
import common.Logger;
import java.io.IOException;
import jxl.WorkbookSettings;
import jxl.biff.ByteData;
import jxl.biff.ContinueRecord;
import jxl.biff.IntegerHelper;
import jxl.biff.StringHelper;
import jxl.write.biff.File;
public class Button implements DrawingGroupObject {
private static Logger logger = Logger.getLogger(Button.class);
private EscherContainer readSpContainer;
private EscherContainer spContainer;
private MsoDrawingRecord msoDrawingRecord;
private ObjRecord objRecord;
private boolean initialized = false;
private int objectId;
private int blipId;
private int shapeId;
private int column;
private int row;
private double width;
private double height;
private int referenceCount;
private EscherContainer escherData;
private Origin origin;
private DrawingGroup drawingGroup;
private DrawingData drawingData;
private ShapeType type;
private int drawingNumber;
private MsoDrawingRecord mso;
private TextObjectRecord txo;
private ContinueRecord text;
private ContinueRecord formatting;
private String commentText;
private WorkbookSettings workbookSettings;
public Button(MsoDrawingRecord mso, ObjRecord obj, DrawingData dd, DrawingGroup dg, WorkbookSettings ws) {
this.drawingGroup = dg;
this.msoDrawingRecord = mso;
this.drawingData = dd;
this.objRecord = obj;
this.initialized = false;
this.workbookSettings = ws;
this.origin = Origin.READ;
this.drawingData.addData(this.msoDrawingRecord.getData());
this.drawingNumber = this.drawingData.getNumDrawings() - 1;
this.drawingGroup.addDrawing(this);
Assert.verify((mso != null && obj != null));
initialize();
}
public Button(DrawingGroupObject dgo, DrawingGroup dg, WorkbookSettings ws) {
Button d = (Button)dgo;
Assert.verify((d.origin == Origin.READ));
this.msoDrawingRecord = d.msoDrawingRecord;
this.objRecord = d.objRecord;
this.initialized = false;
this.origin = Origin.READ;
this.drawingData = d.drawingData;
this.drawingGroup = dg;
this.drawingNumber = d.drawingNumber;
this.drawingGroup.addDrawing(this);
this.mso = d.mso;
this.txo = d.txo;
this.text = d.text;
this.formatting = d.formatting;
this.workbookSettings = ws;
}
private void initialize() {
this.readSpContainer = this.drawingData.getSpContainer(this.drawingNumber);
Assert.verify((this.readSpContainer != null));
EscherRecord[] children = this.readSpContainer.getChildren();
Sp sp = (Sp)this.readSpContainer.getChildren()[0];
this.objectId = this.objRecord.getObjectId();
this.shapeId = sp.getShapeId();
this.type = ShapeType.getType(sp.getShapeType());
if (this.type == ShapeType.UNKNOWN)
logger.warn("Unknown shape type");
ClientAnchor clientAnchor = null;
for (int i = 0; i < children.length && clientAnchor == null; i++) {
if (children[i].getType() == EscherRecordType.CLIENT_ANCHOR)
clientAnchor = (ClientAnchor)children[i];
}
if (clientAnchor == null) {
logger.warn("Client anchor not found");
} else {
this.column = (int)clientAnchor.getX1() - 1;
this.row = (int)clientAnchor.getY1() + 1;
}
this.initialized = true;
}
public final void setObjectId(int objid, int bip, int sid) {
this.objectId = objid;
this.blipId = bip;
this.shapeId = sid;
if (this.origin == Origin.READ)
this.origin = Origin.READ_WRITE;
}
public final int getObjectId() {
if (!this.initialized)
initialize();
return this.objectId;
}
public final int getShapeId() {
if (!this.initialized)
initialize();
return this.shapeId;
}
public final int getBlipId() {
if (!this.initialized)
initialize();
return this.blipId;
}
public MsoDrawingRecord getMsoDrawingRecord() {
return this.msoDrawingRecord;
}
public EscherContainer getSpContainer() {
if (!this.initialized)
initialize();
if (this.origin == Origin.READ)
return getReadSpContainer();
Assert.verify(false);
return this.spContainer;
}
public void setDrawingGroup(DrawingGroup dg) {
this.drawingGroup = dg;
}
public DrawingGroup getDrawingGroup() {
return this.drawingGroup;
}
public Origin getOrigin() {
return this.origin;
}
public int getReferenceCount() {
return this.referenceCount;
}
public void setReferenceCount(int r) {
this.referenceCount = r;
}
public double getX() {
if (!this.initialized)
initialize();
return this.column;
}
public void setX(double x) {
if (this.origin == Origin.READ) {
if (!this.initialized)
initialize();
this.origin = Origin.READ_WRITE;
}
this.column = (int)x;
}
public double getY() {
if (!this.initialized)
initialize();
return this.row;
}
public void setY(double y) {
if (this.origin == Origin.READ) {
if (!this.initialized)
initialize();
this.origin = Origin.READ_WRITE;
}
this.row = (int)y;
}
public double getWidth() {
if (!this.initialized)
initialize();
return this.width;
}
public void setWidth(double w) {
if (this.origin == Origin.READ) {
if (!this.initialized)
initialize();
this.origin = Origin.READ_WRITE;
}
this.width = w;
}
public double getHeight() {
if (!this.initialized)
initialize();
return this.height;
}
public void setHeight(double h) {
if (this.origin == Origin.READ) {
if (!this.initialized)
initialize();
this.origin = Origin.READ_WRITE;
}
this.height = h;
}
private EscherContainer getReadSpContainer() {
if (!this.initialized)
initialize();
return this.readSpContainer;
}
public byte[] getImageData() {
Assert.verify((this.origin == Origin.READ || this.origin == Origin.READ_WRITE));
if (!this.initialized)
initialize();
return this.drawingGroup.getImageData(this.blipId);
}
public ShapeType getType() {
return this.type;
}
public void setTextObject(TextObjectRecord t) {
this.txo = t;
}
public void setText(ContinueRecord t) {
this.text = t;
}
public void setFormatting(ContinueRecord t) {
this.formatting = t;
}
public byte[] getImageBytes() {
Assert.verify(false);
return null;
}
public String getImageFilePath() {
Assert.verify(false);
return null;
}
public void addMso(MsoDrawingRecord d) {
this.mso = d;
this.drawingData.addRawData(this.mso.getData());
}
public void writeAdditionalRecords(File outputFile) throws IOException {
if (this.origin == Origin.READ) {
outputFile.write((ByteData)this.objRecord);
if (this.mso != null)
outputFile.write((ByteData)this.mso);
outputFile.write((ByteData)this.txo);
outputFile.write((ByteData)this.text);
if (this.formatting != null)
outputFile.write((ByteData)this.formatting);
return;
}
Assert.verify(false);
ObjRecord objRecord = new ObjRecord(this.objectId, ObjRecord.EXCELNOTE);
outputFile.write((ByteData)objRecord);
ClientTextBox textBox = new ClientTextBox();
MsoDrawingRecord msod = new MsoDrawingRecord(textBox.getData());
outputFile.write((ByteData)msod);
TextObjectRecord txo = new TextObjectRecord(getText());
outputFile.write((ByteData)txo);
byte[] textData = new byte[this.commentText.length() * 2 + 1];
textData[0] = 1;
StringHelper.getUnicodeBytes(this.commentText, textData, 1);
ContinueRecord textContinue = new ContinueRecord(textData);
outputFile.write((ByteData)textContinue);
byte[] frData = new byte[16];
IntegerHelper.getTwoBytes(0, frData, 0);
IntegerHelper.getTwoBytes(0, frData, 2);
IntegerHelper.getTwoBytes(this.commentText.length(), frData, 8);
IntegerHelper.getTwoBytes(0, frData, 10);
ContinueRecord frContinue = new ContinueRecord(frData);
outputFile.write((ByteData)frContinue);
}
public void writeTailRecords(File outputFile) {}
public int getRow() {
return 0;
}
public int getColumn() {
return 0;
}
public String getText() {
if (this.commentText == null) {
Assert.verify((this.text != null));
byte[] td = this.text.getData();
if (td[0] == 0) {
this.commentText = StringHelper.getString(td, td.length - 1, 1, this.workbookSettings);
} else {
this.commentText = StringHelper.getUnicodeString(td, (td.length - 1) / 2, 1);
}
}
return this.commentText;
}
public int hashCode() {
return this.commentText.hashCode();
}
public void setButtonText(String t) {
this.commentText = t;
if (this.origin == Origin.READ)
this.origin = Origin.READ_WRITE;
}
public boolean isFirst() {
return this.mso.isFirst();
}
public boolean isFormObject() {
return true;
}
}

View File

@@ -0,0 +1,111 @@
package jxl.biff.drawing;
import common.Assert;
import common.Logger;
import jxl.WorkbookSettings;
import jxl.biff.ByteData;
import jxl.biff.IndexMapping;
import jxl.biff.IntegerHelper;
import jxl.biff.Type;
import jxl.read.biff.File;
public class Chart implements ByteData, EscherStream {
private static final Logger logger = Logger.getLogger(Chart.class);
private MsoDrawingRecord msoDrawingRecord;
private ObjRecord objRecord;
private int startpos;
private int endpos;
private File file;
private DrawingData drawingData;
private int drawingNumber;
private byte[] data;
private boolean initialized;
private WorkbookSettings workbookSettings;
public Chart(MsoDrawingRecord mso, ObjRecord obj, DrawingData dd, int sp, int ep, File f, WorkbookSettings ws) {
this.msoDrawingRecord = mso;
this.objRecord = obj;
this.startpos = sp;
this.endpos = ep;
this.file = f;
this.workbookSettings = ws;
if (this.msoDrawingRecord != null) {
this.drawingData = dd;
this.drawingData.addData(this.msoDrawingRecord.getRecord().getData());
this.drawingNumber = this.drawingData.getNumDrawings() - 1;
}
this.initialized = false;
Assert.verify(((mso != null && obj != null) || (mso == null && obj == null)));
}
public byte[] getBytes() {
if (!this.initialized)
initialize();
return this.data;
}
public byte[] getData() {
return this.msoDrawingRecord.getRecord().getData();
}
private void initialize() {
this.data = this.file.read(this.startpos, this.endpos - this.startpos);
this.initialized = true;
}
public void rationalize(IndexMapping xfMapping, IndexMapping fontMapping, IndexMapping formatMapping) {
if (!this.initialized)
initialize();
int pos = 0;
int code = 0;
int length = 0;
Type type = null;
while (pos < this.data.length) {
code = IntegerHelper.getInt(this.data[pos], this.data[pos + 1]);
length = IntegerHelper.getInt(this.data[pos + 2], this.data[pos + 3]);
type = Type.getType(code);
if (type == Type.FONTX) {
int fontind = IntegerHelper.getInt(this.data[pos + 4], this.data[pos + 5]);
IntegerHelper.getTwoBytes(fontMapping.getNewIndex(fontind), this.data, pos + 4);
} else if (type == Type.FBI) {
int fontind = IntegerHelper.getInt(this.data[pos + 12], this.data[pos + 13]);
IntegerHelper.getTwoBytes(fontMapping.getNewIndex(fontind), this.data, pos + 12);
} else if (type == Type.IFMT) {
int formind = IntegerHelper.getInt(this.data[pos + 4], this.data[pos + 5]);
IntegerHelper.getTwoBytes(formatMapping.getNewIndex(formind), this.data, pos + 4);
} else if (type == Type.ALRUNS) {
int numRuns = IntegerHelper.getInt(this.data[pos + 4], this.data[pos + 5]);
int fontPos = pos + 6;
for (int i = 0; i < numRuns; i++) {
int fontind = IntegerHelper.getInt(this.data[fontPos + 2], this.data[fontPos + 3]);
IntegerHelper.getTwoBytes(fontMapping.getNewIndex(fontind), this.data, fontPos + 2);
fontPos += 4;
}
}
pos += length + 4;
}
}
EscherContainer getSpContainer() {
EscherContainer spContainer = this.drawingData.getSpContainer(this.drawingNumber);
return spContainer;
}
MsoDrawingRecord getMsoDrawingRecord() {
return this.msoDrawingRecord;
}
ObjRecord getObjRecord() {
return this.objRecord;
}
}

View File

@@ -0,0 +1,77 @@
package jxl.biff.drawing;
import common.Logger;
import jxl.biff.IntegerHelper;
class ClientAnchor extends EscherAtom {
private static final Logger logger = Logger.getLogger(ClientAnchor.class);
private byte[] data;
private double x1;
private double y1;
private double x2;
private double y2;
public ClientAnchor(EscherRecordData erd) {
super(erd);
byte[] bytes = getBytes();
int x1Cell = IntegerHelper.getInt(bytes[2], bytes[3]);
int x1Fraction = IntegerHelper.getInt(bytes[4], bytes[5]);
this.x1 = x1Cell + x1Fraction / 1024.0D;
int y1Cell = IntegerHelper.getInt(bytes[6], bytes[7]);
int y1Fraction = IntegerHelper.getInt(bytes[8], bytes[9]);
this.y1 = y1Cell + y1Fraction / 256.0D;
int x2Cell = IntegerHelper.getInt(bytes[10], bytes[11]);
int x2Fraction = IntegerHelper.getInt(bytes[12], bytes[13]);
this.x2 = x2Cell + x2Fraction / 1024.0D;
int y2Cell = IntegerHelper.getInt(bytes[14], bytes[15]);
int y2Fraction = IntegerHelper.getInt(bytes[16], bytes[17]);
this.y2 = y2Cell + y2Fraction / 256.0D;
}
public ClientAnchor(double x1, double y1, double x2, double y2) {
super(EscherRecordType.CLIENT_ANCHOR);
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
byte[] getData() {
this.data = new byte[18];
IntegerHelper.getTwoBytes(2, this.data, 0);
IntegerHelper.getTwoBytes((int)this.x1, this.data, 2);
int x1fraction = (int)((this.x1 - (int)this.x1) * 1024.0D);
IntegerHelper.getTwoBytes(x1fraction, this.data, 4);
IntegerHelper.getTwoBytes((int)this.y1, this.data, 6);
int y1fraction = (int)((this.y1 - (int)this.y1) * 256.0D);
IntegerHelper.getTwoBytes(y1fraction, this.data, 8);
IntegerHelper.getTwoBytes((int)this.x2, this.data, 10);
int x2fraction = (int)((this.x2 - (int)this.x2) * 1024.0D);
IntegerHelper.getTwoBytes(x2fraction, this.data, 12);
IntegerHelper.getTwoBytes((int)this.y2, this.data, 14);
int y2fraction = (int)((this.y2 - (int)this.y2) * 256.0D);
IntegerHelper.getTwoBytes(y2fraction, this.data, 16);
return setHeaderData(this.data);
}
double getX1() {
return this.x1;
}
double getY1() {
return this.y1;
}
double getX2() {
return this.x2;
}
double getY2() {
return this.y2;
}
}

View File

@@ -0,0 +1,22 @@
package jxl.biff.drawing;
import common.Logger;
class ClientData extends EscherAtom {
private static Logger logger = Logger.getLogger(ClientData.class);
private byte[] data;
public ClientData(EscherRecordData erd) {
super(erd);
}
public ClientData() {
super(EscherRecordType.CLIENT_DATA);
}
byte[] getData() {
this.data = new byte[0];
return setHeaderData(this.data);
}
}

View File

@@ -0,0 +1,22 @@
package jxl.biff.drawing;
import common.Logger;
class ClientTextBox extends EscherAtom {
private static Logger logger = Logger.getLogger(ClientTextBox.class);
private byte[] data;
public ClientTextBox(EscherRecordData erd) {
super(erd);
}
public ClientTextBox() {
super(EscherRecordType.CLIENT_TEXT_BOX);
}
byte[] getData() {
this.data = new byte[0];
return setHeaderData(this.data);
}
}

View File

@@ -0,0 +1,405 @@
package jxl.biff.drawing;
import common.Assert;
import common.Logger;
import java.io.IOException;
import jxl.WorkbookSettings;
import jxl.biff.ByteData;
import jxl.biff.ContinueRecord;
import jxl.biff.IntegerHelper;
import jxl.biff.StringHelper;
import jxl.write.biff.File;
public class Comment implements DrawingGroupObject {
private static Logger logger = Logger.getLogger(Comment.class);
private EscherContainer readSpContainer;
private EscherContainer spContainer;
private MsoDrawingRecord msoDrawingRecord;
private ObjRecord objRecord;
private boolean initialized = false;
private int objectId;
private int blipId;
private int shapeId;
private int column;
private int row;
private double width;
private double height;
private int referenceCount;
private EscherContainer escherData;
private Origin origin;
private DrawingGroup drawingGroup;
private DrawingData drawingData;
private ShapeType type;
private int drawingNumber;
private MsoDrawingRecord mso;
private TextObjectRecord txo;
private NoteRecord note;
private ContinueRecord text;
private ContinueRecord formatting;
private String commentText;
private WorkbookSettings workbookSettings;
public Comment(MsoDrawingRecord mso, ObjRecord obj, DrawingData dd, DrawingGroup dg, WorkbookSettings ws) {
this.drawingGroup = dg;
this.msoDrawingRecord = mso;
this.drawingData = dd;
this.objRecord = obj;
this.initialized = false;
this.workbookSettings = ws;
this.origin = Origin.READ;
this.drawingData.addData(this.msoDrawingRecord.getData());
this.drawingNumber = this.drawingData.getNumDrawings() - 1;
this.drawingGroup.addDrawing(this);
Assert.verify((mso != null && obj != null));
if (!this.initialized)
initialize();
}
public Comment(DrawingGroupObject dgo, DrawingGroup dg, WorkbookSettings ws) {
Comment d = (Comment)dgo;
Assert.verify((d.origin == Origin.READ));
this.msoDrawingRecord = d.msoDrawingRecord;
this.objRecord = d.objRecord;
this.initialized = false;
this.origin = Origin.READ;
this.drawingData = d.drawingData;
this.drawingGroup = dg;
this.drawingNumber = d.drawingNumber;
this.drawingGroup.addDrawing(this);
this.mso = d.mso;
this.txo = d.txo;
this.text = d.text;
this.formatting = d.formatting;
this.note = d.note;
this.width = d.width;
this.height = d.height;
this.workbookSettings = ws;
}
public Comment(String text, int c, int r) {
this.initialized = true;
this.origin = Origin.WRITE;
this.column = c;
this.row = r;
this.referenceCount = 1;
this.type = ShapeType.TEXT_BOX;
this.commentText = text;
this.width = 3.0D;
this.height = 4.0D;
}
private void initialize() {
this.readSpContainer = this.drawingData.getSpContainer(this.drawingNumber);
Assert.verify((this.readSpContainer != null));
EscherRecord[] children = this.readSpContainer.getChildren();
Sp sp = (Sp)this.readSpContainer.getChildren()[0];
this.objectId = this.objRecord.getObjectId();
this.shapeId = sp.getShapeId();
this.type = ShapeType.getType(sp.getShapeType());
if (this.type == ShapeType.UNKNOWN)
logger.warn("Unknown shape type");
ClientAnchor clientAnchor = null;
for (int i = 0; i < children.length && clientAnchor == null; i++) {
if (children[i].getType() == EscherRecordType.CLIENT_ANCHOR)
clientAnchor = (ClientAnchor)children[i];
}
if (clientAnchor == null) {
logger.warn("client anchor not found");
} else {
this.column = (int)clientAnchor.getX1() - 1;
this.row = (int)clientAnchor.getY1() + 1;
this.width = clientAnchor.getX2() - clientAnchor.getX1();
this.height = clientAnchor.getY2() - clientAnchor.getY1();
}
this.initialized = true;
}
public final void setObjectId(int objid, int bip, int sid) {
this.objectId = objid;
this.blipId = bip;
this.shapeId = sid;
if (this.origin == Origin.READ)
this.origin = Origin.READ_WRITE;
}
public final int getObjectId() {
if (!this.initialized)
initialize();
return this.objectId;
}
public final int getShapeId() {
if (!this.initialized)
initialize();
return this.shapeId;
}
public final int getBlipId() {
if (!this.initialized)
initialize();
return this.blipId;
}
public MsoDrawingRecord getMsoDrawingRecord() {
return this.msoDrawingRecord;
}
public EscherContainer getSpContainer() {
if (!this.initialized)
initialize();
if (this.origin == Origin.READ)
return getReadSpContainer();
if (this.spContainer == null) {
this.spContainer = new SpContainer();
Sp sp = new Sp(this.type, this.shapeId, 2560);
this.spContainer.add(sp);
Opt opt = new Opt();
opt.addProperty(344, false, false, 0);
opt.addProperty(385, false, false, 134217808);
opt.addProperty(387, false, false, 134217808);
opt.addProperty(959, false, false, 131074);
this.spContainer.add(opt);
ClientAnchor clientAnchor = new ClientAnchor(this.column + 1.3D, Math.max(0.0D, this.row - 0.6D), this.column + 1.3D + this.width, this.row + this.height);
this.spContainer.add(clientAnchor);
ClientData clientData = new ClientData();
this.spContainer.add(clientData);
ClientTextBox clientTextBox = new ClientTextBox();
this.spContainer.add(clientTextBox);
}
return this.spContainer;
}
public void setDrawingGroup(DrawingGroup dg) {
this.drawingGroup = dg;
}
public DrawingGroup getDrawingGroup() {
return this.drawingGroup;
}
public Origin getOrigin() {
return this.origin;
}
public int getReferenceCount() {
return this.referenceCount;
}
public void setReferenceCount(int r) {
this.referenceCount = r;
}
public double getX() {
if (!this.initialized)
initialize();
return this.column;
}
public void setX(double x) {
if (this.origin == Origin.READ) {
if (!this.initialized)
initialize();
this.origin = Origin.READ_WRITE;
}
this.column = (int)x;
}
public double getY() {
if (!this.initialized)
initialize();
return this.row;
}
public void setY(double y) {
if (this.origin == Origin.READ) {
if (!this.initialized)
initialize();
this.origin = Origin.READ_WRITE;
}
this.row = (int)y;
}
public double getWidth() {
if (!this.initialized)
initialize();
return this.width;
}
public void setWidth(double w) {
if (this.origin == Origin.READ) {
if (!this.initialized)
initialize();
this.origin = Origin.READ_WRITE;
}
this.width = w;
}
public double getHeight() {
if (!this.initialized)
initialize();
return this.height;
}
public void setHeight(double h) {
if (this.origin == Origin.READ) {
if (!this.initialized)
initialize();
this.origin = Origin.READ_WRITE;
}
this.height = h;
}
private EscherContainer getReadSpContainer() {
if (!this.initialized)
initialize();
return this.readSpContainer;
}
public byte[] getImageData() {
Assert.verify((this.origin == Origin.READ || this.origin == Origin.READ_WRITE));
if (!this.initialized)
initialize();
return this.drawingGroup.getImageData(this.blipId);
}
public ShapeType getType() {
return this.type;
}
public void setTextObject(TextObjectRecord t) {
this.txo = t;
}
public void setNote(NoteRecord t) {
this.note = t;
}
public void setText(ContinueRecord t) {
this.text = t;
}
public void setFormatting(ContinueRecord t) {
this.formatting = t;
}
public byte[] getImageBytes() {
Assert.verify(false);
return null;
}
public String getImageFilePath() {
Assert.verify(false);
return null;
}
public void addMso(MsoDrawingRecord d) {
this.mso = d;
this.drawingData.addRawData(this.mso.getData());
}
public void writeAdditionalRecords(File outputFile) throws IOException {
if (this.origin == Origin.READ) {
outputFile.write((ByteData)this.objRecord);
if (this.mso != null)
outputFile.write((ByteData)this.mso);
outputFile.write((ByteData)this.txo);
outputFile.write((ByteData)this.text);
if (this.formatting != null)
outputFile.write((ByteData)this.formatting);
return;
}
ObjRecord objRecord = new ObjRecord(this.objectId, ObjRecord.EXCELNOTE);
outputFile.write((ByteData)objRecord);
ClientTextBox textBox = new ClientTextBox();
MsoDrawingRecord msod = new MsoDrawingRecord(textBox.getData());
outputFile.write((ByteData)msod);
TextObjectRecord txo = new TextObjectRecord(getText());
outputFile.write((ByteData)txo);
byte[] textData = new byte[this.commentText.length() * 2 + 1];
textData[0] = 1;
StringHelper.getUnicodeBytes(this.commentText, textData, 1);
ContinueRecord textContinue = new ContinueRecord(textData);
outputFile.write((ByteData)textContinue);
byte[] frData = new byte[16];
IntegerHelper.getTwoBytes(0, frData, 0);
IntegerHelper.getTwoBytes(0, frData, 2);
IntegerHelper.getTwoBytes(this.commentText.length(), frData, 8);
IntegerHelper.getTwoBytes(0, frData, 10);
ContinueRecord frContinue = new ContinueRecord(frData);
outputFile.write((ByteData)frContinue);
}
public void writeTailRecords(File outputFile) throws IOException {
if (this.origin == Origin.READ) {
outputFile.write((ByteData)this.note);
return;
}
NoteRecord noteRecord = new NoteRecord(this.column, this.row, this.objectId);
outputFile.write((ByteData)noteRecord);
}
public int getRow() {
return this.note.getRow();
}
public int getColumn() {
return this.note.getColumn();
}
public String getText() {
if (this.commentText == null) {
Assert.verify((this.text != null));
byte[] td = this.text.getData();
if (td[0] == 0) {
this.commentText = StringHelper.getString(td, td.length - 1, 1, this.workbookSettings);
} else {
this.commentText = StringHelper.getUnicodeString(td, (td.length - 1) / 2, 1);
}
}
return this.commentText;
}
public int hashCode() {
return this.commentText.hashCode();
}
public void setCommentText(String t) {
this.commentText = t;
if (this.origin == Origin.READ)
this.origin = Origin.READ_WRITE;
}
public boolean isFirst() {
return this.msoDrawingRecord.isFirst();
}
public boolean isFormObject() {
return true;
}
}

View File

@@ -0,0 +1,40 @@
package jxl.biff.drawing;
import jxl.biff.IntegerHelper;
class Dg extends EscherAtom {
private byte[] data;
private int drawingId;
private int shapeCount;
private int seed;
public Dg(EscherRecordData erd) {
super(erd);
this.drawingId = getInstance();
byte[] bytes = getBytes();
this.shapeCount = IntegerHelper.getInt(bytes[0], bytes[1], bytes[2], bytes[3]);
this.seed = IntegerHelper.getInt(bytes[4], bytes[5], bytes[6], bytes[7]);
}
public Dg(int numDrawings) {
super(EscherRecordType.DG);
this.drawingId = 1;
this.shapeCount = numDrawings + 1;
this.seed = 1024 + this.shapeCount + 1;
setInstance(this.drawingId);
}
public int getDrawingId() {
return this.drawingId;
}
byte[] getData() {
this.data = new byte[8];
IntegerHelper.getFourBytes(this.shapeCount, this.data, 0);
IntegerHelper.getFourBytes(this.seed, this.data, 4);
return setHeaderData(this.data);
}
}

View File

@@ -0,0 +1,7 @@
package jxl.biff.drawing;
class DgContainer extends EscherContainer {
public DgContainer() {
super(EscherRecordType.DG_CONTAINER);
}
}

View File

@@ -0,0 +1,91 @@
package jxl.biff.drawing;
import common.Logger;
import java.util.ArrayList;
import jxl.biff.IntegerHelper;
class Dgg extends EscherAtom {
private static Logger logger = Logger.getLogger(Dgg.class);
private byte[] data;
private int numClusters;
private int maxShapeId;
private int shapesSaved;
private int drawingsSaved;
private ArrayList clusters;
static final class Cluster {
int drawingGroupId;
int shapeIdsUsed;
Cluster(int dgId, int sids) {
this.drawingGroupId = dgId;
this.shapeIdsUsed = sids;
}
}
public Dgg(EscherRecordData erd) {
super(erd);
this.clusters = new ArrayList();
byte[] bytes = getBytes();
this.maxShapeId = IntegerHelper.getInt(bytes[0], bytes[1], bytes[2], bytes[3]);
this.numClusters = IntegerHelper.getInt(bytes[4], bytes[5], bytes[6], bytes[7]);
this.shapesSaved = IntegerHelper.getInt(bytes[8], bytes[9], bytes[10], bytes[11]);
this.drawingsSaved = IntegerHelper.getInt(bytes[12], bytes[13], bytes[14], bytes[15]);
int pos = 16;
for (int i = 0; i < this.numClusters; i++) {
int dgId = IntegerHelper.getInt(bytes[pos], bytes[pos + 1]);
int sids = IntegerHelper.getInt(bytes[pos + 2], bytes[pos + 3]);
Cluster c = new Cluster(dgId, sids);
this.clusters.add(c);
pos += 4;
}
}
public Dgg(int numShapes, int numDrawings) {
super(EscherRecordType.DGG);
this.shapesSaved = numShapes;
this.drawingsSaved = numDrawings;
this.clusters = new ArrayList();
}
void addCluster(int dgid, int sids) {
Cluster c = new Cluster(dgid, sids);
this.clusters.add(c);
}
byte[] getData() {
this.numClusters = this.clusters.size();
this.data = new byte[16 + this.numClusters * 4];
IntegerHelper.getFourBytes(1024 + this.shapesSaved, this.data, 0);
IntegerHelper.getFourBytes(this.numClusters, this.data, 4);
IntegerHelper.getFourBytes(this.shapesSaved, this.data, 8);
IntegerHelper.getFourBytes(1, this.data, 12);
int pos = 16;
for (int i = 0; i < this.numClusters; i++) {
Cluster c = this.clusters.get(i);
IntegerHelper.getTwoBytes(c.drawingGroupId, this.data, pos);
IntegerHelper.getTwoBytes(c.shapeIdsUsed, this.data, pos + 2);
pos += 4;
}
return setHeaderData(this.data);
}
int getShapesSaved() {
return this.shapesSaved;
}
int getDrawingsSaved() {
return this.drawingsSaved;
}
Cluster getCluster(int i) {
return this.clusters.get(i);
}
}

View File

@@ -0,0 +1,7 @@
package jxl.biff.drawing;
class DggContainer extends EscherContainer {
public DggContainer() {
super(EscherRecordType.DGG_CONTAINER);
}
}

View File

@@ -0,0 +1,345 @@
package jxl.biff.drawing;
import common.Assert;
import common.Logger;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import jxl.Image;
import jxl.biff.ByteData;
import jxl.write.biff.File;
public class Drawing implements DrawingGroupObject, Image {
private static Logger logger = Logger.getLogger(Drawing.class);
private EscherContainer readSpContainer;
private MsoDrawingRecord msoDrawingRecord;
private ObjRecord objRecord;
private boolean initialized = false;
private File imageFile;
private byte[] imageData;
private int objectId;
private int blipId;
private double x;
private double y;
private double width;
private double height;
private int referenceCount;
private EscherContainer escherData;
private Origin origin;
private DrawingGroup drawingGroup;
private DrawingData drawingData;
private ShapeType type;
private int shapeId;
private int drawingNumber;
public Drawing(MsoDrawingRecord mso, ObjRecord obj, DrawingData dd, DrawingGroup dg) {
this.drawingGroup = dg;
this.msoDrawingRecord = mso;
this.drawingData = dd;
this.objRecord = obj;
this.initialized = false;
this.origin = Origin.READ;
this.drawingData.addData(this.msoDrawingRecord.getData());
this.drawingNumber = this.drawingData.getNumDrawings() - 1;
this.drawingGroup.addDrawing(this);
Assert.verify((mso != null && obj != null));
initialize();
}
protected Drawing(DrawingGroupObject dgo, DrawingGroup dg) {
Drawing d = (Drawing)dgo;
Assert.verify((d.origin == Origin.READ));
this.msoDrawingRecord = d.msoDrawingRecord;
this.objRecord = d.objRecord;
this.initialized = false;
this.origin = Origin.READ;
this.drawingData = d.drawingData;
this.drawingGroup = dg;
this.drawingNumber = d.drawingNumber;
this.drawingGroup.addDrawing(this);
}
public Drawing(double x, double y, double width, double height, File image) {
this.imageFile = image;
this.initialized = true;
this.origin = Origin.WRITE;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.referenceCount = 1;
this.type = ShapeType.PICTURE_FRAME;
}
public Drawing(double x, double y, double width, double height, byte[] image) {
this.imageData = image;
this.initialized = true;
this.origin = Origin.WRITE;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.referenceCount = 1;
this.type = ShapeType.PICTURE_FRAME;
}
private void initialize() {
this.readSpContainer = this.drawingData.getSpContainer(this.drawingNumber);
Assert.verify((this.readSpContainer != null));
EscherRecord[] children = this.readSpContainer.getChildren();
Sp sp = (Sp)this.readSpContainer.getChildren()[0];
this.shapeId = sp.getShapeId();
this.objectId = this.objRecord.getObjectId();
this.type = ShapeType.getType(sp.getShapeType());
if (this.type == ShapeType.UNKNOWN)
logger.warn("Unknown shape type");
Opt opt = (Opt)this.readSpContainer.getChildren()[1];
if (opt.getProperty(260) != null)
this.blipId = (opt.getProperty(260)).value;
if (opt.getProperty(261) != null) {
this.imageFile = new File((opt.getProperty(261)).stringValue);
} else if (this.type == ShapeType.PICTURE_FRAME) {
logger.warn("no filename property for drawing");
this.imageFile = new File(Integer.toString(this.blipId));
}
ClientAnchor clientAnchor = null;
for (int i = 0; i < children.length && clientAnchor == null; i++) {
if (children[i].getType() == EscherRecordType.CLIENT_ANCHOR)
clientAnchor = (ClientAnchor)children[i];
}
if (clientAnchor == null) {
logger.warn("client anchor not found");
} else {
this.x = clientAnchor.getX1();
this.y = clientAnchor.getY1();
this.width = clientAnchor.getX2() - this.x;
this.height = clientAnchor.getY2() - this.y;
}
if (this.blipId == 0)
logger.warn("linked drawings are not supported");
this.initialized = true;
}
public File getImageFile() {
return this.imageFile;
}
public String getImageFilePath() {
if (this.imageFile == null)
return (this.blipId != 0) ? Integer.toString(this.blipId) : "__new__image__";
return this.imageFile.getPath();
}
public final void setObjectId(int objid, int bip, int sid) {
this.objectId = objid;
this.blipId = bip;
this.shapeId = sid;
if (this.origin == Origin.READ)
this.origin = Origin.READ_WRITE;
}
public final int getObjectId() {
if (!this.initialized)
initialize();
return this.objectId;
}
public int getShapeId() {
if (!this.initialized)
initialize();
return this.shapeId;
}
public final int getBlipId() {
if (!this.initialized)
initialize();
return this.blipId;
}
public MsoDrawingRecord getMsoDrawingRecord() {
return this.msoDrawingRecord;
}
public EscherContainer getSpContainer() {
if (!this.initialized)
initialize();
if (this.origin == Origin.READ)
return getReadSpContainer();
SpContainer spContainer = new SpContainer();
Sp sp = new Sp(this.type, this.shapeId, 2560);
spContainer.add(sp);
Opt opt = new Opt();
opt.addProperty(260, true, false, this.blipId);
if (this.type == ShapeType.PICTURE_FRAME) {
String filePath = (this.imageFile != null) ? this.imageFile.getPath() : "";
opt.addProperty(261, true, true, filePath.length() * 2, filePath);
opt.addProperty(447, false, false, 65536);
opt.addProperty(959, false, false, 524288);
spContainer.add(opt);
}
ClientAnchor clientAnchor = new ClientAnchor(this.x, this.y, this.x + this.width, this.y + this.height);
spContainer.add(clientAnchor);
ClientData clientData = new ClientData();
spContainer.add(clientData);
return spContainer;
}
public void setDrawingGroup(DrawingGroup dg) {
this.drawingGroup = dg;
}
public DrawingGroup getDrawingGroup() {
return this.drawingGroup;
}
public Origin getOrigin() {
return this.origin;
}
public int getReferenceCount() {
return this.referenceCount;
}
public void setReferenceCount(int r) {
this.referenceCount = r;
}
public double getX() {
if (!this.initialized)
initialize();
return this.x;
}
public void setX(double x) {
if (this.origin == Origin.READ) {
if (!this.initialized)
initialize();
this.origin = Origin.READ_WRITE;
}
this.x = x;
}
public double getY() {
if (!this.initialized)
initialize();
return this.y;
}
public void setY(double y) {
if (this.origin == Origin.READ) {
if (!this.initialized)
initialize();
this.origin = Origin.READ_WRITE;
}
this.y = y;
}
public double getWidth() {
if (!this.initialized)
initialize();
return this.width;
}
public void setWidth(double w) {
if (this.origin == Origin.READ) {
if (!this.initialized)
initialize();
this.origin = Origin.READ_WRITE;
}
this.width = w;
}
public double getHeight() {
if (!this.initialized)
initialize();
return this.height;
}
public void setHeight(double h) {
if (this.origin == Origin.READ) {
if (!this.initialized)
initialize();
this.origin = Origin.READ_WRITE;
}
this.height = h;
}
private EscherContainer getReadSpContainer() {
if (!this.initialized)
initialize();
return this.readSpContainer;
}
public byte[] getImageData() {
Assert.verify((this.origin == Origin.READ || this.origin == Origin.READ_WRITE));
if (!this.initialized)
initialize();
return this.drawingGroup.getImageData(this.blipId);
}
public byte[] getImageBytes() throws IOException {
if (this.origin == Origin.READ || this.origin == Origin.READ_WRITE)
return getImageData();
Assert.verify((this.origin == Origin.WRITE));
if (this.imageFile == null) {
Assert.verify((this.imageData != null));
return this.imageData;
}
byte[] data = new byte[(int)this.imageFile.length()];
FileInputStream fis = new FileInputStream(this.imageFile);
fis.read(data, 0, data.length);
fis.close();
return data;
}
public ShapeType getType() {
return this.type;
}
public void writeAdditionalRecords(File outputFile) throws IOException {
if (this.origin == Origin.READ) {
outputFile.write((ByteData)this.objRecord);
return;
}
ObjRecord objRecord = new ObjRecord(this.objectId, ObjRecord.PICTURE);
outputFile.write((ByteData)objRecord);
}
public void writeTailRecords(File outputFile) throws IOException {}
public double getColumn() {
return getX();
}
public double getRow() {
return getY();
}
public boolean isFirst() {
return this.msoDrawingRecord.isFirst();
}
public boolean isFormObject() {
return false;
}
}

View File

@@ -0,0 +1,93 @@
package jxl.biff.drawing;
import common.Assert;
import common.Logger;
import java.util.ArrayList;
public class DrawingData implements EscherStream {
private static Logger logger = Logger.getLogger(DrawingData.class);
private int numDrawings = 0;
private byte[] drawingData = null;
private boolean initialized = false;
private EscherRecord[] spContainers;
private void initialize() {
EscherRecordData er = new EscherRecordData(this, 0);
Assert.verify(er.isContainer());
EscherContainer dgContainer = new EscherContainer(er);
EscherRecord[] children = dgContainer.getChildren();
children = dgContainer.getChildren();
EscherContainer spgrContainer = null;
for (int i = 0; i < children.length && spgrContainer == null; i++) {
EscherRecord child = children[i];
if (child.getType() == EscherRecordType.SPGR_CONTAINER)
spgrContainer = (EscherContainer)child;
}
Assert.verify((spgrContainer != null));
EscherRecord[] spgrChildren = spgrContainer.getChildren();
boolean nestedContainers = false;
for (int j = 0; j < spgrChildren.length && !nestedContainers; j++) {
if (spgrChildren[j].getType() == EscherRecordType.SPGR_CONTAINER)
nestedContainers = true;
}
if (!nestedContainers) {
this.spContainers = spgrChildren;
} else {
ArrayList sps = new ArrayList();
getSpContainers(spgrContainer, sps);
this.spContainers = new EscherRecord[sps.size()];
this.spContainers = (EscherRecord[])sps.toArray((Object[])this.spContainers);
}
this.initialized = true;
}
private void getSpContainers(EscherContainer spgrContainer, ArrayList sps) {
EscherRecord[] spgrChildren = spgrContainer.getChildren();
for (int i = 0; i < spgrChildren.length; i++) {
if (spgrChildren[i].getType() == EscherRecordType.SP_CONTAINER) {
sps.add(spgrChildren[i]);
} else if (spgrChildren[i].getType() == EscherRecordType.SPGR_CONTAINER) {
getSpContainers((EscherContainer)spgrChildren[i], sps);
} else {
logger.warn("Spgr Containers contains a record other than Sp/Spgr containers");
}
}
}
public void addData(byte[] data) {
addRawData(data);
this.numDrawings++;
}
public void addRawData(byte[] data) {
if (this.drawingData == null) {
this.drawingData = data;
return;
}
byte[] newArray = new byte[this.drawingData.length + data.length];
System.arraycopy(this.drawingData, 0, newArray, 0, this.drawingData.length);
System.arraycopy(data, 0, newArray, this.drawingData.length, data.length);
this.drawingData = newArray;
this.initialized = false;
}
final int getNumDrawings() {
return this.numDrawings;
}
EscherContainer getSpContainer(int drawingNum) {
if (!this.initialized)
initialize();
EscherContainer spContainer = (EscherContainer)this.spContainers[drawingNum + 1];
Assert.verify((spContainer != null));
return spContainer;
}
public byte[] getData() {
return this.drawingData;
}
}

View File

@@ -0,0 +1,279 @@
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;
}
}

View File

@@ -0,0 +1,60 @@
package jxl.biff.drawing;
import java.io.IOException;
import jxl.write.biff.File;
public interface DrawingGroupObject {
void setObjectId(int paramInt1, int paramInt2, int paramInt3);
int getObjectId();
int getBlipId();
int getShapeId();
MsoDrawingRecord getMsoDrawingRecord();
EscherContainer getSpContainer();
void setDrawingGroup(DrawingGroup paramDrawingGroup);
DrawingGroup getDrawingGroup();
Origin getOrigin();
int getReferenceCount();
void setReferenceCount(int paramInt);
double getX();
void setX(double paramDouble);
double getY();
void setY(double paramDouble);
double getWidth();
void setWidth(double paramDouble);
double getHeight();
void setHeight(double paramDouble);
ShapeType getType();
byte[] getImageData();
byte[] getImageBytes() throws IOException;
String getImageFilePath();
void writeAdditionalRecords(File paramFile) throws IOException;
void writeTailRecords(File paramFile) throws IOException;
boolean isFirst();
boolean isFormObject();
}

View File

@@ -0,0 +1,20 @@
package jxl.biff.drawing;
import common.Logger;
class EscherAtom extends EscherRecord {
private static Logger logger = Logger.getLogger(EscherAtom.class);
public EscherAtom(EscherRecordData erd) {
super(erd);
}
protected EscherAtom(EscherRecordType type) {
super(type);
}
byte[] getData() {
logger.warn("escher atom getData called on object of type " + getClass().getName() + " code " + Integer.toString(getType().getValue(), 16));
return null;
}
}

View File

@@ -0,0 +1,99 @@
package jxl.biff.drawing;
import common.Logger;
import java.util.ArrayList;
import java.util.Iterator;
class EscherContainer extends EscherRecord {
private static Logger logger = Logger.getLogger(EscherContainer.class);
private boolean initialized;
private ArrayList children;
public EscherContainer(EscherRecordData erd) {
super(erd);
this.initialized = false;
this.children = new ArrayList();
}
protected EscherContainer(EscherRecordType type) {
super(type);
setContainer(true);
this.children = new ArrayList();
}
public EscherRecord[] getChildren() {
if (!this.initialized)
initialize();
Object[] ca = this.children.toArray((Object[])new EscherRecord[this.children.size()]);
return (EscherRecord[])ca;
}
public void add(EscherRecord child) {
this.children.add(child);
}
public void remove(EscherRecord child) {
this.children.remove(child);
}
private void initialize() {
int curpos = getPos() + 8;
int endpos = Math.min(getPos() + getLength(), getStreamLength());
EscherRecord newRecord = null;
while (curpos < endpos) {
EscherRecordData erd = new EscherRecordData(getEscherStream(), curpos);
EscherRecordType type = erd.getType();
if (type == EscherRecordType.DGG) {
newRecord = new Dgg(erd);
} else if (type == EscherRecordType.DG) {
newRecord = new Dg(erd);
} else if (type == EscherRecordType.BSTORE_CONTAINER) {
newRecord = new BStoreContainer(erd);
} else if (type == EscherRecordType.SPGR_CONTAINER) {
newRecord = new SpgrContainer(erd);
} else if (type == EscherRecordType.SP_CONTAINER) {
newRecord = new SpContainer(erd);
} else if (type == EscherRecordType.SPGR) {
newRecord = new Spgr(erd);
} else if (type == EscherRecordType.SP) {
newRecord = new Sp(erd);
} else if (type == EscherRecordType.CLIENT_ANCHOR) {
newRecord = new ClientAnchor(erd);
} else if (type == EscherRecordType.CLIENT_DATA) {
newRecord = new ClientData(erd);
} else if (type == EscherRecordType.BSE) {
newRecord = new BlipStoreEntry(erd);
} else if (type == EscherRecordType.OPT) {
newRecord = new Opt(erd);
} else if (type == EscherRecordType.SPLIT_MENU_COLORS) {
newRecord = new SplitMenuColors(erd);
} else if (type == EscherRecordType.CLIENT_TEXT_BOX) {
newRecord = new ClientTextBox(erd);
} else {
newRecord = new EscherAtom(erd);
}
this.children.add(newRecord);
curpos += newRecord.getLength();
}
this.initialized = true;
}
byte[] getData() {
if (!this.initialized)
initialize();
byte[] data = new byte[0];
for (Iterator i = this.children.iterator(); i.hasNext(); ) {
EscherRecord er = i.next();
byte[] childData = er.getData();
if (childData != null) {
byte[] newData = new byte[data.length + childData.length];
System.arraycopy(data, 0, newData, 0, data.length);
System.arraycopy(childData, 0, newData, data.length, childData.length);
data = newData;
}
}
return setHeaderData(data);
}
}

View File

@@ -0,0 +1,65 @@
package jxl.biff.drawing;
import common.Logger;
abstract class EscherRecord {
private static Logger logger = Logger.getLogger(EscherRecord.class);
protected EscherRecordData data;
protected static final int HEADER_LENGTH = 8;
protected EscherRecord(EscherRecordData erd) {
this.data = erd;
}
protected EscherRecord(EscherRecordType type) {
this.data = new EscherRecordData(type);
}
protected void setContainer(boolean cont) {
this.data.setContainer(cont);
}
public int getLength() {
return this.data.getLength() + 8;
}
protected final EscherStream getEscherStream() {
return this.data.getEscherStream();
}
protected final int getPos() {
return this.data.getPos();
}
protected final int getInstance() {
return this.data.getInstance();
}
protected final void setInstance(int i) {
this.data.setInstance(i);
}
protected final void setVersion(int v) {
this.data.setVersion(v);
}
public EscherRecordType getType() {
return this.data.getType();
}
final byte[] setHeaderData(byte[] d) {
return this.data.setHeaderData(d);
}
byte[] getBytes() {
return this.data.getBytes();
}
protected int getStreamLength() {
return this.data.getStreamLength();
}
abstract byte[] getData();
}

View File

@@ -0,0 +1,121 @@
package jxl.biff.drawing;
import common.Logger;
import jxl.biff.IntegerHelper;
final class EscherRecordData {
private static Logger logger = Logger.getLogger(EscherRecordData.class);
private int pos;
private int instance;
private int version;
private int recordId;
private int length;
private int streamLength;
private boolean container;
private EscherRecordType type;
private EscherStream escherStream;
public EscherRecordData(EscherStream dg, int p) {
this.escherStream = dg;
this.pos = p;
byte[] data = this.escherStream.getData();
this.streamLength = data.length;
int value = IntegerHelper.getInt(data[this.pos], data[this.pos + 1]);
this.instance = (value & 0xFFF0) >> 4;
this.version = value & 0xF;
this.recordId = IntegerHelper.getInt(data[this.pos + 2], data[this.pos + 3]);
this.length = IntegerHelper.getInt(data[this.pos + 4], data[this.pos + 5], data[this.pos + 6], data[this.pos + 7]);
if (this.version == 15) {
this.container = true;
} else {
this.container = false;
}
}
public EscherRecordData(EscherRecordType t) {
this.type = t;
this.recordId = this.type.getValue();
}
public boolean isContainer() {
return this.container;
}
public int getLength() {
return this.length;
}
public int getRecordId() {
return this.recordId;
}
EscherStream getDrawingGroup() {
return this.escherStream;
}
int getPos() {
return this.pos;
}
EscherRecordType getType() {
if (this.type == null)
this.type = EscherRecordType.getType(this.recordId);
return this.type;
}
int getInstance() {
return this.instance;
}
void setContainer(boolean c) {
this.container = c;
}
void setInstance(int inst) {
this.instance = inst;
}
void setLength(int l) {
this.length = l;
}
void setVersion(int v) {
this.version = v;
}
byte[] setHeaderData(byte[] d) {
byte[] data = new byte[d.length + 8];
System.arraycopy(d, 0, data, 8, d.length);
if (this.container)
this.version = 15;
int value = this.instance << 4;
value |= this.version;
IntegerHelper.getTwoBytes(value, data, 0);
IntegerHelper.getTwoBytes(this.recordId, data, 2);
IntegerHelper.getFourBytes(d.length, data, 4);
return data;
}
EscherStream getEscherStream() {
return this.escherStream;
}
byte[] getBytes() {
byte[] d = new byte[this.length];
System.arraycopy(this.escherStream.getData(), this.pos + 8, d, 0, this.length);
return d;
}
int getStreamLength() {
return this.streamLength;
}
}

View File

@@ -0,0 +1,62 @@
package jxl.biff.drawing;
final class EscherRecordType {
private int value;
private static EscherRecordType[] types = new EscherRecordType[0];
private EscherRecordType(int val) {
this.value = val;
EscherRecordType[] newtypes = new EscherRecordType[types.length + 1];
System.arraycopy(types, 0, newtypes, 0, types.length);
newtypes[types.length] = this;
types = newtypes;
}
public int getValue() {
return this.value;
}
public static EscherRecordType getType(int val) {
EscherRecordType type = UNKNOWN;
for (int i = 0; i < types.length; i++) {
if (val == (types[i]).value) {
type = types[i];
break;
}
}
return type;
}
public static final EscherRecordType UNKNOWN = new EscherRecordType(0);
public static final EscherRecordType DGG_CONTAINER = new EscherRecordType(61440);
public static final EscherRecordType BSTORE_CONTAINER = new EscherRecordType(61441);
public static final EscherRecordType DG_CONTAINER = new EscherRecordType(61442);
public static final EscherRecordType SPGR_CONTAINER = new EscherRecordType(61443);
public static final EscherRecordType SP_CONTAINER = new EscherRecordType(61444);
public static final EscherRecordType DGG = new EscherRecordType(61446);
public static final EscherRecordType BSE = new EscherRecordType(61447);
public static final EscherRecordType DG = new EscherRecordType(61448);
public static final EscherRecordType SPGR = new EscherRecordType(61449);
public static final EscherRecordType SP = new EscherRecordType(61450);
public static final EscherRecordType OPT = new EscherRecordType(61451);
public static final EscherRecordType CLIENT_ANCHOR = new EscherRecordType(61456);
public static final EscherRecordType CLIENT_DATA = new EscherRecordType(61457);
public static final EscherRecordType CLIENT_TEXT_BOX = new EscherRecordType(61453);
public static final EscherRecordType SPLIT_MENU_COLORS = new EscherRecordType(61726);
}

View File

@@ -0,0 +1,5 @@
package jxl.biff.drawing;
interface EscherStream {
byte[] getData();
}

View File

@@ -0,0 +1,23 @@
package jxl.biff.drawing;
import jxl.biff.Type;
import jxl.biff.WritableRecordData;
import jxl.read.biff.Record;
public class MsoDrawingGroupRecord extends WritableRecordData {
private byte[] data;
public MsoDrawingGroupRecord(Record t) {
super(t);
this.data = t.getData();
}
MsoDrawingGroupRecord(byte[] d) {
super(Type.MSODRAWINGGROUP);
this.data = d;
}
public byte[] getData() {
return this.data;
}
}

View File

@@ -0,0 +1,42 @@
package jxl.biff.drawing;
import common.Logger;
import jxl.biff.Type;
import jxl.biff.WritableRecordData;
import jxl.read.biff.Record;
public class MsoDrawingRecord extends WritableRecordData {
private static Logger logger = Logger.getLogger(MsoDrawingRecord.class);
private boolean first;
private byte[] data;
public MsoDrawingRecord(Record t) {
super(t);
this.data = getRecord().getData();
this.first = false;
}
public MsoDrawingRecord(byte[] d) {
super(Type.MSODRAWING);
this.data = d;
this.first = false;
}
public byte[] getData() {
return this.data;
}
public Record getRecord() {
return super.getRecord();
}
public void setFirst() {
this.first = true;
}
public boolean isFirst() {
return this.first;
}
}

View File

@@ -0,0 +1,63 @@
package jxl.biff.drawing;
import common.Logger;
import jxl.biff.IntegerHelper;
import jxl.biff.Type;
import jxl.biff.WritableRecordData;
import jxl.read.biff.Record;
public class NoteRecord extends WritableRecordData {
private static Logger logger = Logger.getLogger(NoteRecord.class);
private byte[] data;
private int row;
private int column;
private int objectId;
public NoteRecord(Record t) {
super(t);
this.data = getRecord().getData();
this.row = IntegerHelper.getInt(this.data[0], this.data[1]);
this.column = IntegerHelper.getInt(this.data[2], this.data[3]);
this.objectId = IntegerHelper.getInt(this.data[6], this.data[7]);
}
public NoteRecord(byte[] d) {
super(Type.NOTE);
this.data = d;
}
public NoteRecord(int c, int r, int id) {
super(Type.NOTE);
this.row = r;
this.column = c;
this.objectId = id;
}
public byte[] getData() {
if (this.data != null)
return this.data;
String author = "";
this.data = new byte[8 + author.length() + 4];
IntegerHelper.getTwoBytes(this.row, this.data, 0);
IntegerHelper.getTwoBytes(this.column, this.data, 2);
IntegerHelper.getTwoBytes(this.objectId, this.data, 6);
IntegerHelper.getTwoBytes(author.length(), this.data, 8);
return this.data;
}
int getRow() {
return this.row;
}
int getColumn() {
return this.column;
}
public int getObjectId() {
return this.objectId;
}
}

View File

@@ -0,0 +1,177 @@
package jxl.biff.drawing;
import common.Assert;
import common.Logger;
import jxl.biff.IntegerHelper;
import jxl.biff.Type;
import jxl.biff.WritableRecordData;
import jxl.read.biff.Record;
public class ObjRecord extends WritableRecordData {
private static final Logger logger = Logger.getLogger(ObjRecord.class);
private ObjType type;
private boolean read;
private int objectId;
private static final class ObjType {
public int value;
public String desc;
private static ObjType[] types = new ObjType[0];
ObjType(int v, String d) {
this.value = v;
this.desc = d;
ObjType[] oldtypes = types;
types = new ObjType[types.length + 1];
System.arraycopy(oldtypes, 0, types, 0, oldtypes.length);
types[oldtypes.length] = this;
}
public String toString() {
return this.desc;
}
public static ObjType getType(int val) {
ObjType retval = ObjRecord.UNKNOWN;
for (int i = 0; i < types.length && retval == ObjRecord.UNKNOWN; i++) {
if ((types[i]).value == val)
retval = types[i];
}
return retval;
}
}
public static final ObjType TBD2 = new ObjType(1, "TBD2");
public static final ObjType TBD = new ObjType(2, "TBD");
public static final ObjType CHART = new ObjType(5, "Chart");
public static final ObjType TEXT = new ObjType(6, "Text");
public static final ObjType BUTTON = new ObjType(7, "Button");
public static final ObjType PICTURE = new ObjType(8, "Picture");
public static final ObjType CHECKBOX = new ObjType(14, "Checkbox");
public static final ObjType OPTION = new ObjType(12, "Option");
public static final ObjType EDITBOX = new ObjType(13, "Edit Box");
public static final ObjType LABEL = new ObjType(14, "Label");
public static final ObjType DIALOGUEBOX = new ObjType(15, "Dialogue Box");
public static final ObjType LISTBOX = new ObjType(18, "List Box");
public static final ObjType GROUPBOX = new ObjType(19, "Group Box");
public static final ObjType COMBOBOX = new ObjType(20, "Combo Box");
public static final ObjType MSOFFICEDRAWING = new ObjType(30, "MS Office Drawing");
public static final ObjType FORMCONTROL = new ObjType(20, "Form Combo Box");
public static final ObjType EXCELNOTE = new ObjType(25, "Excel Note");
public static final ObjType UNKNOWN = new ObjType(255, "Unknown");
private static final int COMMON_DATA_LENGTH = 22;
private static final int CLIPBOARD_FORMAT_LENGTH = 6;
private static final int PICTURE_OPTION_LENGTH = 6;
private static final int NOTE_STRUCTURE_LENGTH = 26;
private static final int END_LENGTH = 4;
public ObjRecord(Record t) {
super(t);
byte[] data = t.getData();
int objtype = IntegerHelper.getInt(data[4], data[5]);
this.read = true;
this.type = ObjType.getType(objtype);
if (this.type == UNKNOWN)
logger.warn("unknown object type code " + objtype);
this.objectId = IntegerHelper.getInt(data[6], data[7]);
}
ObjRecord(int objId, ObjType t) {
super(Type.OBJ);
this.objectId = objId;
this.type = t;
}
public byte[] getData() {
if (this.read)
return getRecord().getData();
if (this.type == PICTURE || this.type == CHART)
return getPictureData();
if (this.type == EXCELNOTE)
return getNoteData();
Assert.verify(false);
return null;
}
private byte[] getPictureData() {
int dataLength = 38;
int pos = 0;
byte[] data = new byte[dataLength];
IntegerHelper.getTwoBytes(21, data, pos);
IntegerHelper.getTwoBytes(18, data, pos + 2);
IntegerHelper.getTwoBytes(this.type.value, data, pos + 4);
IntegerHelper.getTwoBytes(this.objectId, data, pos + 6);
IntegerHelper.getTwoBytes(24593, data, pos + 8);
pos += 22;
IntegerHelper.getTwoBytes(7, data, pos);
IntegerHelper.getTwoBytes(2, data, pos + 2);
IntegerHelper.getTwoBytes(65535, data, pos + 4);
pos += 6;
IntegerHelper.getTwoBytes(8, data, pos);
IntegerHelper.getTwoBytes(2, data, pos + 2);
IntegerHelper.getTwoBytes(1, data, pos + 4);
pos += 6;
IntegerHelper.getTwoBytes(0, data, pos);
IntegerHelper.getTwoBytes(0, data, pos + 2);
pos += 4;
return data;
}
private byte[] getNoteData() {
int dataLength = 52;
int pos = 0;
byte[] data = new byte[dataLength];
IntegerHelper.getTwoBytes(21, data, pos);
IntegerHelper.getTwoBytes(18, data, pos + 2);
IntegerHelper.getTwoBytes(this.type.value, data, pos + 4);
IntegerHelper.getTwoBytes(this.objectId, data, pos + 6);
IntegerHelper.getTwoBytes(16401, data, pos + 8);
pos += 22;
IntegerHelper.getTwoBytes(13, data, pos);
IntegerHelper.getTwoBytes(22, data, pos + 2);
pos += 26;
IntegerHelper.getTwoBytes(0, data, pos);
IntegerHelper.getTwoBytes(0, data, pos + 2);
pos += 4;
return data;
}
public Record getRecord() {
return super.getRecord();
}
public ObjType getType() {
return this.type;
}
int getObjectId() {
return this.objectId;
}
}

View File

@@ -0,0 +1,126 @@
package jxl.biff.drawing;
import common.Logger;
import java.util.ArrayList;
import java.util.Iterator;
import jxl.biff.IntegerHelper;
import jxl.biff.StringHelper;
class Opt extends EscherAtom {
private static Logger logger = Logger.getLogger(Opt.class);
private byte[] data;
private int numProperties;
private ArrayList properties;
static final class Property {
int id;
boolean blipId;
boolean complex;
int value;
String stringValue;
public Property(int i, boolean bl, boolean co, int v) {
this.id = i;
this.blipId = bl;
this.complex = co;
this.value = v;
}
public Property(int i, boolean bl, boolean co, int v, String s) {
this.id = i;
this.blipId = bl;
this.complex = co;
this.value = v;
this.stringValue = s;
}
}
public Opt(EscherRecordData erd) {
super(erd);
this.numProperties = getInstance();
readProperties();
}
private void readProperties() {
this.properties = new ArrayList();
int pos = 0;
byte[] bytes = getBytes();
for (int j = 0; j < this.numProperties; j++) {
int val = IntegerHelper.getInt(bytes[pos], bytes[pos + 1]);
int id = val & 0x3FFF;
int value = IntegerHelper.getInt(bytes[pos + 2], bytes[pos + 3], bytes[pos + 4], bytes[pos + 5]);
Property p = new Property(id, ((val & 0x4000) != 0), ((val & 0x8000) != 0), value);
pos += 6;
this.properties.add(p);
}
for (Iterator i = this.properties.iterator(); i.hasNext(); ) {
Property p = i.next();
if (p.complex) {
p.stringValue = StringHelper.getUnicodeString(bytes, p.value / 2, pos);
pos += p.value;
}
}
}
public Opt() {
super(EscherRecordType.OPT);
this.properties = new ArrayList();
setVersion(3);
}
byte[] getData() {
this.numProperties = this.properties.size();
setInstance(this.numProperties);
this.data = new byte[this.numProperties * 6];
int pos = 0;
for (Iterator iterator1 = this.properties.iterator(); iterator1.hasNext(); ) {
Property p = iterator1.next();
int val = p.id & 0x3FFF;
if (p.blipId)
val |= 0x4000;
if (p.complex)
val |= 0x8000;
IntegerHelper.getTwoBytes(val, this.data, pos);
IntegerHelper.getFourBytes(p.value, this.data, pos + 2);
pos += 6;
}
for (Iterator i = this.properties.iterator(); i.hasNext(); ) {
Property p = i.next();
if (p.complex && p.stringValue != null) {
byte[] newData = new byte[this.data.length + p.stringValue.length() * 2];
System.arraycopy(this.data, 0, newData, 0, this.data.length);
StringHelper.getUnicodeBytes(p.stringValue, newData, this.data.length);
this.data = newData;
}
}
return setHeaderData(this.data);
}
void addProperty(int id, boolean blip, boolean complex, int val) {
Property p = new Property(id, blip, complex, val);
this.properties.add(p);
}
void addProperty(int id, boolean blip, boolean complex, int val, String s) {
Property p = new Property(id, blip, complex, val, s);
this.properties.add(p);
}
Property getProperty(int id) {
boolean found = false;
Property p = null;
for (Iterator i = this.properties.iterator(); i.hasNext() && !found; ) {
p = i.next();
if (p.id == id)
found = true;
}
return found ? p : null;
}
}

View File

@@ -0,0 +1,9 @@
package jxl.biff.drawing;
public final class Origin {
public static final Origin READ = new Origin();
public static final Origin WRITE = new Origin();
public static final Origin READ_WRITE = new Origin();
}

View File

@@ -0,0 +1,37 @@
package jxl.biff.drawing;
final class ShapeType {
int value;
private static ShapeType[] types = new ShapeType[0];
ShapeType(int v) {
this.value = v;
ShapeType[] old = types;
types = new ShapeType[types.length + 1];
System.arraycopy(old, 0, types, 0, old.length);
types[old.length] = this;
}
static ShapeType getType(int v) {
ShapeType st = UNKNOWN;
boolean found = false;
for (int i = 0; i < types.length && !found; i++) {
if ((types[i]).value == v) {
found = true;
st = types[i];
}
}
return st;
}
public static final ShapeType MIN = new ShapeType(0);
public static final ShapeType PICTURE_FRAME = new ShapeType(75);
public static final ShapeType HOST_CONTROL = new ShapeType(201);
public static final ShapeType TEXT_BOX = new ShapeType(202);
public static final ShapeType UNKNOWN = new ShapeType(-1);
}

View File

@@ -0,0 +1,238 @@
package jxl.biff.drawing;
import common.Logger;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import jxl.WorkbookSettings;
import jxl.biff.ByteData;
import jxl.biff.IntegerHelper;
import jxl.write.biff.File;
public class SheetDrawingWriter {
private static Logger logger = Logger.getLogger(SheetDrawingWriter.class);
private ArrayList drawings;
private boolean drawingsModified;
private Chart[] charts = new Chart[0];
private WorkbookSettings workbookSettings;
public void setDrawings(ArrayList dr, boolean mod) {
this.drawings = dr;
this.drawingsModified = mod;
}
public void write(File outputFile) throws IOException {
if (this.drawings.size() == 0 && this.charts.length == 0)
return;
boolean modified = this.drawingsModified;
int numImages = this.drawings.size();
for (Iterator i = this.drawings.iterator(); i.hasNext() && !modified; ) {
DrawingGroupObject d = i.next();
if (d.getOrigin() != Origin.READ)
modified = true;
}
if (numImages > 0 && !modified) {
DrawingGroupObject d2 = this.drawings.get(0);
if (!d2.isFirst())
modified = true;
}
if (numImages == 0 && this.charts.length == 1 && this.charts[0].getMsoDrawingRecord() == null)
modified = false;
if (!modified) {
writeUnmodified(outputFile);
return;
}
Object[] spContainerData = new Object[numImages + this.charts.length];
int length = 0;
EscherContainer firstSpContainer = null;
int j;
for (j = 0; j < numImages; j++) {
DrawingGroupObject drawing = this.drawings.get(j);
EscherContainer spc = drawing.getSpContainer();
byte[] data = spc.getData();
spContainerData[j] = data;
if (j == 0) {
firstSpContainer = spc;
} else {
length += data.length;
}
}
for (j = 0; j < this.charts.length; j++) {
EscherContainer escherContainer = this.charts[j].getSpContainer();
byte[] data = escherContainer.getData();
data = escherContainer.setHeaderData(data);
spContainerData[j + numImages] = data;
if (j == 0 && numImages == 0) {
firstSpContainer = escherContainer;
} else {
length += data.length;
}
}
DgContainer dgContainer = new DgContainer();
Dg dg = new Dg(numImages + this.charts.length);
dgContainer.add(dg);
SpgrContainer spgrContainer = new SpgrContainer();
SpContainer spContainer = new SpContainer();
Spgr spgr = new Spgr();
spContainer.add(spgr);
Sp sp = new Sp(ShapeType.MIN, 1024, 5);
spContainer.add(sp);
spgrContainer.add(spContainer);
spgrContainer.add(firstSpContainer);
dgContainer.add(spgrContainer);
byte[] firstMsoData = dgContainer.getData();
int len = IntegerHelper.getInt(firstMsoData[4], firstMsoData[5], firstMsoData[6], firstMsoData[7]);
IntegerHelper.getFourBytes(len + length, firstMsoData, 4);
len = IntegerHelper.getInt(firstMsoData[28], firstMsoData[29], firstMsoData[30], firstMsoData[31]);
IntegerHelper.getFourBytes(len + length, firstMsoData, 28);
if (numImages > 0 && ((DrawingGroupObject)this.drawings.get(0)).isFormObject()) {
byte[] msodata2 = new byte[firstMsoData.length - 8];
System.arraycopy(firstMsoData, 0, msodata2, 0, msodata2.length);
firstMsoData = msodata2;
}
MsoDrawingRecord msoDrawingRecord = new MsoDrawingRecord(firstMsoData);
outputFile.write((ByteData)msoDrawingRecord);
if (numImages > 0) {
DrawingGroupObject firstDrawing = this.drawings.get(0);
firstDrawing.writeAdditionalRecords(outputFile);
} else {
Chart chart = this.charts[0];
ObjRecord objRecord = chart.getObjRecord();
outputFile.write((ByteData)objRecord);
outputFile.write(chart);
}
for (int k = 1; k < spContainerData.length; k++) {
byte[] bytes = (byte[])spContainerData[k];
if (k < numImages && ((DrawingGroupObject)this.drawings.get(k)).isFormObject()) {
byte[] bytes2 = new byte[bytes.length - 8];
System.arraycopy(bytes, 0, bytes2, 0, bytes2.length);
bytes = bytes2;
}
msoDrawingRecord = new MsoDrawingRecord(bytes);
outputFile.write((ByteData)msoDrawingRecord);
if (k < numImages) {
DrawingGroupObject d = this.drawings.get(k);
d.writeAdditionalRecords(outputFile);
} else {
Chart chart = this.charts[k - numImages];
ObjRecord objRecord = chart.getObjRecord();
outputFile.write((ByteData)objRecord);
outputFile.write(chart);
}
}
for (Iterator iterator1 = this.drawings.iterator(); iterator1.hasNext(); ) {
DrawingGroupObject dgo2 = iterator1.next();
dgo2.writeTailRecords(outputFile);
}
}
private void writeUnmodified(File outputFile) throws IOException {
if (this.charts.length == 0 && this.drawings.size() == 0)
return;
if (this.charts.length == 0 && this.drawings.size() != 0) {
for (Iterator iterator2 = this.drawings.iterator(); iterator2.hasNext(); ) {
DrawingGroupObject d = iterator2.next();
outputFile.write((ByteData)d.getMsoDrawingRecord());
d.writeAdditionalRecords(outputFile);
}
for (Iterator iterator1 = this.drawings.iterator(); iterator1.hasNext(); ) {
DrawingGroupObject d = iterator1.next();
d.writeTailRecords(outputFile);
}
return;
}
if (this.drawings.size() == 0 && this.charts.length != 0) {
Chart curChart = null;
for (int k = 0; k < this.charts.length; k++) {
curChart = this.charts[k];
if (curChart.getMsoDrawingRecord() != null)
outputFile.write((ByteData)curChart.getMsoDrawingRecord());
if (curChart.getObjRecord() != null)
outputFile.write((ByteData)curChart.getObjRecord());
outputFile.write(curChart);
}
return;
}
int numDrawings = this.drawings.size();
int length = 0;
EscherContainer[] spContainers = new EscherContainer[numDrawings + this.charts.length];
boolean[] isFormObject = new boolean[numDrawings + this.charts.length];
int i;
for (i = 0; i < numDrawings; i++) {
DrawingGroupObject d = this.drawings.get(i);
spContainers[i] = d.getSpContainer();
if (i > 0)
length += spContainers[i].getLength();
if (d.isFormObject())
isFormObject[i] = true;
}
for (i = 0; i < this.charts.length; i++) {
spContainers[i + numDrawings] = this.charts[i].getSpContainer();
length += spContainers[i + numDrawings].getLength();
}
DgContainer dgContainer = new DgContainer();
Dg dg = new Dg(numDrawings + this.charts.length);
dgContainer.add(dg);
SpgrContainer spgrContainer = new SpgrContainer();
SpContainer spContainer = new SpContainer();
Spgr spgr = new Spgr();
spContainer.add(spgr);
Sp sp = new Sp(ShapeType.MIN, 1024, 5);
spContainer.add(sp);
spgrContainer.add(spContainer);
spgrContainer.add(spContainers[0]);
dgContainer.add(spgrContainer);
byte[] firstMsoData = dgContainer.getData();
int len = IntegerHelper.getInt(firstMsoData[4], firstMsoData[5], firstMsoData[6], firstMsoData[7]);
IntegerHelper.getFourBytes(len + length, firstMsoData, 4);
len = IntegerHelper.getInt(firstMsoData[28], firstMsoData[29], firstMsoData[30], firstMsoData[31]);
IntegerHelper.getFourBytes(len + length, firstMsoData, 28);
if (isFormObject[0] == true) {
byte[] cbytes = new byte[firstMsoData.length - 8];
System.arraycopy(firstMsoData, 0, cbytes, 0, cbytes.length);
firstMsoData = cbytes;
}
MsoDrawingRecord msoDrawingRecord = new MsoDrawingRecord(firstMsoData);
outputFile.write((ByteData)msoDrawingRecord);
DrawingGroupObject dgo = this.drawings.get(0);
dgo.writeAdditionalRecords(outputFile);
for (int j = 1; j < spContainers.length; j++) {
byte[] bytes = spContainers[j].getBytes();
byte[] bytes2 = spContainers[j].setHeaderData(bytes);
if (isFormObject[j] == true) {
byte[] cbytes = new byte[bytes2.length - 8];
System.arraycopy(bytes2, 0, cbytes, 0, cbytes.length);
bytes2 = cbytes;
}
msoDrawingRecord = new MsoDrawingRecord(bytes2);
outputFile.write((ByteData)msoDrawingRecord);
if (j < numDrawings) {
dgo = this.drawings.get(j);
dgo.writeAdditionalRecords(outputFile);
} else {
Chart chart = this.charts[j - numDrawings];
ObjRecord objRecord = chart.getObjRecord();
outputFile.write((ByteData)objRecord);
outputFile.write(chart);
}
}
for (Iterator iterator = this.drawings.iterator(); iterator.hasNext(); ) {
DrawingGroupObject dgo2 = iterator.next();
dgo2.writeTailRecords(outputFile);
}
}
public void setCharts(Chart[] ch) {
this.charts = ch;
}
public Chart[] getCharts() {
return this.charts;
}
public SheetDrawingWriter(WorkbookSettings ws) {}
}

View File

@@ -0,0 +1,48 @@
package jxl.biff.drawing;
import common.Logger;
import jxl.biff.IntegerHelper;
class Sp extends EscherAtom {
private static Logger logger = Logger.getLogger(Sp.class);
private byte[] data;
private int shapeType;
private int shapeId;
private int persistenceFlags;
public Sp(EscherRecordData erd) {
super(erd);
this.shapeType = getInstance();
byte[] bytes = getBytes();
this.shapeId = IntegerHelper.getInt(bytes[0], bytes[1], bytes[2], bytes[3]);
this.persistenceFlags = IntegerHelper.getInt(bytes[4], bytes[5], bytes[6], bytes[7]);
}
public Sp(ShapeType st, int sid, int p) {
super(EscherRecordType.SP);
setVersion(2);
this.shapeType = st.value;
this.shapeId = sid;
this.persistenceFlags = p;
setInstance(this.shapeType);
}
int getShapeId() {
return this.shapeId;
}
int getShapeType() {
return this.shapeType;
}
byte[] getData() {
this.data = new byte[8];
IntegerHelper.getFourBytes(this.shapeId, this.data, 0);
IntegerHelper.getFourBytes(this.persistenceFlags, this.data, 4);
return setHeaderData(this.data);
}
}

View File

@@ -0,0 +1,11 @@
package jxl.biff.drawing;
class SpContainer extends EscherContainer {
public SpContainer() {
super(EscherRecordType.SP_CONTAINER);
}
public SpContainer(EscherRecordData erd) {
super(erd);
}
}

View File

@@ -0,0 +1,19 @@
package jxl.biff.drawing;
class Spgr extends EscherAtom {
private byte[] data;
public Spgr(EscherRecordData erd) {
super(erd);
}
public Spgr() {
super(EscherRecordType.SPGR);
setVersion(1);
this.data = new byte[16];
}
byte[] getData() {
return setHeaderData(this.data);
}
}

View File

@@ -0,0 +1,15 @@
package jxl.biff.drawing;
import common.Logger;
class SpgrContainer extends EscherContainer {
private static final Logger logger = Logger.getLogger(SpgrContainer.class);
public SpgrContainer() {
super(EscherRecordType.SPGR_CONTAINER);
}
public SpgrContainer(EscherRecordData erd) {
super(erd);
}
}

View File

@@ -0,0 +1,22 @@
package jxl.biff.drawing;
class SplitMenuColors extends EscherAtom {
private byte[] data;
public SplitMenuColors(EscherRecordData erd) {
super(erd);
}
public SplitMenuColors() {
super(EscherRecordType.SPLIT_MENU_COLORS);
setVersion(0);
setInstance(4);
this.data = new byte[] {
13, 0, 0, 8, 12, 0, 0, 8, 23, 0,
0, 8, -9, 0, 0, 16 };
}
byte[] getData() {
return setHeaderData(this.data);
}
}

View File

@@ -0,0 +1,45 @@
package jxl.biff.drawing;
import common.Logger;
import jxl.biff.IntegerHelper;
import jxl.biff.Type;
import jxl.biff.WritableRecordData;
import jxl.read.biff.Record;
public class TextObjectRecord extends WritableRecordData {
private static Logger logger = Logger.getLogger(TextObjectRecord.class);
private byte[] data;
private int textLength;
TextObjectRecord(String t) {
super(Type.TXO);
this.textLength = t.length();
}
public TextObjectRecord(Record t) {
super(t);
this.data = getRecord().getData();
this.textLength = IntegerHelper.getInt(this.data[10], this.data[11]);
}
public TextObjectRecord(byte[] d) {
super(Type.TXO);
this.data = d;
}
public byte[] getData() {
if (this.data != null)
return this.data;
this.data = new byte[18];
int options = 0;
options |= 0x2;
options |= 0x10;
options |= 0x200;
IntegerHelper.getTwoBytes(options, this.data, 0);
IntegerHelper.getTwoBytes(this.textLength, this.data, 10);
IntegerHelper.getTwoBytes(16, this.data, 12);
return this.data;
}
}