Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libDwg / src / org / gvsig / dwg / lib / DwgUtil.java @ 28969

History | View | Annotate | Download (29.1 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 org.gvsig.dwg.lib;
36

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

    
42
import org.gvsig.dwg.lib.util.HexUtil;
43

    
44

    
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
        /**
185
         * Read a double value from a group of unsigned bytes and a default double
186
         *
187
         * @param data Array of unsigned bytes obtained from the DWG binary file
188
         * @param offset The current bit offset where the value begins
189
         * @param defVal Default double value
190
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
191
         *             when we are looking for LwPolylines.
192
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
193
         *                    the new offset, and second is the double value
194
         */
195
        public static ArrayList getDefaultDouble(int[] data, int offset, double defVal) throws RuntimeException {
196
                int flags = ((Integer) getBits(data, 2, offset)).intValue();
197
                int read = 2;
198
                double val;
199
                if (flags == 0x0) {
200
                        val = defVal;
201
                } else {
202
                        int _offset = offset + 2;
203
                        if (flags == 0x3) {
204
                                byte[] bytes = (byte[]) getBits(data, 64, _offset);
205
                                ByteBuffer bb = ByteBuffer.wrap(bytes);
206
                                bb.order(ByteOrder.LITTLE_ENDIAN);
207
                                val = bb.getDouble();
208
                                read = 66;
209
                        } else {
210
                                byte[] dstrArrayAux = new byte[8];
211
                                int[] doubleOffset = new int[] { 0 };
212
                                ByteUtils.doubleToBytes(defVal, dstrArrayAux, doubleOffset);
213
                                byte[] dstrArrayAuxx = new byte[8];
214
                                dstrArrayAuxx[0] = dstrArrayAux[7];
215
                                dstrArrayAuxx[1] = dstrArrayAux[6];
216
                                dstrArrayAuxx[2] = dstrArrayAux[5];
217
                                dstrArrayAuxx[3] = dstrArrayAux[4];
218
                                dstrArrayAuxx[4] = dstrArrayAux[3];
219
                                dstrArrayAuxx[5] = dstrArrayAux[2];
220
                                dstrArrayAuxx[6] = dstrArrayAux[1];
221
                                dstrArrayAuxx[7] = dstrArrayAux[0];
222
                                int[] dstrArrayAuxxx = new int[8];
223
                                for (int i = 0; i < dstrArrayAuxxx.length; i++) {
224
                                        dstrArrayAuxxx[i] = ByteUtils.getUnsigned(dstrArrayAuxx[i]);
225
                                }
226
                                byte[] dstrArray = new byte[8];
227
                                for (int i = 0; i < dstrArray.length; i++) {
228
                                        dstrArray[i] = (byte) dstrArrayAuxxx[i];
229
                                }
230
                                if (flags == 0x1) {
231
                                        byte[] ddArray = (byte[]) getBits(data, 32, _offset);
232
                                        dstrArray[0] = ddArray[0];
233
                                        dstrArray[1] = ddArray[1];
234
                                        dstrArray[2] = ddArray[2];
235
                                        dstrArray[3] = ddArray[3];
236
                                        read = 34;
237
                                } else {
238
                                        byte[] ddArray = (byte[]) getBits(data, 48, _offset);
239
                                        dstrArray[4] = ddArray[0];
240
                                        dstrArray[5] = ddArray[1];
241
                                        dstrArray[0] = ddArray[2];
242
                                        dstrArray[1] = ddArray[3];
243
                                        dstrArray[2] = ddArray[4];
244
                                        dstrArray[3] = ddArray[5];
245
                                        read = 50;
246
                                }
247
                                ByteBuffer bb = ByteBuffer.wrap(dstrArray);
248
                                bb.order(ByteOrder.LITTLE_ENDIAN);
249
                                val = bb.getDouble();
250
                        }
251
                }
252
                ArrayList v = new ArrayList();
253
                v.add(new Integer(offset + read));
254
                v.add(new Double(val));
255
                return v;
256
        }
257

    
258

    
259
        /**
260
         * Read a double value from a group of unsigned bytes
261
         *
262
         * @param data Array of unsigned bytes obtained from the DWG binary file
263
         * @param offset The current bit offset where the value begins
264
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
265
         *             when we are looking for LwPolylines.
266
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
267
         *                    the new offset, and second is the double value
268
         */
269
        public static ArrayList getBitDouble(int[] data, int offset) throws RuntimeException {
270
                ArrayList v = new ArrayList();
271
                int type = ((Integer) getBits(data, 2, offset)).intValue();
272
                int read = 2;
273
                double val = 0.0;
274
                if (type == 0x00) {
275
                        byte[] bytes = (byte[]) getBits(data, 64, (offset + 2));
276
                        ByteBuffer bb = ByteBuffer.wrap(bytes);
277
                        bb.order(ByteOrder.LITTLE_ENDIAN);
278
                        val = bb.getDouble();
279
                        read = 66;
280
                } else if (type == 0x01) {
281
                        val = 1.0;
282
                } else if (type == 0x02) {
283
                        val = 0.0;
284
                } else {
285
                        System.out.println("Bad type " + type + " at bit offset: " + offset);
286
                }
287
                v.add(new Integer(offset + read));
288
                v.add(new Double(val));
289
                return v;
290
        }
291

    
292

    
293
        /**
294
         * Read a double value from a group of unsigned bytes
295
         *
296
         * @param data Array of unsigned bytes obtained from the DWG binary file
297
         * @param offset The current bit offset where the value begins
298
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
299
         *             when we are looking for LwPolylines.
300
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
301
         *                    the new offset, and second is the double value
302
         */
303
        public static ArrayList getRawDouble(int[] data, int offset) throws RuntimeException {
304
                byte[] bytes = (byte[]) getBits(data, 64, offset);
305
                ByteBuffer bb = ByteBuffer.wrap(bytes);
306
                bb.order(ByteOrder.LITTLE_ENDIAN);
307
                double val = bb.getDouble();
308
                ArrayList v = new ArrayList();
309
                v.add(new Integer(offset + 64));
310
                v.add(new Double(val));
311
                return v;
312
        }
313

    
314
        /**
315
         * Read a short value from a group of unsigned bytes
316
         *
317
         * @param data Array of unsigned bytes obtained from the DWG binary file
318
         * @param offset The current bit offset where the value begins
319
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
320
         *             when we are looking for LwPolylines.
321
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
322
         *                    the new offset, and second is the short value
323
         */
324
        public static ArrayList getBitShort(int[] data, int offset) throws RuntimeException {
325
                ArrayList v = new ArrayList();
326
                int type = ((Integer) getBits(data, 2, offset)).intValue();
327
                int read = 2;
328
                int val = 0;
329
                if (type == 0x00) {
330
                        byte[] bytes = (byte[]) getBits(data, 16, (offset + 2));
331
                        ByteBuffer bb = ByteBuffer.wrap(bytes);
332
                        bb.order(ByteOrder.LITTLE_ENDIAN);
333
                        val = bb.getShort();
334
                        read = 18;
335
                } else if (type == 0x01) {
336
                        val = ((Integer) getBits(data, 8, (offset + 2))).intValue();
337
                        read = 10;
338
                } else if (type == 0x02) {
339
                        val = 0;
340
                } else if (type == 0x03) {
341
                        val = 256;
342
                }
343
                v.add(new Integer(offset + read));
344
                v.add(new Integer(val));
345
                return v;
346
        }
347

    
348
        /**
349
         * Read a short value from a group of unsigned bytes
350
         *
351
         * @param data Array of unsigned bytes obtained from the DWG binary file
352
         * @param offset The current bit offset where the value begins
353
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
354
         *             when we are looking for LwPolylines.
355
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
356
         *                    the new offset, and second is the short value
357
         */
358
        public static ArrayList getRawShort(int[] data, int offset) throws RuntimeException {
359
                byte[] bytes = (byte[]) getBits(data, 16, offset);
360
                ByteBuffer bb = ByteBuffer.wrap(bytes);
361
                bb.order(ByteOrder.LITTLE_ENDIAN);
362
                int val = bb.getShort();
363
                ArrayList v = new ArrayList();
364
                v.add(new Integer(offset + 16));
365
                v.add(new Integer(val));
366
                return v;
367
        }
368

    
369
        /**
370
         * Read a long value from a group of unsigned bytes
371
         *
372
         * @param data Array of unsigned bytes obtained from the DWG binary file
373
         * @param offset The current bit offset where the value begins
374
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
375
         *             when we are looking for LwPolylines.
376
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
377
         *                    the new offset, and second is the long value
378
         */
379
        public static ArrayList getBitLong(int[] data, int offset) throws RuntimeException {
380
                int type = ((Integer) getBits(data, 2, offset)).intValue();
381
                int read = 2;
382
                int val = 0;
383
                if (type == 0x0) {
384
                        byte[] bytes = (byte[]) getBits(data, 32, (offset + 2));
385
                        ByteBuffer bb = ByteBuffer.wrap(bytes);
386
                        bb.order(ByteOrder.LITTLE_ENDIAN);
387
                        val = bb.getInt();
388
                        read = 34;
389
                } else if (type == 0x01) {
390
                        val = ((Integer) getBits(data, 8, (offset + 2))).intValue();
391
                        read = 10;
392
                } else if (type == 0x02) {
393
                        val = 0;
394
                } else {
395
                        System.out.println("Bad type at bit offset: " + offset);
396
                }
397
                ArrayList v = new ArrayList();
398
                v.add(new Integer(offset + read));
399
                v.add(new Integer(val));
400
                return v;
401
        }
402

    
403
        /**
404
         * Read a long value from a group of unsigned bytes
405
         *
406
         * @param data Array of unsigned bytes obtained from the DWG binary file
407
         * @param offset The current bit offset where the value begins
408
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
409
         *             when we are looking for LwPolylines.
410
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
411
         *                    the new offset, and second is the long value
412
         * @throws RuntimeException
413
         */
414
        public static ArrayList getRawLong(int[] data, int offset) throws RuntimeException {
415
                ArrayList v = new ArrayList();
416
                // _val = struct.unpack('<l', _long)[0]
417
                byte[] bytes = (byte[]) getBits(data, 32, offset);
418
                ByteBuffer bb = ByteBuffer.wrap(bytes);
419
                bb.order(ByteOrder.LITTLE_ENDIAN);
420
                int val = bb.getInt();
421
                v.add(new Integer(offset + 32));
422
                v.add(new Integer(val));
423
                return v;
424
        }
425

    
426
        /**
427
         * Read a char value from a group of unsigned bytes
428
         *
429
         * @param data Array of unsigned bytes obtained from the DWG binary file
430
         * @param offset The current bit offset where the value begins
431
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
432
         *             when we are looking for LwPolylines.
433
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
434
         *                    the new offset, and second is the char value
435
         */
436
        public static ArrayList getRawChar(int[] data, int offset) throws RuntimeException {
437
                int charr = ((Integer) getBits(data, 8, offset)).intValue();
438
                ArrayList v = new ArrayList();
439
                v.add(new Integer(offset + 8));
440
                v.add(new Integer(charr));
441
                return v;
442
        }
443

    
444
        /**
445
         * Read a char value from a group of unsigned bytes
446
         *
447
         * @param data Array of unsigned bytes obtained from the DWG binary file
448
         * @param offset The current bit offset where the value begins
449
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
450
         *             when we are looking for LwPolylines.
451
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
452
         *                    the new offset, and second is the char value
453
         */
454
        public static ArrayList getModularChar(int[] data, int offset) throws RuntimeException {
455
                int val = 0;
456
                ArrayList bytes = new ArrayList();
457
                boolean read = true;
458
                int offsett = offset;
459
                int fac = 1;
460
                while (read) {
461
                        int bytee = ((Integer) getBits(data, 8, offsett)).intValue();
462
                        offsett = offsett + 8;
463
                        if ((bytee & 0x80) == 0) {
464
                                read = false;
465
                                if ((bytee & 0x40) > 0) {
466
                                        fac = -1;
467
                                        bytee = bytee & 0xbf;
468
                                }
469
                        }
470
                        bytes.add(new Integer(bytee & 0x7f));
471
                }
472
                if (bytes.size()==1) val = ((Integer)bytes.get(0)).intValue();
473
                else if (bytes.size()==2) val = ((Integer)bytes.get(0)).intValue() | (((Integer)bytes.get(1)).intValue() << 7);
474
                else if (bytes.size()==3) val = ((Integer)bytes.get(0)).intValue() | (((Integer)bytes.get(1)).intValue() << 7) | (((Integer)bytes.get(2)).intValue() << 14);
475
                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);
476
                else System.out.println("Unexpected byte array length: " + bytes.size());
477
                ArrayList v = new ArrayList();
478
                v.add(new Integer(offsett));
479
                v.add(new Integer(fac * val));
480
                return v;
481
        }
482

    
483
        /**
484
         * Read a String from a group of unsigned bytes
485
         *
486
         * @param data Array of unsigned bytes obtained from the DWG binary file
487
         * @param offset The current bit offset where the value begins
488
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
489
         *             when we are looking for LwPolylines.
490
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
491
         *                    the new offset, and second is the String
492
         */
493
        public static ArrayList getTextString(int[] data, int offset) throws RuntimeException {
494
                int bitPos = offset;
495
                ArrayList bitShort = DwgUtil.getBitShort(data, bitPos);
496
                int newBitPos = ((Integer) bitShort.get(0)).intValue();
497
                int len = ((Integer) bitShort.get(1)).intValue();
498
                bitPos = newBitPos;
499
                int bitLen = len * 8;
500
                Object cosa = DwgUtil.getBits(data, bitLen, bitPos);
501
                String string;
502
                if (cosa instanceof byte[]) {
503
                        string = new String((byte[]) cosa);
504
                } else {
505
                        // string = ((Integer)cosa).toString();
506
                        byte[] bytes = new byte[] { ((Integer) cosa).byteValue() };
507
                        string = new String((byte[]) bytes);
508
                }
509
                bitPos = bitPos + bitLen;
510
                ArrayList v = new ArrayList();
511
                v.add(new Integer(bitPos));
512
                v.add(string);
513
                return v;
514
        }
515

    
516
        /**
517
         * Read a CmColor from a group of unsigned bytes
518
         *
519
         * @param data
520
         *            Array of unsigned bytes obtained from the DWG binary file
521
         * @param offset
522
         *            The current bit offset where the value begins
523
         * @throws RuntimeException
524
         *             If an unexpected bit value is found in the DWG file. Occurs
525
         *             when we are looking for LwPolylines.
526
         * @return ArrayList This ArrayList has two parts. First is an int value
527
         *         that represents the new offset, and second is the int value
528
         *         (handle of a DWG object)
529
         */
530
        public static ArrayList getCmColor(int[] intData, int offset, String version) throws RuntimeException {
531

    
532
                ArrayList v = new ArrayList();
533
                int bitPos = offset;
534
                List val = getBitShort(intData, bitPos);
535
                bitPos = ((Integer) val.get(0)).intValue();
536
                v.add((Integer) val.get(1));                //color index
537

    
538
                //FIXME: para versiones superiores habrá que ampliar la condición
539
                if (version.equalsIgnoreCase("Autocad R2004, R2005, R2006")){
540

    
541
                        val = getBitLong(intData, bitPos);
542
                        bitPos = ((Integer) val.get(0)).intValue();
543
                        v.add((Integer) val.get(1));        //RGB value
544

    
545
                        val = getRawChar(intData, bitPos);
546
                        bitPos = ((Integer) val.get(0)).intValue();
547
                        Integer colorByte = ((Integer) val.get(1)); //.intValue();
548
                        v.add(colorByte);                                //Color Byte
549

    
550
                        // Según la documentacion:
551
                        // Color Byte & 1 ==> color name follows
552
                        // Color Byte & 2 ==> book name follows
553
                        if (((colorByte.intValue() & 0x01) != 0) || ((colorByte.intValue() & 0x02) != 0)) {
554
                                val = getTextString(intData, bitPos);
555
                                bitPos = ((Integer) val.get(0)).intValue();
556
                                v.add(val.get(1));//color name or book name
557
                        } else {
558
                                v.add("");//color name or book name
559
                        }
560
                }
561

    
562
                v.add(0, new Integer(bitPos));
563
                return v;
564
        }
565

    
566
        /**
567
         * Read a int value (the handle of a DWG object) from a group of unsigned
568
         * bytes
569
         *
570
         * @param data
571
         *            Array of unsigned bytes obtained from the DWG binary file
572
         * @param offset
573
         *            The current bit offset where the value begins
574
         * @throws RuntimeException
575
         *             If an unexpected bit value is found in the DWG file. Occurs
576
         *             when we are looking for LwPolylines.
577
         * @return ArrayList This ArrayList has two parts. First is an int value
578
         *         that represents the new offset, and second is the int value
579
         *         (handle of a DWG object)
580
         */
581
        public static ArrayList getHandle(int[] data, int offset)
582
                        throws RuntimeException {
583
                ArrayList v = new ArrayList();
584
                int code = ((Integer) DwgUtil.getBits(data, 4, offset)).intValue();
585
            int counter = ((Integer)DwgUtil.getBits(data, 4, (offset + 4))).intValue();
586
                int read = 8;
587
                ArrayList hlist = new ArrayList();
588
                if (counter > 0) {
589
                        int hlen = counter * 8;
590
                        Object handle = DwgUtil.getBits(data, hlen, (offset + 8));
591
                        read = read + hlen;
592
                        if (hlen > 8) {
593
                                byte[] handleBytes = (byte[]) handle;
594
                                int[] handleInts = new int[handleBytes.length];
595
                                // Hacerlos unsigned ...
596
                                for (int i = 0; i < handleBytes.length; i++) {
597
                                        handleInts[i] = ByteUtils.getUnsigned(handleBytes[i]);
598
                                }
599
                                for (int i = 0; i < handleInts.length; i++) {
600
                                        hlist.add(new Integer(handleInts[i]));
601
                                }
602
                        } else {
603
                                hlist.add(handle);
604
                        }
605
                }
606
                v.add(new Integer(offset + read));
607
                v.add(new Integer(code));
608
                v.add(new Integer(counter));
609
                for (int i = 0; i < hlist.size(); i++) {
610
                        v.add(hlist.get(i));
611
                }
612
                return v;
613
        }
614

    
615
        /**
616
         * Read a int value (the size of a modular short) from a ByteBuffer
617
         *
618
         * @param bb Data given as a ByteBuffer
619
         * @return int Size of the modular short
620
         */
621
        public static int getModularShort(ByteBuffer bb) {
622
                ArrayList shorts = new ArrayList();
623
                bb.order(ByteOrder.BIG_ENDIAN);
624
                short shortt = bb.getShort();
625
                int size = 0;
626
                while ((shortt & 0x80) > 0) {
627
                        shorts.add(new Short(shortt));
628
                        shortt = bb.getShort();
629
                }
630
                shorts.add(new Short(shortt));
631
                for (int i = 0; i < shorts.size(); i++) {
632
                        shortt = ((Short) shorts.get(i)).shortValue();
633
                        shorts.set(i, new Integer(((shortt & 0xff00) >> 8) | ((shortt & 0xff) << 8)));
634
                }
635
                int slen = shorts.size();
636
                if (slen == 1) {
637
                        size = (((Integer)shorts.get(0)).intValue()) & 0x7fff;//(new Integer(((Integer)shorts.get(0)).shortValue() & 0x7fff)).byteValue();
638
                } else if (slen == 2) {
639
                        int tmp = ((Integer) shorts.get(0)).intValue();
640
                        shorts.set(0, shorts.get(1));
641
                        shorts.set(1, new Integer(tmp));
642
                        size = (((((Integer)shorts.get(0)).intValue()) & 0x7fff) << 15) | (((((Integer)shorts.get(1)).intValue()) & 0x7fff));//(new Integer(((Integer)shorts.get(0)).shortValue() & 0x7fff)).byteValue();
643
                } else {
644
                        System.out.println("Unexpected array length: " + slen);
645
                }
646
                return size;
647
        }
648

    
649
        /**
650
         * Returns a set of bits from a group of unsigned bytes
651
         *
652
         * @param data Array of unsigned bytes obtained from the DWG binary file
653
         * @param count Bit counter
654
         * @param offset The current bit offset where the value begins
655
         * @throws RuntimeException If an unexpected bit value is found in the DWG file. Occurs
656
         *             when we are looking for LwPolylines.
657
         * @return This method returns an array of bytes or an int value
658
         */
659
        public static Object getBits(int[] data, int count, int offset) throws RuntimeException {
660
                int idx = offset / 8;
661
                int bitidx = offset % 8;
662
                /**
663
                 * mask1: bit mask to apply to the current byte
664
                 * lshift: left shift amount of mask results
665
                 * mask2: bit mask to apply to the next byte
666
                 * rshift: right shift amount of the mask results
667
                 */
668
                int[][] maskTable = new int[][]{
669
                    {0xff, 0, 0x00, 0}, // bit offset == 0
670
                                { 0x7f, 1, 0x80, 7 }, // bit offset == 1
671
                                { 0x3f, 2, 0xc0, 6 }, // bit offset == 2
672
                                { 0x1f, 3, 0xe0, 5 }, // bit offset == 3
673
                                { 0x0f, 4, 0xf0, 4 }, // bit offset == 4
674
                                { 0x07, 5, 0xf8, 3 }, // bit offset == 5
675
                                { 0x03, 6, 0xfc, 2 }, // bit offset == 6
676
                                { 0x01, 7, 0xfe, 1 }, // bit offset == 7
677
                };
678
                int mask1 = maskTable[bitidx][0];
679
                int lsh = maskTable[bitidx][1];
680
                int mask2 = maskTable[bitidx][2];
681
                int rsh = maskTable[bitidx][3];
682
                int binc = 8 - bitidx;
683
                int read = 0;
684
                int rem = count;
685
                int bytee = 0x0;
686
                ArrayList bytes = new ArrayList();
687
                while (read < count) {
688
                        int b1 = 0;
689
                        if (rem > binc) {
690
                                b1 = (data[idx] & mask1);
691
                                read = read + binc;
692
                                rem = rem - binc;
693
                        } else {
694
                                b1 = ((data[idx] & mask1) >> (8 - bitidx - rem));
695
                                bytee = b1;
696
                                read = read + rem;
697
                                rem = 0;
698
                        }
699
                        if (read < count) {
700
                                idx = idx + 1;
701
                                if (rem > bitidx) {
702
                                        int b2 = (data[idx] & mask2);
703
                                        bytee = (b1 << lsh) | (b2 >> rsh);
704
                                        read = read + bitidx;
705
                                        rem = rem - bitidx;
706
                                } else {
707
                                        int mask = maskTable[rem][2];
708
                                        int b2 = data[idx] & mask;
709
                                        bytee = (b1 << rem) | (b2 >> (8 - rem));
710
                                        read = read + rem;
711
                                        rem = 0;
712
                                }
713
                        }
714
                        if (count > 8) {
715
                                bytes.add(new Integer(bytee));
716
                        }
717
                }
718
                if (bytes.size() > 0) {
719
                        byte[] newBytes = new byte[bytes.size()];
720
                        for (int i = 0; i < newBytes.length; i++) {
721
                                newBytes[i] = ((Integer) bytes.get(i)).byteValue();
722
                        }
723
                        return newBytes;
724
                }
725
                return new Integer(bytee);
726
        }
727

    
728
        /**
729
         * Test a bit obtained from a set of unsigned bytes
730
         *
731
         * @param data Array of unsigned bytes obtained from the DWG binary file
732
         * @param offset The current bit offset where the value begins
733
         * @return ArrayList This ArrayList has two parts. First is an int value that represents
734
         *                    the new offset, and second is a bit flag
735
         */
736
        public static ArrayList testBit(int[] data, int offset) {
737
                int idx = offset / 8;
738
                int bitidx = offset % 8;
739
                int mask = 0x1 << (7 - bitidx);
740
                boolean val = false;
741
                if ((data[idx] & mask) > 0) val = true;
742
                ArrayList v = new ArrayList();
743
                v.add(new Integer(offset + 1));
744
                v.add(new Boolean(val));
745
                return v;
746
        }
747

    
748
        /**
749
         * Convert bytes to machine value bytes
750
         *
751
         * @param data Input of array of bytes
752
         * @return int[] Output of array of machine bytes
753
         */
754
        public static int[] bytesToMachineBytes(byte[] data) {
755
                String[] dataString = new String[data.length];
756
                int[] dataOut = new int[data.length];
757
                for (int i = 0; i < data.length; i++) {
758
                        dataString[i] = HexUtil.bytesToHex(new byte[] { data[i] });
759
                        Integer dataInt = Integer.decode("0x" + dataString[i]);
760
                        dataOut[i] = dataInt.intValue();
761
                }
762
                return dataOut;
763
        }
764

    
765
        /**
766
         * It receives the list procedent from getHandle method, and return the
767
         * handle as int
768
         *
769
     * */
770
        public static int handleToInt(List fromGetHandle) {
771

    
772
                int[] handle = new int[fromGetHandle.size() - 1];
773
                for (int j = 1; j < fromGetHandle.size(); j++) {
774
                        handle[j - 1] = ((Integer) fromGetHandle.get(j)).intValue();
775
                }
776
                ArrayList handleVect = new ArrayList();
777
                for (int i = 0; i < handle.length; i++) {
778
                        handleVect.add(new Integer(handle[i]));
779
                }
780
                return DwgUtil.handleBinToHandleInt(handleVect);
781

    
782

    
783
    }
784
        /**
785
         * Obtain the int value of a handle given in binary format
786
         *
787
         * @param layerHandle Handle in binary format
788
         * @return int Int value of the handle
789
         */
790
        public static int handleBinToHandleInt(ArrayList layerHandle) {
791
                byte[] layerBytes = new byte[] { 0, 0, 0, 0 };
792
                if (layerHandle.size()>2) layerBytes[3] = (byte)((Integer)layerHandle.get(2)).intValue();
793
                if (layerHandle.size() > 3) {
794
                        layerBytes[3] = (byte) ((Integer) layerHandle.get(3)).intValue();
795
                        layerBytes[2] = (byte) ((Integer) layerHandle.get(2)).intValue();
796
                }
797
                if (layerHandle.size() > 4) {
798
                        layerBytes[3] = (byte) ((Integer) layerHandle.get(4)).intValue();
799
                        layerBytes[2] = (byte) ((Integer) layerHandle.get(3)).intValue();
800
                        layerBytes[1] = (byte) ((Integer) layerHandle.get(2)).intValue();
801
                }
802
                if (layerHandle.size() > 5) {
803
                        layerBytes[3] = (byte) ((Integer) layerHandle.get(5)).intValue();
804
                        layerBytes[2] = (byte) ((Integer) layerHandle.get(4)).intValue();
805
                        layerBytes[1] = (byte) ((Integer) layerHandle.get(3)).intValue();
806
                        layerBytes[0] = (byte) ((Integer) layerHandle.get(2)).intValue();
807
                }
808
                int layer = ByteUtils.bytesToInt(layerBytes, new int[] { 0 });
809
                return layer;
810
        }
811

    
812
        /*
813
         * TODO Ver si esto es necesario
814
         * */
815
        public static int[] toIntArray(byte[] bytes) {
816
                String[] dataMachValString = new String[bytes.length];
817
                int[] data = new int[bytes.length];
818
                for (int i = 0; i < bytes.length; i++) {
819
                        dataMachValString[i] = HexUtil.bytesToHex(new byte[] { bytes[i] });
820
                        Integer dataMachValShort = Integer.decode("0x" + dataMachValString[i]);
821
                        data[i] = dataMachValShort.byteValue();
822
                        data[i] = ByteUtils.getUnsigned((byte) data[i]);
823
                }// for
824
                return data;
825

    
826
        }
827
}