KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jxl > biff > drawing > Drawing


1 /*********************************************************************
2 *
3 * Copyright (C) 2002 Andrew Khan
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ***************************************************************************/

19
20 package jxl.biff.drawing;
21
22 import java.io.IOException JavaDoc;
23 import java.io.FileInputStream JavaDoc;
24
25 import common.Assert;
26 import common.Logger;
27
28 import jxl.Image;
29 import jxl.WorkbookSettings;
30 import jxl.biff.ByteData;
31 import jxl.biff.IntegerHelper;
32 import jxl.biff.IndexMapping;
33 import jxl.biff.Type;
34 import jxl.write.biff.File;
35 import jxl.biff.drawing.MsoDrawingRecord;
36 import jxl.biff.drawing.ObjRecord;
37
38 /**
39  * Contains the various biff records used to insert a drawing into a
40  * worksheet
41  */

42 public class Drawing implements DrawingGroupObject, Image
43 {
44   /**
45    * The logger
46    */

47   private static Logger logger = Logger.getLogger(Drawing.class);
48
49   /**
50    * The spContainer that was read in
51    */

52   private EscherContainer readSpContainer;
53
54   /**
55    * The MsoDrawingRecord associated with the drawing
56    */

57   private MsoDrawingRecord msoDrawingRecord;
58
59   /**
60    * The ObjRecord associated with the drawing
61    */

62   private ObjRecord objRecord;
63
64   /**
65    * Initialized flag
66    */

67   private boolean initialized = false;
68
69   /**
70    * The file containing the image
71    */

72   private java.io.File JavaDoc imageFile;
73
74   /**
75    * The raw image data, used instead of an image file
76    */

77   private byte[] imageData;
78
79   /**
80    * The object id, assigned by the drawing group
81    */

82   private int objectId;
83
84   /**
85    * The blip id
86    */

87   private int blipId;
88
89   /**
90    * The column position of the image
91    */

92   private double x;
93
94   /**
95    * The row position of the image
96    */

97   private double y;
98
99   /**
100    * The width of the image in cells
101    */

102   private double width;
103
104   /**
105    * The height of the image in cells
106    */

107   private double height;
108
109   /**
110    * The number of places this drawing is referenced
111    */

112   private int referenceCount;
113
114   /**
115    * The top level escher container
116    */

117   private EscherContainer escherData;
118
119   /**
120    * Where this image came from (read, written or a copy)
121    */

122   private Origin origin;
123
124   /**
125    * The drawing group for all the images
126    */

127   private DrawingGroup drawingGroup;
128
129   /**
130    * The drawing data
131    */

132   private DrawingData drawingData;
133
134   /**
135    * The type of this drawing object
136    */

137   private ShapeType type;
138
139   /**
140    * The shape id
141    */

142   private int shapeId;
143
144   /**
145    * The drawing position on the sheet
146    */

147   private int drawingNumber;
148
149
150   /**
151    * Constructor used when reading images
152    *
153    * @param mso the drawing record
154    * @param obj the object record
155    * @param dd the drawing data for all drawings on this sheet
156    * @param dg the drawing group
157    */

158   public Drawing(MsoDrawingRecord mso, ObjRecord obj,
159                  DrawingData dd,
160                  DrawingGroup dg)
161   {
162     drawingGroup = dg;
163     msoDrawingRecord = mso;
164     drawingData = dd;
165     objRecord = obj;
166     initialized = false;
167     origin = Origin.READ;
168     drawingData.addData(msoDrawingRecord.getData());
169     drawingNumber = drawingData.getNumDrawings() - 1;
170     drawingGroup.addDrawing(this);
171
172     Assert.verify(mso != null && obj != null);
173
174     initialize();
175   }
176
177   /**
178    * Copy constructor used to copy drawings from read to write
179    *
180    * @param d the drawing to copy
181    */

182   protected Drawing(DrawingGroupObject dgo, DrawingGroup dg)
183   {
184     Drawing d = (Drawing) dgo;
185     Assert.verify(d.origin == Origin.READ);
186     msoDrawingRecord = d.msoDrawingRecord;
187     objRecord = d.objRecord;
188     initialized = false;
189     origin = Origin.READ;
190     drawingData = d.drawingData;
191     drawingGroup = dg;
192     drawingNumber = d.drawingNumber;
193     drawingGroup.addDrawing(this);
194   }
195
196   /**
197    * Constructor invoked when writing the images
198    *
199    * @param x the column
200    * @param y the row
201    * @param width the width in cells
202    * @param height the height in cells
203    * @param image the image file
204    */

205   public Drawing(double x, double y, double width, double height,
206                  java.io.File JavaDoc image)
207   {
208     imageFile = image;
209     initialized = true;
210     origin = Origin.WRITE;
211     this.x = x;
212     this.y = y;
213     this.width = width;
214     this.height = height;
215     referenceCount = 1;
216     type = ShapeType.PICTURE_FRAME;
217   }
218
219   /**
220    * Constructor invoked when writing the images
221    *
222    * @param x the column
223    * @param y the row
224    * @param width the width in cells
225    * @param height the height in cells
226    * @param image the image data
227    */

228   public Drawing(double x, double y, double width, double height,
229                  byte[] image)
230   {
231     imageData = image;
232     initialized = true;
233     origin = Origin.WRITE;
234     this.x = x;
235     this.y = y;
236     this.width = width;
237     this.height = height;
238     referenceCount = 1;
239     type = ShapeType.PICTURE_FRAME;
240   }
241
242   /**
243    * Initializes the member variables from the Escher stream data
244    */

245   private void initialize()
246   {
247     readSpContainer = drawingData.getSpContainer(drawingNumber);
248     Assert.verify(readSpContainer != null);
249
250     EscherRecord[] children = readSpContainer.getChildren();
251
252     Sp sp = (Sp) readSpContainer.getChildren()[0];
253     shapeId = sp.getShapeId();
254     objectId = objRecord.getObjectId();
255     type = ShapeType.getType(sp.getShapeType());
256
257     if (type == ShapeType.UNKNOWN)
258     {
259       logger.warn("Unknown shape type");
260     }
261
262     Opt opt = (Opt) readSpContainer.getChildren()[1];
263
264     if (opt.getProperty(260) != null)
265     {
266       blipId = opt.getProperty(260).value;
267     }
268
269     if (opt.getProperty(261) != null)
270     {
271       imageFile = new java.io.File JavaDoc(opt.getProperty(261).stringValue);
272     }
273     else
274     {
275       if (type == ShapeType.PICTURE_FRAME)
276       {
277         logger.warn("no filename property for drawing");
278         imageFile = new java.io.File JavaDoc(Integer.toString(blipId));
279       }
280     }
281     
282     ClientAnchor clientAnchor = null;
283     for (int i = 0 ; i < children.length && clientAnchor == null ; i++)
284     {
285       if (children[i].getType() == EscherRecordType.CLIENT_ANCHOR)
286       {
287         clientAnchor = (ClientAnchor) children[i];
288       }
289     }
290     
291     if (clientAnchor == null)
292     {
293       logger.warn("client anchor not found");
294     }
295     else
296     {
297       x = clientAnchor.getX1();
298       y = clientAnchor.getY1();
299       width = clientAnchor.getX2() - x;
300       height = clientAnchor.getY2() - y;
301     }
302
303     if (blipId == 0)
304     {
305       logger.warn("linked drawings are not supported");
306     }
307
308     initialized = true;
309   }
310
311   /**
312    * Accessor for the image file
313    *
314    * @return the image file
315    */

316   public java.io.File JavaDoc getImageFile()
317   {
318     return imageFile;
319   }
320
321   /**
322    * Accessor for the image file path. Normally this is the absolute path
323    * of a file on the directory system, but if this drawing was constructed
324    * using an byte[] then the blip id is returned
325    *
326    * @return the image file path, or the blip id
327    */

328   public String JavaDoc getImageFilePath()
329   {
330     if (imageFile == null)
331     {
332       // return the blip id, if it exists
333
return blipId != 0 ? Integer.toString(blipId) : "__new__image__";
334     }
335
336     return imageFile.getPath();
337   }
338
339   /**
340    * Sets the object id. Invoked by the drawing group when the object is
341    * added to id
342    *
343    * @param objid the object id
344    * @param bip the blip id
345    * @param sid the shape id
346    */

347   public final void setObjectId(int objid, int bip, int sid)
348   {
349     objectId = objid;
350     blipId = bip;
351     shapeId = sid;
352
353     if (origin == Origin.READ)
354     {
355       origin = Origin.READ_WRITE;
356     }
357   }
358
359   /**
360    * Accessor for the object id
361    *
362    * @return the object id
363    */

364   public final int getObjectId()
365   {
366     if (!initialized)
367     {
368       initialize();
369     }
370
371     return objectId;
372   }
373
374   /**
375    * Accessor for the shape id
376    *
377    * @return the shape id
378    */

379   public int getShapeId()
380   {
381     if (!initialized)
382     {
383       initialize();
384     }
385
386     return shapeId;
387   }
388
389   /**
390    * Accessor for the blip id
391    *
392    * @return the blip id
393    */

394   public final int getBlipId()
395   {
396     if (!initialized)
397     {
398       initialize();
399     }
400
401     return blipId;
402   }
403
404   /**
405    * Gets the drawing record which was read in
406    *
407    * @return the drawing record
408    */

409   public MsoDrawingRecord getMsoDrawingRecord()
410   {
411     return msoDrawingRecord;
412   }
413   
414   /**
415    * Creates the main Sp container for the drawing
416    *
417    * @return the SP container
418    */

419   public EscherContainer getSpContainer()
420   {
421     if (!initialized)
422     {
423       initialize();
424     }
425
426     if (origin == Origin.READ)
427     {
428       return getReadSpContainer();
429     }
430
431     SpContainer spContainer = new SpContainer();
432     Sp sp = new Sp(type, shapeId, 2560);
433     spContainer.add(sp);
434     Opt opt = new Opt();
435     opt.addProperty(260, true, false, blipId);
436
437     if (type == ShapeType.PICTURE_FRAME)
438     {
439       String JavaDoc filePath = imageFile != null ? imageFile.getPath(): "";
440       opt.addProperty(261, true, true, filePath.length() * 2, filePath);
441       opt.addProperty(447, false, false, 65536);
442       opt.addProperty(959, false, false, 524288);
443       spContainer.add(opt);
444     }
445
446     ClientAnchor clientAnchor = new ClientAnchor(x, y, x + width, y + height);
447     spContainer.add(clientAnchor);
448     ClientData clientData = new ClientData();
449     spContainer.add(clientData);
450
451     return spContainer;
452   }
453
454   /**
455    * Sets the drawing group for this drawing. Called by the drawing group
456    * when this drawing is added to it
457    *
458    * @param dg the drawing group
459    */

460   public void setDrawingGroup(DrawingGroup dg)
461   {
462     drawingGroup = dg;
463   }
464
465   /**
466    * Accessor for the drawing group
467    *
468    * @return the drawing group
469    */

470   public DrawingGroup getDrawingGroup()
471   {
472     return drawingGroup;
473   }
474
475   /**
476    * Gets the origin of this drawing
477    *
478    * @return where this drawing came from
479    */

480   public Origin getOrigin()
481   {
482     return origin;
483   }
484   
485   /**
486    * Accessor for the reference count on this drawing
487    *
488    * @return the reference count
489    */

490   public int getReferenceCount()
491   {
492     return referenceCount;
493   }
494
495   /**
496    * Sets the new reference count on the drawing
497    *
498    * @param r the new reference count
499    */

500   public void setReferenceCount(int r)
501   {
502     referenceCount = r;
503   }
504
505   /**
506    * Accessor for the column of this drawing
507    *
508    * @return the column
509    */

510   public double getX()
511   {
512     if (!initialized)
513     {
514       initialize();
515     }
516     return x;
517   }
518
519   /**
520    * Sets the column position of this drawing
521    *
522    * @param x the column
523    */

524   public void setX(double x)
525   {
526     if (origin == Origin.READ)
527     {
528       if (!initialized)
529       {
530         initialize();
531       }
532       origin = Origin.READ_WRITE;
533     }
534
535     this.x = x;
536   }
537
538   /**
539    * Accessor for the row of this drawing
540    *
541    * @return the row
542    */

543   public double getY()
544   {
545     if (!initialized)
546     {
547       initialize();
548     }
549
550     return y;
551   }
552
553   /**
554    * Accessor for the row of the drawing
555    *
556    * @param y the row
557    */

558   public void setY(double y)
559   {
560     if (origin == Origin.READ)
561     {
562       if (!initialized)
563       {
564         initialize();
565       }
566       origin = Origin.READ_WRITE;
567     }
568
569     this.y = y;
570   }
571
572
573   /**
574    * Accessor for the width of this drawing
575    *
576    * @return the number of columns spanned by this image
577    */

578   public double getWidth()
579   {
580     if (!initialized)
581     {
582       initialize();
583     }
584
585     return width;
586   }
587
588   /**
589    * Accessor for the width
590    *
591    * @param w the number of columns to span
592    */

593   public void setWidth(double w)
594   {
595     if (origin == Origin.READ)
596     {
597       if (!initialized)
598       {
599         initialize();
600       }
601       origin = Origin.READ_WRITE;
602     }
603
604     width = w;
605   }
606
607   /**
608    * Accessor for the height of this drawing
609    *
610    * @return the number of rows spanned by this image
611    */

612   public double getHeight()
613   {
614     if (!initialized)
615     {
616       initialize();
617     }
618
619     return height;
620   }
621
622   /**
623    * Accessor for the height of this drawing
624    *
625    * @param h the number of rows spanned by this image
626    */

627   public void setHeight(double h)
628   {
629     if (origin == Origin.READ)
630     {
631       if (!initialized)
632       {
633         initialize();
634       }
635       origin = Origin.READ_WRITE;
636     }
637
638     height = h;
639   }
640
641   
642   /**
643    * Gets the SpContainer that was read in
644    *
645    * @return the read sp container
646    */

647   private EscherContainer getReadSpContainer()
648   {
649     if (!initialized)
650     {
651       initialize();
652     }
653
654     return readSpContainer;
655   }
656
657   /**
658    * Accessor for the image data
659    *
660    * @return the image data
661    */

662   public byte[] getImageData()
663   {
664     Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE);
665
666     if (!initialized)
667     {
668       initialize();
669     }
670     
671     return drawingGroup.getImageData(blipId);
672   }
673
674   /**
675    * Accessor for the image data
676    *
677    * @return the image data
678    */

679   public byte[] getImageBytes() throws IOException JavaDoc
680   {
681     if (origin == Origin.READ || origin == Origin.READ_WRITE)
682     {
683       return getImageData();
684     }
685
686     Assert.verify(origin == Origin.WRITE);
687
688     if (imageFile == null)
689     {
690       Assert.verify(imageData != null);
691       return imageData;
692     }
693
694     byte[] data = new byte[(int) imageFile.length()];
695     FileInputStream JavaDoc fis = new FileInputStream JavaDoc(imageFile);
696     fis.read(data, 0, data.length);
697     fis.close();
698     return data;
699   }
700
701   /**
702    * Accessor for the type
703    *
704    * @return the type
705    */

706   public ShapeType getType()
707   {
708     return type;
709   }
710
711   /**
712    * Writes any other records associated with this drawing group object
713    */

714   public void writeAdditionalRecords(File outputFile) throws IOException JavaDoc
715   {
716     if (origin == Origin.READ)
717     {
718       outputFile.write(objRecord);
719       return;
720     }
721
722     // Create the obj record
723
ObjRecord objRecord = new ObjRecord(objectId,
724                                         ObjRecord.PICTURE);
725     outputFile.write(objRecord);
726   }
727
728   /**
729    * Writes any records that need to be written after all the drawing group
730    * objects have been written
731    * Does nothing here
732    */

733   public void writeTailRecords(File outputFile) throws IOException JavaDoc
734   {
735     // does nothing
736
}
737
738   /**
739    * Interface method
740    *
741    * @return the column number at which the image is positioned
742    */

743   public double getColumn()
744   {
745     return getX();
746   }
747
748   /**
749    * Interface method
750    *
751    * @return the row number at which the image is positions
752    */

753   public double getRow()
754   {
755     return getY();
756   }
757
758   /**
759    * Accessor for the first drawing on the sheet. This is used when
760    * copying unmodified sheets to indicate that this drawing contains
761    * the first time Escher gubbins
762    *
763    * @return TRUE if this MSORecord is the first drawing on the sheet
764    */

765   public boolean isFirst()
766   {
767     return msoDrawingRecord.isFirst();
768   }
769
770   /**
771    * Queries whether this object is a form object. Form objects have their
772    * drawings records spread over TXO and CONTINUE records and
773    * require special handling
774    *
775    * @return TRUE if this is a form object, FALSE otherwise
776    */

777   public boolean isFormObject()
778   {
779     return false;
780   }
781
782 }
783
784
785
786
Popular Tags