Statistics
| Revision:

root / trunk / libraries / libDwg / src / com / iver / cit / jdwglib / dwg / DwgUtil.java @ 10878

History | View | Annotate | Download (27.6 KB)

1
/* jdwglib. Java Library for reading Dwg files.
2
 * 
3
 * Author: Jose Morell Rama (jose.morell@gmail.com).
4
 * Port from the Pythoncad Dwg library by Art Haas.
5
 *
6
 * Copyright (C) 2005 Jose Morell, IVER TI S.A. and Generalitat Valenciana
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
21
 *
22
 * For more information, contact:
23
 *
24
 * Jose Morell (jose.morell@gmail.com)
25
 * 
26
 * or
27
 *
28
 * IVER TI S.A.
29
 *  C/Salamanca, 50
30
 *  46005 Valencia
31
 *  Spain
32
 *  +34 963163400
33
 *  dac@iver.es
34
 */
35
package com.iver.cit.jdwglib.dwg;
36

    
37
import java.nio.ByteBuffer;
38
import java.nio.ByteOrder;
39
import java.util.ArrayList;
40
import java.util.List;
41

    
42
import com.iver.cit.gvsig.fmap.drivers.dgn.ByteUtils;
43

    
44
import freenet.support.HexUtil;
45

    
46
/**
47
 * The DwgUtil class contains the essential set of functions for reading bitstreams
48
 * in DWG files
49
 * 
50
 * @author jmorell
51
 */
52
public final class DwgUtil {
53
    
54
        /**
55
         * Read the extended data for a DWG object
56
         * Don't use in this version. Serious bugs detected
57
         * 
58
         * @param data Array of unsigned bytes obtained from the DWG binary file
59
         * @param offset The current bit offset where the value begins
60
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
61
         *                    when we are looking for LwPolylines.
62
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
63
         *                    the new offset, and second is the extended data of a DWG object 
64
         */
65
        public static ArrayList readExtendedData(int[] data, int offset) throws RuntimeException {
66
                int bitPos = offset;
67
                ArrayList extData = new ArrayList();
68
                while (true) {
69
                        int newBitPos = ((Integer)getBitShort(data, bitPos).get(0)).intValue();
70
                        int size = ((Integer)getBitShort(data, bitPos).get(1)).intValue();
71
                        bitPos = newBitPos;
72
                        if (size==0) {
73
                                break;
74
                        }
75
                        newBitPos = ((Integer)((ArrayList)getHandle(data, bitPos)).get(0)).intValue();
76
                        // TODO: Esto no es correcto. Repasar ...
77
                        int handle = ((Integer)((ArrayList)getHandle(data, bitPos)).get(1)).intValue();
78
                        bitPos = newBitPos;
79
                        ArrayList eedata = new ArrayList();
80
                        while (size>0) {
81
                                newBitPos = ((Integer)getRawChar(data, bitPos).get(0)).intValue();
82
                                int cb = ((Integer)getRawChar(data, bitPos).get(1)).intValue();
83
                                bitPos = newBitPos;
84
                                size = size-1;
85
                                if (cb==0x0) {
86
                                        newBitPos = ((Integer)getRawChar(data, bitPos).get(0)).intValue();
87
                                        int len = ((Integer)getRawChar(data, bitPos).get(1)).intValue();
88
                                        bitPos = newBitPos;
89
                                        newBitPos = ((Integer)getRawShort(data, bitPos).get(0)).intValue();
90
                                        int cp = ((Integer)getRawShort(data, bitPos).get(1)).intValue();
91
                                        bitPos = newBitPos;
92
                                        ArrayList chars = new ArrayList();
93
                                        for (int i=0; i<len; i++) {
94
                                                newBitPos = ((Integer)getRawChar(data, bitPos).get(0)).intValue();
95
                                                int charr = ((Integer)getRawChar(data, bitPos).get(1)).intValue();
96
                                                bitPos = newBitPos;
97
                                                // ?int o char?
98
                                                chars.add(new Integer(charr));
99
                                        }
100
                                        // Incorrecto. Repasar ...
101
                                        eedata.add(chars);
102
                                        size = size-len-3;
103
                                } else if (cb==0x1) {
104
                                        System.out.println("Invalid EXX code byte: 0x1");
105
                                } else if (cb==0x2) {
106
                                        newBitPos = ((Integer)getRawChar(data, bitPos).get(0)).intValue();
107
                                        int charr = ((Integer)getRawChar(data, bitPos).get(1)).intValue();
108
                                        bitPos = newBitPos;
109
                                        if (charr==0x0) {
110
                                                eedata.add("{");
111
                                        } else if (charr==0x1) {
112
                                                eedata.add("}");
113
                                        } else {
114
                                                System.out.println("Unexpected EXX char: " + charr);
115
                                        }
116
                                        size = size - 1;
117
                                } else if (cb==0x3 || cb==0x5) {
118
                                        ArrayList chars = new ArrayList();
119
                                        for (int i=0; i<8; i++) {
120
                                                newBitPos = ((Integer)getRawChar(data, bitPos).get(0)).intValue();
121
                                                int charr = ((Integer)getRawChar(data, bitPos).get(1)).intValue();
122
                                                bitPos = newBitPos;
123
                                                chars.add(new Integer(charr));
124
                                        }
125
                                        eedata.add(chars);
126
                                        size = size - 8;
127
                                } else if (cb==0x4) {
128
                                        newBitPos = ((Integer)getRawChar(data, bitPos).get(0)).intValue();
129
                                        int len = ((Integer)getRawChar(data, bitPos).get(1)).intValue();
130
                                        bitPos = newBitPos;
131
                                        ArrayList chars = new ArrayList();
132
                                        for (int i=0; i<len; i++) {
133
                                                newBitPos = ((Integer)getRawChar(data, bitPos).get(0)).intValue();
134
                                                int charr = ((Integer)getRawChar(data, bitPos).get(1)).intValue();
135
                                                bitPos = newBitPos;
136
                                                chars.add(new Integer(charr));
137
                                        }
138
                                        eedata.add(chars);
139
                                        size = size - len -1;
140
                                } else if (0xa<=cb && cb<=0xd) {
141
                                        newBitPos = ((Integer)((ArrayList)getRawDouble(data, bitPos)).get(0)).intValue();
142
                                        double d1 = ((Double)((ArrayList)getRawDouble(data, bitPos)).get(1)).doubleValue();
143
                                        bitPos = newBitPos;
144
                                        newBitPos = ((Integer)((ArrayList)getRawDouble(data, bitPos)).get(0)).intValue();
145
                                        double d2 = ((Double)((ArrayList)getRawDouble(data, bitPos)).get(1)).doubleValue();
146
                                        bitPos = newBitPos;
147
                                        newBitPos = ((Integer)((ArrayList)getRawDouble(data, bitPos)).get(0)).intValue();
148
                                        double d3 = ((Double)((ArrayList)getRawDouble(data, bitPos)).get(1)).doubleValue();
149
                                        bitPos = newBitPos;
150
                                        eedata.add(new double[]{d1, d2, d3});
151
                                        size = size - 24;
152
                                } else if (0x28<=cb && cb<=0x2a) {
153
                                        newBitPos = ((Integer)((ArrayList)getRawDouble(data, bitPos)).get(0)).intValue();
154
                                        double d = ((Double)((ArrayList)getRawDouble(data, bitPos)).get(1)).doubleValue();
155
                                        bitPos = newBitPos;
156
                                        eedata.add(new Double(d));
157
                                        size=size-8;
158
                                } else if (cb==0x46) {
159
                                        newBitPos = ((Integer)getRawShort(data, bitPos).get(0)).intValue();
160
                                        int shortt = ((Integer)getRawShort(data, bitPos).get(1)).intValue();
161
                                        bitPos = newBitPos;
162
                                        eedata.add(new Integer(shortt));
163
                                        size=size-2;
164
                                } else if (cb==0x47) {
165
                                        newBitPos = ((Integer)getRawLong(data, bitPos).get(0)).intValue();
166
                                        int longg = ((Integer)getRawLong(data, bitPos).get(1)).intValue();
167
                                        bitPos = newBitPos;
168
                                        eedata.add(new Integer(longg));
169
                                        size=size-4;
170
                                } else {
171
                                        System.out.println("Unexpected code byte: " + cb);
172
                                }
173
                        }
174
                        ArrayList v = new ArrayList();
175
                        //v.add(handle, eedata);
176
                        extData.add(v);
177
                }
178
                ArrayList v = new ArrayList();
179
                v.add(new Integer(bitPos));
180
                v.add(extData);
181
                return v;
182
        }
183
        /**
184
         * Read a double value from a group of unsigned bytes and a default double
185
         * 
186
         * @param data Array of unsigned bytes obtained from the DWG binary file
187
         * @param offset The current bit offset where the value begins
188
         * @param defVal Default double value
189
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
190
         *                    when we are looking for LwPolylines.
191
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
192
         *                    the new offset, and second is the double value
193
         */
194
        public static ArrayList getDefaultDouble(int[] data, int offset, double defVal) throws RuntimeException {
195
            int flags = ((Integer)getBits(data, 2, offset)).intValue();
196
            int read = 2;
197
            double val;
198
            if (flags==0x0) {
199
                    val = defVal;
200
            } else {
201
                    int _offset = offset + 2;
202
                    if (flags==0x3) {
203
                            byte[] bytes = (byte[])getBits(data, 64, _offset);
204
                            ByteBuffer bb = ByteBuffer.wrap(bytes);
205
                            bb.order(ByteOrder.LITTLE_ENDIAN);
206
                            val = bb.getDouble();
207
                            read = 66;
208
                    } else {
209
                            byte[] dstrArrayAux = new byte[8];
210
                            int[] doubleOffset = new int[]{0};
211
                            ByteUtils.doubleToBytes(defVal, dstrArrayAux, doubleOffset);
212
                            byte[] dstrArrayAuxx = new byte[8];
213
                            dstrArrayAuxx[0] = dstrArrayAux[7];
214
                            dstrArrayAuxx[1] = dstrArrayAux[6];
215
                            dstrArrayAuxx[2] = dstrArrayAux[5];
216
                            dstrArrayAuxx[3] = dstrArrayAux[4];
217
                            dstrArrayAuxx[4] = dstrArrayAux[3];
218
                            dstrArrayAuxx[5] = dstrArrayAux[2];
219
                            dstrArrayAuxx[6] = dstrArrayAux[1];
220
                            dstrArrayAuxx[7] = dstrArrayAux[0];
221
                            int[] dstrArrayAuxxx = new int[8];
222
                            for (int i=0;i<dstrArrayAuxxx.length;i++) {
223
                                dstrArrayAuxxx[i] = ByteUtils.getUnsigned(dstrArrayAuxx[i]);
224
                            }
225
                            byte[] dstrArray = new byte[8];
226
                            for (int i=0;i<dstrArray.length;i++) {
227
                                    dstrArray[i] = (byte)dstrArrayAuxxx[i];
228
                            }
229
                            if (flags==0x1) {
230
                                byte[] ddArray = (byte[])getBits(data, 32, _offset);
231
                                    dstrArray[0] = ddArray[0];
232
                                dstrArray[1] = ddArray[1];
233
                                dstrArray[2] = ddArray[2];
234
                                dstrArray[3] = ddArray[3];
235
                                read = 34;
236
                            } else {
237
                                byte[] ddArray = (byte[])getBits(data, 48, _offset);
238
                                    dstrArray[4] = ddArray[0];
239
                                dstrArray[5] = ddArray[1];
240
                                dstrArray[0] = ddArray[2];
241
                                dstrArray[1] = ddArray[3];
242
                                dstrArray[2] = ddArray[4];
243
                                dstrArray[3] = ddArray[5];
244
                                read = 50;
245
                            }
246
                            ByteBuffer bb = ByteBuffer.wrap(dstrArray);
247
                            bb.order(ByteOrder.LITTLE_ENDIAN);
248
                            val = bb.getDouble();
249
                    }
250
            }
251
            ArrayList v = new ArrayList();
252
                v.add(new Integer(offset+read));
253
                v.add(new Double(val));
254
                return v;
255
        }
256
        /**
257
         * Read a double value from a group of unsigned bytes
258
         * 
259
         * @param data Array of unsigned bytes obtained from the DWG binary file
260
         * @param offset The current bit offset where the value begins
261
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
262
         *                    when we are looking for LwPolylines.
263
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
264
         *                    the new offset, and second is the double value
265
         */
266
        public static ArrayList getBitDouble(int[] data, int offset) throws RuntimeException {
267
                ArrayList v = new ArrayList();
268
                int type = ((Integer)getBits(data, 2, offset)).intValue();
269
                int read = 2;
270
                double val = 0.0;
271
                if (type==0x00) {
272
                        byte[] bytes = (byte[])getBits(data, 64, (offset+2));
273
                        ByteBuffer bb = ByteBuffer.wrap(bytes);
274
                        bb.order(ByteOrder.LITTLE_ENDIAN);
275
                        val = bb.getDouble();
276
                        read = 66;
277
                } else if (type==0x01) {
278
                        val = 1.0;
279
                } else if (type==0x02) {
280
                        val = 0.0;
281
                } else {
282
                        System.out.println("Bad type " + type + " at bit offset: " + offset);
283
                }
284
                v.add(new Integer(offset+read));
285
                v.add(new Double(val));
286
                return v;
287
        }
288
        /**
289
         * Read a double value from a group of unsigned bytes
290
         * 
291
         * @param data Array of unsigned bytes obtained from the DWG binary file
292
         * @param offset The current bit offset where the value begins
293
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
294
         *                    when we are looking for LwPolylines.
295
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
296
         *                    the new offset, and second is the double value
297
         */
298
        public static ArrayList getRawDouble(int[] data, int offset) throws RuntimeException {
299
            byte[] bytes = (byte[])getBits(data, 64, offset);
300
                ByteBuffer bb = ByteBuffer.wrap(bytes);
301
                bb.order(ByteOrder.LITTLE_ENDIAN);
302
                double val = bb.getDouble();
303
                ArrayList v = new ArrayList();
304
                v.add(new Integer(offset+64));
305
                v.add(new Double(val));
306
                return v;
307
        }
308
        /**
309
         * Read a short value from a group of unsigned bytes
310
         * 
311
         * @param data Array of unsigned bytes obtained from the DWG binary file
312
         * @param offset The current bit offset where the value begins
313
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
314
         *                    when we are looking for LwPolylines.
315
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
316
         *                    the new offset, and second is the short value
317
         */
318
        public static ArrayList getBitShort(int[] data, int offset) throws RuntimeException {
319
                ArrayList v = new ArrayList();
320
                int type = ((Integer)getBits(data, 2, offset)).intValue();
321
                int read = 2;
322
                int val = 0;
323
                if (type==0x00) {
324
                        byte[] bytes = (byte[])getBits(data, 16, (offset+2));
325
                        ByteBuffer bb = ByteBuffer.wrap(bytes);
326
                        bb.order(ByteOrder.LITTLE_ENDIAN);
327
                        val = bb.getShort();
328
                        read = 18;
329
                } else if (type==0x01) {
330
                        val = ((Integer)getBits(data, 8, (offset+2))).intValue();
331
                        read = 10;
332
                } else if (type==0x02) {
333
                        val = 0;
334
                } else if (type==0x03) {
335
                        val = 256;
336
                }
337
                v.add(new Integer(offset+read));
338
                v.add(new Integer(val));
339
                return v;
340
        }
341
        /**
342
         * Read a short value from a group of unsigned bytes
343
         * 
344
         * @param data Array of unsigned bytes obtained from the DWG binary file
345
         * @param offset The current bit offset where the value begins
346
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
347
         *                    when we are looking for LwPolylines.
348
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
349
         *                    the new offset, and second is the short value
350
         */
351
        public static ArrayList getRawShort(int[] data, int offset) throws RuntimeException {
352
                byte[] bytes = (byte[])getBits(data, 16, offset);
353
                ByteBuffer bb = ByteBuffer.wrap(bytes);
354
                bb.order(ByteOrder.LITTLE_ENDIAN);
355
                int val = bb.getShort();
356
                ArrayList v = new ArrayList();
357
                v.add(new Integer(offset+16));
358
                v.add(new Integer(val));
359
                return v;
360
        }
361
        /**
362
         * Read a long value from a group of unsigned bytes
363
         * 
364
         * @param data Array of unsigned bytes obtained from the DWG binary file
365
         * @param offset The current bit offset where the value begins
366
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
367
         *                    when we are looking for LwPolylines.
368
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
369
         *                    the new offset, and second is the long value
370
         */
371
        public static ArrayList getBitLong(int[] data, int offset) throws RuntimeException {
372
            int type = ((Integer)getBits(data, 2, offset)).intValue();
373
            int read = 2;
374
            int val = 0;
375
            if (type==0x0) {
376
                    byte[] bytes = (byte[])getBits(data, 32, (offset+2));
377
                    ByteBuffer bb = ByteBuffer.wrap(bytes);
378
                    bb.order(ByteOrder.LITTLE_ENDIAN);
379
                    val = bb.getInt();
380
                    read = 34;
381
            } else if (type==0x01) {
382
                    val = ((Integer)getBits(data, 8, (offset+2))).intValue();
383
                    read = 10;
384
            } else if (type==0x02) {
385
                    val = 0;
386
            } else {
387
                        System.out.println("Bad type at bit offset: " + offset);
388
            }
389
            ArrayList v = new ArrayList();
390
            v.add(new Integer(offset+read));
391
            v.add(new Integer(val));
392
            return v;
393
        }
394
        /**
395
         * Read a long value from a group of unsigned bytes
396
         * 
397
         * @param data Array of unsigned bytes obtained from the DWG binary file
398
         * @param offset The current bit offset where the value begins
399
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
400
         *                    when we are looking for LwPolylines.
401
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
402
         *                    the new offset, and second is the long value
403
         * @throws RuntimeException 
404
         */
405
        public static ArrayList getRawLong(int[] data, int offset) throws RuntimeException {
406
                ArrayList v = new ArrayList();
407
            // _val = struct.unpack('<l', _long)[0]
408
                byte[] bytes = (byte[])getBits(data, 32, offset);
409
                ByteBuffer bb = ByteBuffer.wrap(bytes);
410
                bb.order(ByteOrder.LITTLE_ENDIAN);
411
                int val = bb.getInt();
412
                v.add(new Integer(offset+32));
413
                v.add(new Integer(val));
414
                return v;
415
        }
416
        /**
417
         * Read a char value from a group of unsigned bytes
418
         * 
419
         * @param data Array of unsigned bytes obtained from the DWG binary file
420
         * @param offset The current bit offset where the value begins
421
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
422
         *                    when we are looking for LwPolylines.
423
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
424
         *                    the new offset, and second is the char value
425
         */
426
        public static ArrayList getRawChar(int[] data, int offset) throws RuntimeException {
427
                int charr = ((Integer)getBits(data, 8, offset)).intValue();
428
            ArrayList v = new ArrayList();
429
            v.add(new Integer(offset+8));
430
            v.add(new Integer(charr));
431
                return v;
432
        }
433
        /**
434
         * Read a char value from a group of unsigned bytes
435
         * 
436
         * @param data Array of unsigned bytes obtained from the DWG binary file
437
         * @param offset The current bit offset where the value begins
438
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
439
         *                    when we are looking for LwPolylines.
440
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
441
         *                    the new offset, and second is the char value
442
         */
443
        public static ArrayList getModularChar(int[] data, int offset) throws RuntimeException {
444
                int val=0;
445
                ArrayList bytes = new ArrayList();
446
                boolean read = true;
447
                int offsett = offset;
448
                int fac = 1;
449
                while (read) {
450
                        int bytee = ((Integer)getBits(data, 8, offsett)).intValue();
451
                        offsett = offsett + 8;
452
                        if ((bytee & 0x80)==0) {
453
                                read = false;
454
                                if ((bytee & 0x40)>0) {
455
                                        fac = -1;
456
                                        bytee = bytee & 0xbf;
457
                                }
458
                        }
459
                        bytes.add(new Integer(bytee & 0x7f));
460
                }
461
                if (bytes.size()==1) val = ((Integer)bytes.get(0)).intValue();
462
                else if (bytes.size()==2) val = ((Integer)bytes.get(0)).intValue() | (((Integer)bytes.get(1)).intValue() << 7);
463
                else if (bytes.size()==3) val = ((Integer)bytes.get(0)).intValue() | (((Integer)bytes.get(1)).intValue() << 7) | (((Integer)bytes.get(2)).intValue() << 14);
464
                else if (bytes.size()==4) val = ((Integer)bytes.get(0)).intValue() | (((Integer)bytes.get(1)).intValue() << 7) | (((Integer)bytes.get(2)).intValue() << 14) | (((Integer)bytes.get(3)).intValue() << 21);
465
                else System.out.println("Unexpected byte array length: " + bytes.size());
466
                ArrayList v = new ArrayList();
467
                v.add(new Integer(offsett));
468
                v.add(new Integer(fac*val));
469
                return v;
470
        }
471
        /**
472
         * Read a String from a group of unsigned bytes
473
         * 
474
         * @param data Array of unsigned bytes obtained from the DWG binary file
475
         * @param offset The current bit offset where the value begins
476
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
477
         *                    when we are looking for LwPolylines.
478
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
479
         *                    the new offset, and second is the String
480
         */
481
        public static ArrayList getTextString(int[] data, int offset) throws RuntimeException {
482
                int bitPos = offset;
483
                ArrayList bitShort = DwgUtil.getBitShort(data, bitPos);
484
            int newBitPos = ((Integer)bitShort.get(0)).intValue();
485
            int len = ((Integer)bitShort.get(1)).intValue();
486
            bitPos = newBitPos;
487
            int bitLen = len * 8;
488
            Object cosa = DwgUtil.getBits(data, bitLen, bitPos);
489
            String string;
490
            if (cosa instanceof byte[]) {
491
                    string = new String((byte[])cosa);
492
            } else {
493
                    //string = ((Integer)cosa).toString();
494
                    byte[] bytes = new byte[]{((Integer)cosa).byteValue()};
495
                    string = new String((byte[])bytes);
496
            }
497
            bitPos = bitPos + bitLen;
498
            ArrayList v = new ArrayList();
499
            v.add(new Integer(bitPos));
500
            v.add(string);
501
            return v;
502
        }
503
        /**
504
         * Read a int value (the handle of a DWG object) from a group of unsigned bytes
505
         * 
506
         * @param data Array of unsigned bytes obtained from the DWG binary file
507
         * @param offset The current bit offset where the value begins
508
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
509
         *                    when we are looking for LwPolylines.
510
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
511
         *                    the new offset, and second is the int value (handle of a DWG object)
512
         */
513
        public static ArrayList getHandle(int[] data, int offset) throws RuntimeException {
514
                ArrayList v = new ArrayList();
515
                int code = ((Integer)DwgUtil.getBits(data, 4, offset)).intValue();
516
            int counter = ((Integer)DwgUtil.getBits(data, 4, (offset + 4))).intValue();
517
            int read = 8;
518
            ArrayList hlist = new ArrayList();
519
            if (counter>0) {
520
                int hlen = counter * 8;
521
                Object handle = DwgUtil.getBits(data, hlen, (offset + 8));
522
                read = read + hlen;
523
                if (hlen > 8) {
524
                        byte[] handleBytes = (byte[])handle;
525
                        int[] handleInts = new int[handleBytes.length];
526
                            // Hacerlos unsigned ...
527
                            for (int i=0; i<handleBytes.length; i++) {
528
                                    handleInts[i] = ByteUtils.getUnsigned(handleBytes[i]);
529
                            }
530
                        for (int i=0; i<handleInts.length; i++) {
531
                                hlist.add(new Integer(handleInts[i]));
532
                        }
533
                } else {
534
                    hlist.add(handle);
535
                }
536
            }
537
            v.add(new Integer(offset+read));
538
            v.add(new Integer(code));
539
            v.add(new Integer(counter));
540
            for (int i=0;i<hlist.size();i++) {
541
                    v.add(hlist.get(i));
542
            }
543
                return v;
544
        }
545
        /**
546
         * Read a int value (the size of a modular short) from a ByteBuffer
547
         * 
548
         * @param bb Data given as a ByteBuffer
549
         * @return int Size of the modular short
550
         */
551
        public static int getModularShort(ByteBuffer bb) {
552
                ArrayList shorts = new ArrayList();
553
                bb.order(ByteOrder.BIG_ENDIAN);
554
                short shortt = bb.getShort();
555
                int size = 0;
556
                while ((shortt & 0x80)>0) {
557
                        shorts.add(new Short(shortt));
558
                        shortt = bb.getShort();
559
                }
560
                shorts.add(new Short(shortt));
561
                for (int i=0; i<shorts.size(); i++) {
562
                        shortt = ((Short)shorts.get(i)).shortValue();
563
                        shorts.set(i, new Integer(((shortt & 0xff00) >> 8) | ((shortt & 0xff) << 8)));
564
                }
565
                int slen = shorts.size();
566
                if (slen==1) {
567
                        size = (((Integer)shorts.get(0)).intValue()) & 0x7fff;//(new Integer(((Integer)shorts.get(0)).shortValue() & 0x7fff)).byteValue();
568
                } else if (slen==2) {
569
                        int tmp = ((Integer)shorts.get(0)).intValue();
570
                        shorts.set(0, shorts.get(1));
571
                        shorts.set(1, new Integer(tmp));
572
                        size = (((((Integer)shorts.get(0)).intValue()) & 0x7fff) << 15) | (((((Integer)shorts.get(1)).intValue()) & 0x7fff));//(new Integer(((Integer)shorts.get(0)).shortValue() & 0x7fff)).byteValue();
573
                } else {
574
                        System.out.println("Unexpected array length: " + slen);
575
                }
576
                return size;
577
        }
578
        /**
579
         * Returns a set of bits from a group of unsigned bytes
580
         * 
581
         * @param data Array of unsigned bytes obtained from the DWG binary file
582
         * @param count Bit counter
583
         * @param offset The current bit offset where the value begins
584
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
585
         *                    when we are looking for LwPolylines.
586
         * @return This method returns an array of bytes or an int value
587
         */
588
        public static Object getBits(int[] data, int count, int offset) throws RuntimeException {
589
                int idx = offset/8;
590
                int bitidx = offset%8;
591
                /**
592
                 * mask1: bit mask to apply to the current byte
593
                 * lshift: left shift amount of mask results
594
                 * mask2: bit mask to apply to the next byte
595
                 * rshift: right shift amount of the mask results
596
                 */
597
                int[][] maskTable = new int[][]{
598
                    {0xff, 0, 0x00, 0}, // bit offset == 0
599
                    {0x7f, 1, 0x80, 7}, // bit offset == 1
600
                    {0x3f, 2, 0xc0, 6}, // bit offset == 2
601
                    {0x1f, 3, 0xe0, 5}, // bit offset == 3
602
                    {0x0f, 4, 0xf0, 4}, // bit offset == 4
603
                    {0x07, 5, 0xf8, 3}, // bit offset == 5
604
                    {0x03, 6, 0xfc, 2}, // bit offset == 6
605
                    {0x01, 7, 0xfe, 1}, // bit offset == 7
606
                };
607
                int mask1 = maskTable[bitidx][0];
608
                int lsh = maskTable[bitidx][1];
609
                int mask2 = maskTable[bitidx][2];
610
                int rsh = maskTable[bitidx][3];
611
                int binc = 8 - bitidx;
612
                int read = 0;
613
                int rem = count;
614
                int bytee = 0x0;
615
                ArrayList bytes = new ArrayList();
616
                while (read < count) {
617
                        int b1 = 0;
618
                        if (rem > binc) {
619
                                b1 = (data[idx] & mask1);
620
                                read = read + binc;
621
                                rem = rem - binc;
622
                        } else {
623
                    b1 = ((data[idx] & mask1) >> (8 - bitidx - rem));
624
                    bytee = b1;
625
                                read = read + rem;
626
                                rem = 0;
627
                        }
628
                        if (read < count) {
629
                                idx = idx + 1;
630
                                if (rem > bitidx) {
631
                        int b2 = (data[idx] & mask2);
632
                        bytee = (b1 << lsh) | (b2 >> rsh);
633
                        read = read + bitidx;
634
                        rem = rem - bitidx;
635
                                } else {
636
                        int mask = maskTable[rem][2];
637
                        int b2 = data[idx] & mask;
638
                        bytee = (b1 << rem) | (b2 >> (8 - rem));
639
                        read = read + rem;
640
                        rem = 0;
641
                                }
642
                        }
643
                        if (count > 8) {
644
                                bytes.add(new Integer(bytee));
645
                        }
646
                }
647
                if (bytes.size()>0) {
648
                        byte[] newBytes = new byte[bytes.size()];
649
                        for (int i=0; i<newBytes.length; i++) {
650
                                newBytes[i] = ((Integer)bytes.get(i)).byteValue();
651
                        }
652
                        return newBytes;
653
                }
654
                return new Integer(bytee);
655
        }
656
        /**
657
         * Test a bit obtained from a set of unsigned bytes
658
         * 
659
         * @param data Array of unsigned bytes obtained from the DWG binary file
660
         * @param offset The current bit offset where the value begins
661
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
662
         *                    the new offset, and second is a bit flag
663
         */
664
        public static ArrayList testBit(int[] data, int offset) {
665
                int idx = offset/8;
666
                int bitidx = offset%8;
667
                int mask = 0x1 << (7-bitidx);
668
                boolean val = false;
669
                if ((data[idx] & mask) > 0) val = true;
670
                ArrayList v = new ArrayList();
671
                v.add(new Integer(offset+1));
672
                v.add(new Boolean(val));
673
                return v;
674
        }
675
        /**
676
         * Convert bytes to machine value bytes
677
         * 
678
         * @param data Input of array of bytes
679
         * @return int[] Output of array of machine bytes
680
         */
681
        public static int[] bytesToMachineBytes(byte[] data) {
682
                String[] dataString = new String[data.length];
683
                int[] dataOut = new int[data.length];
684
                for (int i=0; i<data.length; i++) {
685
                        dataString[i] = HexUtil.bytesToHex(new byte[]{data[i]});
686
                        Integer dataInt = Integer.decode("0x" + dataString[i]);
687
                        dataOut[i] = dataInt.intValue();
688
                }
689
                return dataOut;
690
        }
691
        
692
        
693
        
694
        
695
    
696
    
697
    /**
698
     * It receives the list procedent from getHandle method, and return the
699
     * handle as int
700
     * 
701
     * */
702
        public static int handleToInt(List fromGetHandle){
703
            
704
            int[] handle = new int[fromGetHandle.size()-1];
705
        for (int j=1; j< fromGetHandle.size(); j++) {
706
                handle[j-1] = ((Integer)fromGetHandle.get(j)).intValue();
707
        }
708
        ArrayList handleVect = new ArrayList();
709
        for (int i=0;i<handle.length;i++) {
710
                handleVect.add(new Integer(handle[i]));
711
        }
712
        return DwgUtil.handleBinToHandleInt(handleVect);
713
            
714
            
715
    }
716
        /**
717
         * Obtain the int value of a handle given in binary format 
718
         * 
719
         * @param layerHandle Handle in binary format
720
         * @return int Int value of the handle
721
         */
722
        public static int handleBinToHandleInt(ArrayList layerHandle) {
723
                byte[] layerBytes = new byte[]{0,0,0,0};
724
                if (layerHandle.size()>2) layerBytes[3] = (byte)((Integer)layerHandle.get(2)).intValue();
725
                if (layerHandle.size()>3) {
726
                        layerBytes[3] = (byte)((Integer)layerHandle.get(3)).intValue();
727
                        layerBytes[2] = (byte)((Integer)layerHandle.get(2)).intValue();
728
                }
729
                if (layerHandle.size()>4) {
730
                        layerBytes[3] = (byte)((Integer)layerHandle.get(4)).intValue();
731
                        layerBytes[2] = (byte)((Integer)layerHandle.get(3)).intValue();
732
                        layerBytes[1] = (byte)((Integer)layerHandle.get(2)).intValue();
733
                }
734
                if (layerHandle.size()>5) {
735
                        layerBytes[3] = (byte)((Integer)layerHandle.get(5)).intValue();
736
                        layerBytes[2] = (byte)((Integer)layerHandle.get(4)).intValue();
737
                        layerBytes[1] = (byte)((Integer)layerHandle.get(3)).intValue();
738
                        layerBytes[0] = (byte)((Integer)layerHandle.get(2)).intValue();
739
                }
740
                int layer = ByteUtils.bytesToInt(layerBytes, new int[]{0});
741
                return layer;
742
        }
743
        /*
744
         * TODO Ver si esto es necesario
745
         * */
746
        public static int[] toIntArray(byte[] bytes){
747
                String[] dataMachValString = new String[bytes.length];
748
                int[] data = new int[bytes.length];
749
                for (int i=0; i < bytes.length; i++) {
750
                        dataMachValString[i] = HexUtil.bytesToHex(new byte[]{bytes[i]});
751
                        Integer dataMachValShort = Integer.decode("0x" + dataMachValString[i]);
752
                        data[i] = dataMachValShort.byteValue();
753
                        data[i] = ByteUtils.getUnsigned((byte)data[i]);
754
                }//for
755
                return data;
756
                
757
        }
758
}