001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.ddf;
019:
020: import org.apache.poi.util.HexDump;
021: import org.apache.poi.util.HexRead;
022: import org.apache.poi.util.LittleEndian;
023:
024: import java.io.ByteArrayInputStream;
025: import java.io.IOException;
026: import java.io.InputStream;
027: import java.io.PrintStream;
028: import java.util.zip.InflaterInputStream;
029:
030: /**
031: * Used to dump the contents of escher records to a PrintStream.
032: *
033: * @author Glen Stampoultzis (glens at apache.org)
034: */
035: public class EscherDump {
036:
037: public EscherDump() {
038: }
039:
040: /**
041: * Decodes the escher stream from a byte array and dumps the results to
042: * a print stream.
043: *
044: * @param data The data array containing the escher records.
045: * @param offset The starting offset within the data array.
046: * @param size The number of bytes to read.
047: * @param out The output stream to write the results to.
048: *
049: */
050: public void dump(byte[] data, int offset, int size, PrintStream out)
051: throws IOException, LittleEndian.BufferUnderrunException {
052: EscherRecordFactory recordFactory = new DefaultEscherRecordFactory();
053: int pos = offset;
054: while (pos < offset + size) {
055: EscherRecord r = recordFactory.createRecord(data, pos);
056: int bytesRead = r.fillFields(data, pos, recordFactory);
057: System.out.println(r.toString());
058: pos += bytesRead;
059: }
060: }
061:
062: /**
063: * This version of dump is a translation from the open office escher dump routine.
064: *
065: * @param maxLength The number of bytes to read
066: * @param in An input stream to read from.
067: * @param out An output stream to write to.
068: */
069: public void dumpOld(long maxLength, InputStream in, PrintStream out)
070: throws IOException, LittleEndian.BufferUnderrunException {
071: long remainingBytes = maxLength;
072: short options; // 4 bits for the version and 12 bits for the instance
073: short recordId;
074: int recordBytesRemaining; // including enclosing records
075: StringBuffer stringBuf = new StringBuffer();
076: short nDumpSize;
077: String recordName;
078:
079: boolean atEOF = false;
080:
081: while (!atEOF && (remainingBytes > 0)) {
082: stringBuf = new StringBuffer();
083: options = LittleEndian.readShort(in);
084: recordId = LittleEndian.readShort(in);
085: recordBytesRemaining = LittleEndian.readInt(in);
086:
087: remainingBytes -= 2 + 2 + 4;
088:
089: switch (recordId) {
090: case (short) 0xF000:
091: recordName = "MsofbtDggContainer";
092: break;
093: case (short) 0xF006:
094: recordName = "MsofbtDgg";
095: break;
096: case (short) 0xF016:
097: recordName = "MsofbtCLSID";
098: break;
099: case (short) 0xF00B:
100: recordName = "MsofbtOPT";
101: break;
102: case (short) 0xF11A:
103: recordName = "MsofbtColorMRU";
104: break;
105: case (short) 0xF11E:
106: recordName = "MsofbtSplitMenuColors";
107: break;
108: case (short) 0xF001:
109: recordName = "MsofbtBstoreContainer";
110: break;
111: case (short) 0xF007:
112: recordName = "MsofbtBSE";
113: break;
114: case (short) 0xF002:
115: recordName = "MsofbtDgContainer";
116: break;
117: case (short) 0xF008:
118: recordName = "MsofbtDg";
119: break;
120: case (short) 0xF118:
121: recordName = "MsofbtRegroupItem";
122: break;
123: case (short) 0xF120:
124: recordName = "MsofbtColorScheme";
125: break;
126: case (short) 0xF003:
127: recordName = "MsofbtSpgrContainer";
128: break;
129: case (short) 0xF004:
130: recordName = "MsofbtSpContainer";
131: break;
132: case (short) 0xF009:
133: recordName = "MsofbtSpgr";
134: break;
135: case (short) 0xF00A:
136: recordName = "MsofbtSp";
137: break;
138: case (short) 0xF00C:
139: recordName = "MsofbtTextbox";
140: break;
141: case (short) 0xF00D:
142: recordName = "MsofbtClientTextbox";
143: break;
144: case (short) 0xF00E:
145: recordName = "MsofbtAnchor";
146: break;
147: case (short) 0xF00F:
148: recordName = "MsofbtChildAnchor";
149: break;
150: case (short) 0xF010:
151: recordName = "MsofbtClientAnchor";
152: break;
153: case (short) 0xF011:
154: recordName = "MsofbtClientData";
155: break;
156: case (short) 0xF11F:
157: recordName = "MsofbtOleObject";
158: break;
159: case (short) 0xF11D:
160: recordName = "MsofbtDeletedPspl";
161: break;
162: case (short) 0xF005:
163: recordName = "MsofbtSolverContainer";
164: break;
165: case (short) 0xF012:
166: recordName = "MsofbtConnectorRule";
167: break;
168: case (short) 0xF013:
169: recordName = "MsofbtAlignRule";
170: break;
171: case (short) 0xF014:
172: recordName = "MsofbtArcRule";
173: break;
174: case (short) 0xF015:
175: recordName = "MsofbtClientRule";
176: break;
177: case (short) 0xF017:
178: recordName = "MsofbtCalloutRule";
179: break;
180: case (short) 0xF119:
181: recordName = "MsofbtSelection";
182: break;
183: case (short) 0xF122:
184: recordName = "MsofbtUDefProp";
185: break;
186: default:
187: if (recordId >= (short) 0xF018
188: && recordId <= (short) 0xF117)
189: recordName = "MsofbtBLIP";
190: else if ((options & (short) 0x000F) == (short) 0x000F)
191: recordName = "UNKNOWN container";
192: else
193: recordName = "UNKNOWN ID";
194: }
195:
196: stringBuf.append(" ");
197: stringBuf.append(HexDump.toHex(recordId));
198: stringBuf.append(" ").append(recordName).append(" [");
199: stringBuf.append(HexDump.toHex(options));
200: stringBuf.append(',');
201: stringBuf.append(HexDump.toHex(recordBytesRemaining));
202: stringBuf.append("] instance: ");
203: stringBuf.append(HexDump.toHex(((short) (options >> 4))));
204: out.println(stringBuf.toString());
205:
206: if (recordId == (short) 0xF007 && 36 <= remainingBytes
207: && 36 <= recordBytesRemaining) { // BSE, FBSE
208: // ULONG nP = pIn->GetRecPos();
209:
210: byte n8;
211: // short n16;
212: // int n32;
213:
214: stringBuf = new StringBuffer(" btWin32: ");
215: n8 = (byte) in.read();
216: stringBuf.append(HexDump.toHex(n8));
217: stringBuf.append(getBlipType(n8));
218: stringBuf.append(" btMacOS: ");
219: n8 = (byte) in.read();
220: stringBuf.append(HexDump.toHex(n8));
221: stringBuf.append(getBlipType(n8));
222: out.println(stringBuf.toString());
223:
224: out.println(" rgbUid:");
225: HexDump.dump(in, out, 0, 16);
226:
227: out.print(" tag: ");
228: outHex(2, in, out);
229: out.println();
230: out.print(" size: ");
231: outHex(4, in, out);
232: out.println();
233: out.print(" cRef: ");
234: outHex(4, in, out);
235: out.println();
236: out.print(" offs: ");
237: outHex(4, in, out);
238: out.println();
239: out.print(" usage: ");
240: outHex(1, in, out);
241: out.println();
242: out.print(" cbName: ");
243: outHex(1, in, out);
244: out.println();
245: out.print(" unused2: ");
246: outHex(1, in, out);
247: out.println();
248: out.print(" unused3: ");
249: outHex(1, in, out);
250: out.println();
251:
252: // subtract the number of bytes we've read
253: remainingBytes -= 36;
254: //n -= pIn->GetRecPos() - nP;
255: recordBytesRemaining = 0; // loop to MsofbtBLIP
256: } else if (recordId == (short) 0xF010
257: && 0x12 <= remainingBytes
258: && 0x12 <= recordBytesRemaining) { // ClientAnchor
259: //ULONG nP = pIn->GetRecPos();
260: // short n16;
261:
262: out.print(" Flag: ");
263: outHex(2, in, out);
264: out.println();
265: out.print(" Col1: ");
266: outHex(2, in, out);
267: out.print(" dX1: ");
268: outHex(2, in, out);
269: out.print(" Row1: ");
270: outHex(2, in, out);
271: out.print(" dY1: ");
272: outHex(2, in, out);
273: out.println();
274: out.print(" Col2: ");
275: outHex(2, in, out);
276: out.print(" dX2: ");
277: outHex(2, in, out);
278: out.print(" Row2: ");
279: outHex(2, in, out);
280: out.print(" dY2: ");
281: outHex(2, in, out);
282: out.println();
283:
284: remainingBytes -= 18;
285: recordBytesRemaining -= 18;
286:
287: } else if (recordId == (short) 0xF00B
288: || recordId == (short) 0xF122) { // OPT
289: int nComplex = 0;
290: out.println(" PROPID VALUE");
291: while (recordBytesRemaining >= 6 + nComplex
292: && remainingBytes >= 6 + nComplex) {
293: short n16;
294: int n32;
295: n16 = LittleEndian.readShort(in);
296: n32 = LittleEndian.readInt(in);
297:
298: recordBytesRemaining -= 6;
299: remainingBytes -= 6;
300: out.print(" ");
301: out.print(HexDump.toHex(n16));
302: out.print(" (");
303: int propertyId = n16 & (short) 0x3FFF;
304: out.print(" " + propertyId);
305: if ((n16 & (short) 0x8000) == 0) {
306: if ((n16 & (short) 0x4000) != 0)
307: out.print(", fBlipID");
308: out.print(") ");
309:
310: out.print(HexDump.toHex(n32));
311:
312: if ((n16 & (short) 0x4000) == 0) {
313: out.print(" (");
314: out.print(dec1616(n32));
315: out.print(')');
316: out.print(" {"
317: + propName((short) propertyId)
318: + "}");
319: }
320: out.println();
321: } else {
322: out.print(", fComplex) ");
323: out.print(HexDump.toHex(n32));
324: out.print(" - Complex prop len");
325: out.println(" {" + propName((short) propertyId)
326: + "}");
327:
328: nComplex += n32;
329: }
330:
331: }
332: // complex property data
333: while ((nComplex & remainingBytes) > 0) {
334: nDumpSize = (nComplex > (int) remainingBytes) ? (short) remainingBytes
335: : (short) nComplex;
336: HexDump.dump(in, out, 0, nDumpSize);
337: nComplex -= nDumpSize;
338: recordBytesRemaining -= nDumpSize;
339: remainingBytes -= nDumpSize;
340: }
341: } else if (recordId == (short) 0xF012) {
342: out.print(" Connector rule: ");
343: out.print(LittleEndian.readInt(in));
344: out.print(" ShapeID A: ");
345: out.print(LittleEndian.readInt(in));
346: out.print(" ShapeID B: ");
347: out.print(LittleEndian.readInt(in));
348: out.print(" ShapeID connector: ");
349: out.print(LittleEndian.readInt(in));
350: out.print(" Connect pt A: ");
351: out.print(LittleEndian.readInt(in));
352: out.print(" Connect pt B: ");
353: out.println(LittleEndian.readInt(in));
354:
355: recordBytesRemaining -= 24;
356: remainingBytes -= 24;
357: } else if (recordId >= (short) 0xF018
358: && recordId < (short) 0xF117) {
359: out.println(" Secondary UID: ");
360: HexDump.dump(in, out, 0, 16);
361: out.println(" Cache of size: "
362: + HexDump.toHex(LittleEndian.readInt(in)));
363: out.println(" Boundary top: "
364: + HexDump.toHex(LittleEndian.readInt(in)));
365: out.println(" Boundary left: "
366: + HexDump.toHex(LittleEndian.readInt(in)));
367: out.println(" Boundary width: "
368: + HexDump.toHex(LittleEndian.readInt(in)));
369: out.println(" Boundary height: "
370: + HexDump.toHex(LittleEndian.readInt(in)));
371: out.println(" X: "
372: + HexDump.toHex(LittleEndian.readInt(in)));
373: out.println(" Y: "
374: + HexDump.toHex(LittleEndian.readInt(in)));
375: out.println(" Cache of saved size: "
376: + HexDump.toHex(LittleEndian.readInt(in)));
377: out.println(" Compression Flag: "
378: + HexDump.toHex((byte) in.read()));
379: out.println(" Filter: "
380: + HexDump.toHex((byte) in.read()));
381: out.println(" Data (after decompression): ");
382:
383: recordBytesRemaining -= 34 + 16;
384: remainingBytes -= 34 + 16;
385:
386: nDumpSize = (recordBytesRemaining > (int) remainingBytes) ? (short) remainingBytes
387: : (short) recordBytesRemaining;
388:
389: byte[] buf = new byte[nDumpSize];
390: int read = in.read(buf);
391: while (read != -1 && read < nDumpSize)
392: read += in.read(buf, read, buf.length);
393: ByteArrayInputStream bin = new ByteArrayInputStream(buf);
394:
395: InputStream in1 = new InflaterInputStream(bin);
396: int bytesToDump = -1;
397: HexDump.dump(in1, out, 0, bytesToDump);
398:
399: recordBytesRemaining -= nDumpSize;
400: remainingBytes -= nDumpSize;
401:
402: }
403:
404: boolean isContainer = (options & (short) 0x000F) == (short) 0x000F;
405: if (isContainer && remainingBytes >= 0) { // Container
406: if (recordBytesRemaining <= (int) remainingBytes)
407: out.println(" completed within");
408: else
409: out.println(" continued elsewhere");
410: } else if (remainingBytes >= 0)
411: // -> 0x0000 ... 0x0FFF
412: {
413: nDumpSize = (recordBytesRemaining > (int) remainingBytes) ? (short) remainingBytes
414: : (short) recordBytesRemaining;
415:
416: if (nDumpSize != 0) {
417: HexDump.dump(in, out, 0, nDumpSize);
418: remainingBytes -= nDumpSize;
419: }
420: } else
421: out.println(" >> OVERRUN <<");
422: }
423:
424: }
425:
426: /**
427: * Returns a property name given a property id. This is used only by the
428: * old escher dump routine.
429: *
430: * @param propertyId The property number for the name
431: * @return A descriptive name.
432: */
433: private String propName(short propertyId) {
434: class PropName {
435: public PropName(int id, String name) {
436: this .id = id;
437: this .name = name;
438: }
439:
440: int id;
441: String name;
442: }
443:
444: final PropName[] props = new PropName[] {
445: new PropName(4, "transform.rotation"),
446: new PropName(119, "protection.lockrotation"),
447: new PropName(120, "protection.lockaspectratio"),
448: new PropName(121, "protection.lockposition"),
449: new PropName(122, "protection.lockagainstselect"),
450: new PropName(123, "protection.lockcropping"),
451: new PropName(124, "protection.lockvertices"),
452: new PropName(125, "protection.locktext"),
453: new PropName(126, "protection.lockadjusthandles"),
454: new PropName(127, "protection.lockagainstgrouping"),
455: new PropName(128, "text.textid"),
456: new PropName(129, "text.textleft"),
457: new PropName(130, "text.texttop"),
458: new PropName(131, "text.textright"),
459: new PropName(132, "text.textbottom"),
460: new PropName(133, "text.wraptext"),
461: new PropName(134, "text.scaletext"),
462: new PropName(135, "text.anchortext"),
463: new PropName(136, "text.textflow"),
464: new PropName(137, "text.fontrotation"),
465: new PropName(138, "text.idofnextshape"),
466: new PropName(139, "text.bidir"),
467: new PropName(187, "text.singleclickselects"),
468: new PropName(188, "text.usehostmargins"),
469: new PropName(189, "text.rotatetextwithshape"),
470: new PropName(190, "text.sizeshapetofittext"),
471: new PropName(191, "text.sizetexttofitshape"),
472: new PropName(192, "geotext.unicode"),
473: new PropName(193, "geotext.rtftext"),
474: new PropName(194, "geotext.alignmentoncurve"),
475: new PropName(195, "geotext.defaultpointsize"),
476: new PropName(196, "geotext.textspacing"),
477: new PropName(197, "geotext.fontfamilyname"),
478: new PropName(240, "geotext.reverseroworder"),
479: new PropName(241, "geotext.hastexteffect"),
480: new PropName(242, "geotext.rotatecharacters"),
481: new PropName(243, "geotext.kerncharacters"),
482: new PropName(244, "geotext.tightortrack"),
483: new PropName(245, "geotext.stretchtofitshape"),
484: new PropName(246, "geotext.charboundingbox"),
485: new PropName(247, "geotext.scaletextonpath"),
486: new PropName(248, "geotext.stretchcharheight"),
487: new PropName(249, "geotext.nomeasurealongpath"),
488: new PropName(250, "geotext.boldfont"),
489: new PropName(251, "geotext.italicfont"),
490: new PropName(252, "geotext.underlinefont"),
491: new PropName(253, "geotext.shadowfont"),
492: new PropName(254, "geotext.smallcapsfont"),
493: new PropName(255, "geotext.strikethroughfont"),
494: new PropName(256, "blip.cropfromtop"),
495: new PropName(257, "blip.cropfrombottom"),
496: new PropName(258, "blip.cropfromleft"),
497: new PropName(259, "blip.cropfromright"),
498: new PropName(260, "blip.bliptodisplay"),
499: new PropName(261, "blip.blipfilename"),
500: new PropName(262, "blip.blipflags"),
501: new PropName(263, "blip.transparentcolor"),
502: new PropName(264, "blip.contrastsetting"),
503: new PropName(265, "blip.brightnesssetting"),
504: new PropName(266, "blip.gamma"),
505: new PropName(267, "blip.pictureid"),
506: new PropName(268, "blip.doublemod"),
507: new PropName(269, "blip.picturefillmod"),
508: new PropName(270, "blip.pictureline"),
509: new PropName(271, "blip.printblip"),
510: new PropName(272, "blip.printblipfilename"),
511: new PropName(273, "blip.printflags"),
512: new PropName(316, "blip.nohittestpicture"),
513: new PropName(317, "blip.picturegray"),
514: new PropName(318, "blip.picturebilevel"),
515: new PropName(319, "blip.pictureactive"),
516: new PropName(320, "geometry.left"),
517: new PropName(321, "geometry.top"),
518: new PropName(322, "geometry.right"),
519: new PropName(323, "geometry.bottom"),
520: new PropName(324, "geometry.shapepath"),
521: new PropName(325, "geometry.vertices"),
522: new PropName(326, "geometry.segmentinfo"),
523: new PropName(327, "geometry.adjustvalue"),
524: new PropName(328, "geometry.adjust2value"),
525: new PropName(329, "geometry.adjust3value"),
526: new PropName(330, "geometry.adjust4value"),
527: new PropName(331, "geometry.adjust5value"),
528: new PropName(332, "geometry.adjust6value"),
529: new PropName(333, "geometry.adjust7value"),
530: new PropName(334, "geometry.adjust8value"),
531: new PropName(335, "geometry.adjust9value"),
532: new PropName(336, "geometry.adjust10value"),
533: new PropName(378, "geometry.shadowOK"),
534: new PropName(379, "geometry.3dok"),
535: new PropName(380, "geometry.lineok"),
536: new PropName(381, "geometry.geotextok"),
537: new PropName(382, "geometry.fillshadeshapeok"),
538: new PropName(383, "geometry.fillok"),
539: new PropName(384, "fill.filltype"),
540: new PropName(385, "fill.fillcolor"),
541: new PropName(386, "fill.fillopacity"),
542: new PropName(387, "fill.fillbackcolor"),
543: new PropName(388, "fill.backopacity"),
544: new PropName(389, "fill.crmod"),
545: new PropName(390, "fill.patterntexture"),
546: new PropName(391, "fill.blipfilename"),
547: new PropName(392, "fill.blipflags"),
548: new PropName(393, "fill.width"),
549: new PropName(394, "fill.height"),
550: new PropName(395, "fill.angle"),
551: new PropName(396, "fill.focus"),
552: new PropName(397, "fill.toleft"),
553: new PropName(398, "fill.totop"),
554: new PropName(399, "fill.toright"),
555: new PropName(400, "fill.tobottom"),
556: new PropName(401, "fill.rectleft"),
557: new PropName(402, "fill.recttop"),
558: new PropName(403, "fill.rectright"),
559: new PropName(404, "fill.rectbottom"),
560: new PropName(405, "fill.dztype"),
561: new PropName(406, "fill.shadepreset"),
562: new PropName(407, "fill.shadecolors"),
563: new PropName(408, "fill.originx"),
564: new PropName(409, "fill.originy"),
565: new PropName(410, "fill.shapeoriginx"),
566: new PropName(411, "fill.shapeoriginy"),
567: new PropName(412, "fill.shadetype"),
568: new PropName(443, "fill.filled"),
569: new PropName(444, "fill.hittestfill"),
570: new PropName(445, "fill.shape"),
571: new PropName(446, "fill.userect"),
572: new PropName(447, "fill.nofillhittest"),
573: new PropName(448, "linestyle.color"),
574: new PropName(449, "linestyle.opacity"),
575: new PropName(450, "linestyle.backcolor"),
576: new PropName(451, "linestyle.crmod"),
577: new PropName(452, "linestyle.linetype"),
578: new PropName(453, "linestyle.fillblip"),
579: new PropName(454, "linestyle.fillblipname"),
580: new PropName(455, "linestyle.fillblipflags"),
581: new PropName(456, "linestyle.fillwidth"),
582: new PropName(457, "linestyle.fillheight"),
583: new PropName(458, "linestyle.filldztype"),
584: new PropName(459, "linestyle.linewidth"),
585: new PropName(460, "linestyle.linemiterlimit"),
586: new PropName(461, "linestyle.linestyle"),
587: new PropName(462, "linestyle.linedashing"),
588: new PropName(463, "linestyle.linedashstyle"),
589: new PropName(464, "linestyle.linestartarrowhead"),
590: new PropName(465, "linestyle.lineendarrowhead"),
591: new PropName(466, "linestyle.linestartarrowwidth"),
592: new PropName(467, "linestyle.lineestartarrowlength"),
593: new PropName(468, "linestyle.lineendarrowwidth"),
594: new PropName(469, "linestyle.lineendarrowlength"),
595: new PropName(470, "linestyle.linejoinstyle"),
596: new PropName(471, "linestyle.lineendcapstyle"),
597: new PropName(507, "linestyle.arrowheadsok"),
598: new PropName(508, "linestyle.anyline"),
599: new PropName(509, "linestyle.hitlinetest"),
600: new PropName(510, "linestyle.linefillshape"),
601: new PropName(511, "linestyle.nolinedrawdash"),
602: new PropName(512, "shadowstyle.type"),
603: new PropName(513, "shadowstyle.color"),
604: new PropName(514, "shadowstyle.highlight"),
605: new PropName(515, "shadowstyle.crmod"),
606: new PropName(516, "shadowstyle.opacity"),
607: new PropName(517, "shadowstyle.offsetx"),
608: new PropName(518, "shadowstyle.offsety"),
609: new PropName(519, "shadowstyle.secondoffsetx"),
610: new PropName(520, "shadowstyle.secondoffsety"),
611: new PropName(521, "shadowstyle.scalextox"),
612: new PropName(522, "shadowstyle.scaleytox"),
613: new PropName(523, "shadowstyle.scalextoy"),
614: new PropName(524, "shadowstyle.scaleytoy"),
615: new PropName(525, "shadowstyle.perspectivex"),
616: new PropName(526, "shadowstyle.perspectivey"),
617: new PropName(527, "shadowstyle.weight"),
618: new PropName(528, "shadowstyle.originx"),
619: new PropName(529, "shadowstyle.originy"),
620: new PropName(574, "shadowstyle.shadow"),
621: new PropName(575, "shadowstyle.shadowobsured"),
622: new PropName(576, "perspective.type"),
623: new PropName(577, "perspective.offsetx"),
624: new PropName(578, "perspective.offsety"),
625: new PropName(579, "perspective.scalextox"),
626: new PropName(580, "perspective.scaleytox"),
627: new PropName(581, "perspective.scalextoy"),
628: new PropName(582, "perspective.scaleytox"),
629: new PropName(583, "perspective.perspectivex"),
630: new PropName(584, "perspective.perspectivey"),
631: new PropName(585, "perspective.weight"),
632: new PropName(586, "perspective.originx"),
633: new PropName(587, "perspective.originy"),
634: new PropName(639, "perspective.perspectiveon"),
635: new PropName(640, "3d.specularamount"),
636: new PropName(661, "3d.diffuseamount"),
637: new PropName(662, "3d.shininess"),
638: new PropName(663, "3d.edgethickness"),
639: new PropName(664, "3d.extrudeforward"),
640: new PropName(665, "3d.extrudebackward"),
641: new PropName(666, "3d.extrudeplane"),
642: new PropName(667, "3d.extrusioncolor"),
643: new PropName(648, "3d.crmod"),
644: new PropName(700, "3d.3deffect"),
645: new PropName(701, "3d.metallic"),
646: new PropName(702, "3d.useextrusioncolor"),
647: new PropName(703, "3d.lightface"),
648: new PropName(704, "3dstyle.yrotationangle"),
649: new PropName(705, "3dstyle.xrotationangle"),
650: new PropName(706, "3dstyle.rotationaxisx"),
651: new PropName(707, "3dstyle.rotationaxisy"),
652: new PropName(708, "3dstyle.rotationaxisz"),
653: new PropName(709, "3dstyle.rotationangle"),
654: new PropName(710, "3dstyle.rotationcenterx"),
655: new PropName(711, "3dstyle.rotationcentery"),
656: new PropName(712, "3dstyle.rotationcenterz"),
657: new PropName(713, "3dstyle.rendermode"),
658: new PropName(714, "3dstyle.tolerance"),
659: new PropName(715, "3dstyle.xviewpoint"),
660: new PropName(716, "3dstyle.yviewpoint"),
661: new PropName(717, "3dstyle.zviewpoint"),
662: new PropName(718, "3dstyle.originx"),
663: new PropName(719, "3dstyle.originy"),
664: new PropName(720, "3dstyle.skewangle"),
665: new PropName(721, "3dstyle.skewamount"),
666: new PropName(722, "3dstyle.ambientintensity"),
667: new PropName(723, "3dstyle.keyx"),
668: new PropName(724, "3dstyle.keyy"),
669: new PropName(725, "3dstyle.keyz"),
670: new PropName(726, "3dstyle.keyintensity"),
671: new PropName(727, "3dstyle.fillx"),
672: new PropName(728, "3dstyle.filly"),
673: new PropName(729, "3dstyle.fillz"),
674: new PropName(730, "3dstyle.fillintensity"),
675: new PropName(763, "3dstyle.constrainrotation"),
676: new PropName(764, "3dstyle.rotationcenterauto"),
677: new PropName(765, "3dstyle.parallel"),
678: new PropName(766, "3dstyle.keyharsh"),
679: new PropName(767, "3dstyle.fillharsh"),
680: new PropName(769, "shape.master"),
681: new PropName(771, "shape.connectorstyle"),
682: new PropName(772, "shape.blackandwhitesettings"),
683: new PropName(773, "shape.wmodepurebw"),
684: new PropName(774, "shape.wmodebw"),
685: new PropName(826, "shape.oleicon"),
686: new PropName(827, "shape.preferrelativeresize"),
687: new PropName(828, "shape.lockshapetype"),
688: new PropName(830, "shape.deleteattachedobject"),
689: new PropName(831, "shape.backgroundshape"),
690: new PropName(832, "callout.callouttype"),
691: new PropName(833, "callout.xycalloutgap"),
692: new PropName(834, "callout.calloutangle"),
693: new PropName(835, "callout.calloutdroptype"),
694: new PropName(836, "callout.calloutdropspecified"),
695: new PropName(837, "callout.calloutlengthspecified"),
696: new PropName(889, "callout.iscallout"),
697: new PropName(890, "callout.calloutaccentbar"),
698: new PropName(891, "callout.callouttextborder"),
699: new PropName(892, "callout.calloutminusx"),
700: new PropName(893, "callout.calloutminusy"),
701: new PropName(894, "callout.dropauto"),
702: new PropName(895, "callout.lengthspecified"),
703: new PropName(896, "groupshape.shapename"),
704: new PropName(897, "groupshape.description"),
705: new PropName(898, "groupshape.hyperlink"),
706: new PropName(899, "groupshape.wrappolygonvertices"),
707: new PropName(900, "groupshape.wrapdistleft"),
708: new PropName(901, "groupshape.wrapdisttop"),
709: new PropName(902, "groupshape.wrapdistright"),
710: new PropName(903, "groupshape.wrapdistbottom"),
711: new PropName(904, "groupshape.regroupid"),
712: new PropName(953, "groupshape.editedwrap"),
713: new PropName(954, "groupshape.behinddocument"),
714: new PropName(955, "groupshape.ondblclicknotify"),
715: new PropName(956, "groupshape.isbutton"),
716: new PropName(957, "groupshape.1dadjustment"),
717: new PropName(958, "groupshape.hidden"),
718: new PropName(959, "groupshape.print"), };
719:
720: for (int i = 0; i < props.length; i++) {
721: if (props[i].id == propertyId) {
722: return props[i].name;
723: }
724: }
725:
726: return "unknown property";
727: }
728:
729: /**
730: * Returns the blip description given a blip id.
731: *
732: * @param b blip id
733: * @return A description.
734: */
735: private String getBlipType(byte b) {
736: switch (b) {
737: case 0:
738: return " ERROR";
739: case 1:
740: return " UNKNOWN";
741: case 2:
742: return " EMF";
743: case 3:
744: return " WMF";
745: case 4:
746: return " PICT";
747: case 5:
748: return " JPEG";
749: case 6:
750: return " PNG";
751: case 7:
752: return " DIB";
753: default:
754: if (b < 32)
755: return " NotKnown";
756: else
757: return " Client";
758: }
759: }
760:
761: /**
762: * Straight conversion from OO. Converts a type of float.
763: */
764: private String dec1616(int n32) {
765: String result = "";
766: result += (short) (n32 >> 16);
767: result += '.';
768: result += (short) (n32 & (short) 0xFFFF);
769: return result;
770: }
771:
772: /**
773: * Dumps out a hex value by reading from a input stream.
774: *
775: * @param bytes How many bytes this hex value consists of.
776: * @param in The stream to read the hex value from.
777: * @param out The stream to write the nicely formatted hex value to.
778: */
779: private void outHex(int bytes, InputStream in, PrintStream out)
780: throws IOException, LittleEndian.BufferUnderrunException {
781: switch (bytes) {
782: case 1:
783: out.print(HexDump.toHex((byte) in.read()));
784: break;
785: case 2:
786: out.print(HexDump.toHex(LittleEndian.readShort(in)));
787: break;
788: case 4:
789: out.print(HexDump.toHex(LittleEndian.readInt(in)));
790: break;
791: default:
792: throw new IOException(
793: "Unable to output variable of that width");
794: }
795: }
796:
797: /**
798: * A simple test stub.
799: */
800: public static void main(String[] args) throws IOException {
801: String dump = "0F 00 00 F0 89 07 00 00 00 00 06 F0 18 00 00 00 "
802: + "05 04 00 00 02 00 00 00 05 00 00 00 01 00 00 00 "
803: + "01 00 00 00 05 00 00 00 4F 00 01 F0 2F 07 00 00 "
804: + "42 00 07 F0 B7 01 00 00 03 04 3F 14 AE 6B 0F 65 "
805: + "B0 48 BF 5E 94 63 80 E8 91 73 FF 00 93 01 00 00 "
806: + "01 00 00 00 00 00 00 00 00 00 FF FF 20 54 1C F0 "
807: + "8B 01 00 00 3F 14 AE 6B 0F 65 B0 48 BF 5E 94 63 "
808: + "80 E8 91 73 92 0E 00 00 00 00 00 00 00 00 00 00 "
809: + "D1 07 00 00 DD 05 00 00 4A AD 6F 00 8A C5 53 00 "
810: + "59 01 00 00 00 FE 78 9C E3 9B C4 00 04 AC 77 D9 "
811: + "2F 32 08 32 FD E7 61 F8 FF 0F C8 FD 05 C5 30 19 "
812: + "10 90 63 90 FA 0F 06 0C 8C 0C 5C 70 19 43 30 EB "
813: + "0E FB 05 86 85 0C DB 18 58 80 72 8C 70 16 0B 83 "
814: + "05 56 51 29 88 C9 60 D9 69 0C 6C 20 26 23 03 C8 "
815: + "74 B0 A8 0E 03 07 FB 45 56 C7 A2 CC C4 1C 06 66 "
816: + "A0 0D 2C 40 39 5E 86 4C 06 3D A0 4E 10 D0 60 D9 "
817: + "C8 58 CC E8 CF B0 80 61 3A 8A 7E 0D C6 23 AC 4F "
818: + "E0 E2 98 B6 12 2B 06 73 9D 12 E3 52 56 59 F6 08 "
819: + "8A CC 52 66 A3 50 FF 96 2B 94 E9 DF 4C A1 FE 2D "
820: + "3A 03 AB 9F 81 C2 F0 A3 54 BF 0F 85 EE A7 54 FF "
821: + "40 FB 7F A0 E3 9F D2 F4 4F 71 FE 19 58 FF 2B 31 "
822: + "7F 67 36 3B 25 4F 99 1B 4E 53 A6 5F 89 25 95 E9 "
823: + "C4 00 C7 83 12 F3 1F 26 35 4A D3 D2 47 0E 0A C3 "
824: + "41 8E C9 8A 52 37 DC 15 A1 D0 0D BC 4C 06 0C 2B "
825: + "28 2C 13 28 D4 EF 43 61 5A A0 58 3F 85 71 E0 4B "
826: + "69 9E 64 65 FE 39 C0 E5 22 30 1D 30 27 0E 74 3A "
827: + "18 60 FD 4A CC B1 2C 13 7D 07 36 2D 2A 31 85 B2 "
828: + "6A 0D 74 1D 1D 22 4D 99 FE 60 0A F5 9B EC 1C 58 "
829: + "FD 67 06 56 3F 38 0D 84 3C A5 30 0E 28 D3 AF C4 "
830: + "A4 CA FA 44 7A 0D 65 6E 60 7F 4D A1 1B 24 58 F7 "
831: + "49 AF A5 CC 0D CC DF 19 FE 03 00 F0 B1 25 4D 42 "
832: + "00 07 F0 E1 01 00 00 03 04 39 50 BE 98 B0 6F 57 "
833: + "24 31 70 5D 23 2F 9F 10 66 FF 00 BD 01 00 00 01 "
834: + "00 00 00 00 00 00 00 00 00 FF FF 20 54 1C F0 B5 "
835: + "01 00 00 39 50 BE 98 B0 6F 57 24 31 70 5D 23 2F "
836: + "9F 10 66 DA 03 00 00 00 00 00 00 00 00 00 00 D1 "
837: + "07 00 00 DD 05 00 00 4A AD 6F 00 8A C5 53 00 83 "
838: + "01 00 00 00 FE 78 9C A5 52 BF 4B 42 51 14 3E F7 "
839: + "DC 77 7A 16 45 48 8B 3C 48 A8 16 15 0D 6C 88 D0 "
840: + "04 C3 40 A3 32 1C 84 96 08 21 04 A1 C5 5C A2 35 "
841: + "82 C0 35 6A AB 1C 6A 6B A8 24 5A 83 68 08 84 84 "
842: + "96 A2 86 A0 7F C2 86 5E E7 5E F5 41 E4 10 BC 03 "
843: + "1F E7 FB F1 CE B9 F7 F1 9E 7C 05 2E 7A 37 9B E0 "
844: + "45 7B 10 EC 6F 96 5F 1D 74 13 55 7E B0 6C 5D 20 "
845: + "60 C0 49 A2 9A BD 99 4F 50 83 1B 30 38 13 0E 33 "
846: + "60 A6 A7 6B B5 37 EB F4 10 FA 14 15 A0 B6 6B 37 "
847: + "0C 1E B3 49 73 5B A5 C2 26 48 3E C1 E0 6C 08 4A "
848: + "30 C9 93 AA 02 B8 20 13 62 05 4E E1 E8 D7 7C C0 "
849: + "B8 14 95 5E BE B8 A7 CF 1E BE 55 2C 56 B9 78 DF "
850: + "08 7E 88 4C 27 FF 7B DB FF 7A DD B7 1A 17 67 34 "
851: + "6A AE BA DA 35 D1 E7 72 BE FE EC 6E FE DA E5 7C "
852: + "3D EC 7A DE 03 FD 50 06 0B 23 F2 0E F3 B2 A5 11 "
853: + "91 0D 4C B5 B5 F3 BF 94 C1 8F 24 F7 D9 6F 60 94 "
854: + "3B C9 9A F3 1C 6B E7 BB F0 2E 49 B2 25 2B C6 B1 "
855: + "EE 69 EE 15 63 4F 71 7D CE 85 CC C8 35 B9 C3 28 "
856: + "28 CE D0 5C 67 79 F2 4A A2 14 23 A4 38 43 73 9D "
857: + "2D 69 2F C1 08 31 9F C5 5C 9B EB 7B C5 69 19 B3 "
858: + "B4 81 F3 DC E3 B4 8E 8B CC B3 94 53 5A E7 41 2A "
859: + "63 9A AA 38 C5 3D 48 BB EC 57 59 6F 2B AD 73 1F "
860: + "1D 60 92 AE 70 8C BB 8F CE 31 C1 3C 49 27 4A EB "
861: + "DC A4 5B 8C D1 0B 0E 73 37 E9 11 A7 99 C7 E8 41 "
862: + "69 B0 7F 00 96 F2 A7 E8 42 00 07 F0 B4 01 00 00 "
863: + "03 04 1A BA F9 D6 A9 B9 3A 03 08 61 E9 90 FF 7B "
864: + "9E E6 FF 00 90 01 00 00 01 00 00 00 00 00 00 00 "
865: + "00 00 FF FF 20 54 1C F0 88 01 00 00 1A BA F9 D6 "
866: + "A9 B9 3A 03 08 61 E9 90 FF 7B 9E E6 12 0E 00 00 "
867: + "00 00 00 00 00 00 00 00 D1 07 00 00 DD 05 00 00 "
868: + "4A AD 6F 00 8A C5 53 00 56 01 00 00 00 FE 78 9C "
869: + "E3 13 62 00 02 D6 BB EC 17 19 04 99 FE F3 30 FC "
870: + "FF 07 E4 FE 82 62 98 0C 08 C8 31 48 FD 07 03 06 "
871: + "46 06 2E B8 8C 21 98 75 87 FD 02 C3 42 86 6D 0C "
872: + "2C 40 39 46 38 8B 85 C1 02 AB A8 14 C4 64 B0 EC "
873: + "34 06 36 10 93 91 01 64 3A 58 54 87 81 83 FD 22 "
874: + "AB 63 51 66 62 0E 03 33 D0 06 16 A0 1C 2F 43 26 "
875: + "83 1E 50 27 08 68 B0 6C 64 2C 66 F4 67 58 C0 30 "
876: + "1D 45 BF 06 E3 11 D6 27 70 71 4C 5B 89 15 83 B9 "
877: + "4E 89 71 29 AB 2C 7B 04 45 66 29 B3 51 A8 7F CB "
878: + "15 CA F4 6F A6 50 FF 16 9D 81 D5 CF 40 61 F8 51 "
879: + "AA DF 87 42 F7 53 AA 7F A0 FD 3F D0 F1 4F 69 FA "
880: + "A7 38 FF 0C AC FF 95 98 BF 33 9B 9D 92 A7 CC 0D "
881: + "A7 29 D3 AF C4 92 CA 74 62 80 E3 41 89 F9 0F 93 "
882: + "1A A5 69 E9 23 07 85 E1 20 C7 64 45 A9 1B EE 8A "
883: + "50 E8 06 5E 26 03 86 15 14 96 09 14 EA F7 A1 30 "
884: + "2D 50 AC 9F C2 38 F0 A5 34 4F B2 32 FF 1C E0 72 "
885: + "11 98 0E 98 13 07 38 1D 28 31 C7 B2 4C F4 1D D8 "
886: + "B4 A0 C4 14 CA AA 35 D0 75 64 88 34 65 FA 83 29 "
887: + "D4 6F B2 73 60 F5 9F A1 54 FF 0E CA D3 40 C8 53 "
888: + "0A E3 E0 09 85 6E 50 65 7D 22 BD 86 32 37 B0 BF "
889: + "A6 D0 0D 12 AC FB A4 D7 52 E6 06 E6 EF 0C FF 01 "
890: + "97 1D 12 C7 42 00 07 F0 C3 01 00 00 03 04 BA 4C "
891: + "B6 23 BA 8B 27 BE C8 55 59 86 24 9F 89 D4 FF 00 "
892: + "9F 01 00 00 01 00 00 00 00 00 00 00 00 00 FF FF "
893: + "20 54 1C F0 97 01 00 00 BA 4C B6 23 BA 8B 27 BE "
894: + "C8 55 59 86 24 9F 89 D4 AE 0E 00 00 00 00 00 00 "
895: + "00 00 00 00 D1 07 00 00 DD 05 00 00 4A AD 6F 00 "
896: + "8A C5 53 00 65 01 00 00 00 FE 78 9C E3 5B C7 00 "
897: + "04 AC 77 D9 2F 32 08 32 FD E7 61 F8 FF 0F C8 FD "
898: + "05 C5 30 19 10 90 63 90 FA 0F 06 0C 8C 0C 5C 70 "
899: + "19 43 30 EB 0E FB 05 86 85 0C DB 18 58 80 72 8C "
900: + "70 16 0B 83 05 56 51 29 88 C9 60 D9 69 0C 6C 20 "
901: + "26 23 03 C8 74 B0 A8 0E 03 07 FB 45 56 C7 A2 CC "
902: + "C4 1C 06 66 A0 0D 2C 40 39 5E 86 4C 06 3D A0 4E "
903: + "10 D0 60 99 C6 B8 98 D1 9F 61 01 C3 74 14 FD 1A "
904: + "8C 2B D8 84 B1 88 4B A5 A5 75 03 01 50 DF 59 46 "
905: + "77 46 0F A8 3C A6 AB 88 15 83 B9 5E 89 B1 8B D5 "
906: + "97 2D 82 22 B3 94 29 D5 BF E5 CA C0 EA DF AC 43 "
907: + "A1 FD 14 EA 67 A0 30 FC 28 D5 EF 43 A1 FB 7D 87 "
908: + "B8 FF 07 3A FE 07 3A FD 53 EA 7E 0A C3 4F 89 F9 "
909: + "0E 73 EA 69 79 CA DC 70 8A 32 FD 4A 2C 5E 4C DF "
910: + "87 7A 3C BC E0 A5 30 1E 3E 31 C5 33 AC A0 30 2F "
911: + "52 A8 DF 87 C2 30 A4 54 3F A5 65 19 85 65 A9 12 "
912: + "D3 2B 16 0D 8A CB 13 4A F3 E3 27 E6 09 03 9D 0E "
913: + "06 58 BF 12 B3 13 CB C1 01 4E 8B 4A 4C 56 AC 91 "
914: + "03 5D 37 86 48 53 A6 3F 98 42 FD 26 3B 07 56 FF "
915: + "99 1D 14 EA A7 CC 7E 70 1A 08 79 42 61 1C 3C A5 "
916: + "D0 0D 9C 6C C2 32 6B 29 73 03 DB 6B CA DC C0 F8 "
917: + "97 F5 AD CC 1A CA DC C0 F4 83 32 37 B0 A4 30 CE "
918: + "FC C7 48 99 1B FE 33 32 FC 07 00 6C CC 2E 23 33 "
919: + "00 0B F0 12 00 00 00 BF 00 08 00 08 00 81 01 09 "
920: + "00 00 08 C0 01 40 00 00 08 40 00 1E F1 10 00 00 "
921: + "00 0D 00 00 08 0C 00 00 08 17 00 00 08 F7 00 00 "
922: + "10 ";
923:
924: // Decode the stream to bytes
925: byte[] bytes = HexRead.readData(new ByteArrayInputStream(dump
926: .getBytes()), -1);
927: // Create a new instance of the escher dumper
928: EscherDump dumper = new EscherDump();
929: // Dump the contents of scher to screen.
930: // dumper.dumpOld( bytes.length, new ByteArrayInputStream( bytes ), System.out );
931: dumper.dump(bytes, 0, bytes.length, System.out);
932:
933: }
934:
935: public void dump(int recordSize, byte[] data, PrintStream out)
936: throws IOException, LittleEndian.BufferUnderrunException {
937: // ByteArrayInputStream is = new ByteArrayInputStream( data );
938: // dump( recordSize, is, out );
939: dump(data, 0, recordSize, System.out);
940: }
941: }
|