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; } }