Revision 321

View differences:

tags/org.gvsig.dwg-2.0.75/org.gvsig.dwg.lib/src/main/java/org/gvsig/dwg/lib/DwgObjectOffset.java
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
/**
38
 * The DwgObjectOffset class is useful to store the handle of an object with its
39
 * offset in the DWG file
40
 * 
41
 * @author jmorell
42
 */
43
public class DwgObjectOffset {
44
	private int handle;
45
	private int offset;
46
	private int size;
47
	
48
	/**
49
	 * Create a new DwgObjectOffset object
50
	 * 
51
	 * @param handle Handle of the object
52
	 * @param offset Offset in the DWG file of the object
53
	 */
54
	public DwgObjectOffset(int handle, int offset) {
55
		this.handle = handle;
56
		this.offset = offset;
57
	}
58
	
59
    /**
60
     * @return Returns the handle.
61
     */
62
    public int getHandle() {
63
        return handle;
64
    }
65
    /**
66
     * @return Returns the offset.
67
     */
68
    public int getOffset() {
69
        return offset;
70
    }
71
    
72
    public void setSize(int size){
73
    	this.size=size;
74
    }
75
    
76
    public int getSize(){
77
    	return this.size;
78
    }
79
    
80
    
81
}
tags/org.gvsig.dwg-2.0.75/org.gvsig.dwg.lib/src/main/java/org/gvsig/dwg/lib/DwgUtil.java
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
}
tags/org.gvsig.dwg-2.0.75/org.gvsig.dwg.lib/src/main/java/org/gvsig/dwg/lib/IDwg2FMap.java
1
/*
2
 * Created on 09-ene-2007
3
 *
4
 * gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. 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
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib��ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 *
34
 *    or
35
 *
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 *
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44

  
45
/* CVS MESSAGES:
46
*
47
* $Id: IDwg2FMap.java 29001 2009-05-26 15:32:46Z jmvivo $
48
* $Log$
49
* Revision 1.2.2.2  2007-03-21 19:49:16  azabala
50
* implementation of dwg 12, 13, 14.
51
*
52
* Revision 1.3  2007/03/20 19:55:27  azabala
53
* source code cleaning
54
*
55
* Revision 1.2  2007/01/18 13:35:22  azabala
56
* Refactoring general para evitar dar tantas pasadas en la carga, y para incrementar
57
* la legibilidad del codigo (demasiados if-else-if en vez de usar polimorfismo)
58
*
59
* Revision 1.1  2007/01/12 19:29:58  azabala
60
* first version in cvs
61
*
62
*
63
*/
64
package org.gvsig.dwg.lib;
65

  
66
import org.gvsig.fmap.geom.Geometry;
67
import org.gvsig.fmap.geom.exception.CreateGeometryException;
68

  
69
/**
70
 * All dwg objects that are drawing entities
71
 * and that can be converted to a fmap geometry
72
 * implements this interface.
73
 *
74
 * */
75
/*
76
 * TODO
77
 * Esta solucion tiene el problema de que es mas simple
78
 * (cada entidad dwg se ocupa de su conversion a fmap),pero acopla
79
 * libDwg con fmap
80
 * (una clase Dwg2FMap lo desacoplar�a, pero llenar�a el codigo de
81
 * infinitos if(dwg instanceof ...) else if.....
82
 *
83
 * */
84
public interface IDwg2FMap {
85
	public Geometry toFMapGeometry(boolean is3DFile) throws CreateGeometryException;
86
	public String toFMapString(boolean is3DFile);
87
	public int getGeometryType();
88
	public int getGeometrySubType(boolean is3DFile);
89
	public String toString();
90
}
91

  
tags/org.gvsig.dwg-2.0.75/org.gvsig.dwg.lib/src/main/java/org/gvsig/dwg/lib/DwgFile.java
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.awt.geom.Point2D;
38
import java.io.File;
39
import java.io.FileInputStream;
40
import java.io.IOException;
41
import java.nio.ByteBuffer;
42
import java.nio.channels.FileChannel;
43
import java.util.ArrayList;
44
import java.util.HashMap;
45
import java.util.Iterator;
46
import java.util.List;
47
import java.util.Map;
48

  
49
import org.gvsig.dwg.lib.objects.DwgBlockHeader;
50
import org.gvsig.dwg.lib.objects.DwgInsert;
51
import org.gvsig.dwg.lib.objects.DwgLayer;
52
import org.gvsig.dwg.lib.readers.DwgFileV12Reader;
53
import org.gvsig.dwg.lib.readers.DwgFileV14Reader;
54
import org.gvsig.dwg.lib.readers.DwgFileV15Reader;
55
import org.gvsig.dwg.lib.readers.DwgFileVR2004Reader;
56
import org.gvsig.dwg.lib.readers.IDwgFileReader;
57
import org.slf4j.Logger;
58
import org.slf4j.LoggerFactory;
59

  
60

  
61
/**
62
 * The DwgFile class provides a revision-neutral interface for reading and handling
63
 * DWG files
64
 * Reading methods are useful for reading DWG files, and handling methods like
65
 * calculateDwgPolylines() are useful for handling more complex
66
 * objects in the DWG file
67
 *
68
 * @author jmorell
69
 * @author azabala
70
 */
71
public class DwgFile {
72
	/**
73
	 * It has all known DWG version's header.
74
	 * Extracted from Autodesk web.
75
	 */
76
	private static HashMap acadVersions = new HashMap();
77
	static{
78
		acadVersions.put("AC1004", "Autocad R9");
79
		acadVersions.put("AC1006", "Autocad R10");
80
		acadVersions.put("AC1007", "Autocad pre-R11");
81
		acadVersions.put("AC1007", "Autocad pre-R11");
82
		acadVersions.put("AC1008", "Autocad pre-R11b");
83
		acadVersions.put("AC1009", "Autocad R12");
84
		acadVersions.put("AC1010", "Autocad pre-R13 a");
85
		acadVersions.put("AC1011", "Autocad pre-R13 b");
86
		acadVersions.put("AC1012", "Autocad R13");
87
		acadVersions.put("AC1013", "Autocad pre-R14");
88
		acadVersions.put("AC1014", "Autocad R14");
89
		acadVersions.put("AC1500", "Autocad pre-2000");
90
		acadVersions.put("AC1015", "Autocad R2000, R2000i, R2002");
91
		acadVersions.put("AC402a", "Autocad pre-2004a");
92
		acadVersions.put("AC402b", "Autocad pre-2004b");
93
		acadVersions.put("AC1018", "Autocad R2004, R2005, R2006");
94
		acadVersions.put("AC1021", "Autocad R2007");
95

  
96
	}
97

  
98
	private static Logger logger = LoggerFactory.getLogger(DwgFile.class.getName());
99
	/**
100
	 * Path and name of the dwg file
101
	 * */
102
	private String fileName;
103
	/**
104
	 * DWG version of the file (AC1013, AC1018, etc.)
105
	 * */
106
	private String dwgVersion;
107

  
108
	/**
109
	 * Offsets to the DWG sections
110
	 */
111
	private ArrayList dwgSectionOffsets;
112
	/**
113
	 * Header vars readed from the HEADER section of the DWG file
114
	 * */
115
	private Map headerVars;
116

  
117
	/**
118
	 * This list contains what in OpenDWG specification is called
119
	 * the object map ( a collection of entries where each entry contains
120
	 * the seek of each object, and its size)
121
	 * */
122
	private ArrayList dwgObjectOffsets;
123

  
124
	/**
125
	 * For each entry in dwgObjectOffsets, we have an instance of
126
	 * DwgObject in the dwgObjects collection
127
	 *
128
	 * */
129
	private List dwgObjects;
130
	private HashMap handle_objects;
131

  
132

  
133
	private ArrayList dwgClasses;
134

  
135

  
136
	/**
137
	 * hash map that indexes all DwgLayer objects
138
	 * by its handle property
139
	 * */
140
	private HashMap layerTable;
141

  
142
	/**
143
	 * Specific reader of the DWG file version (12, 13, 14, 2000, etc., each
144
	 * version will have an specific reader)
145
	 * */
146
	private IDwgFileReader dwgReader;
147
	private boolean dwg3DFile = false;
148
	/**
149
	 * Memory mapped byte buffer of the whole DWG file
150
	 * */
151
	private ByteBuffer bb;
152

  
153
	/*
154
	 * Optimizaciones para evitar leer el fichero completo en cada
155
	 * pasada.
156
	 * */
157
	/**
158
	 * Contains all IDwgPolyline implementations
159
	 * */
160
	private List dwgPolylines;
161
	/**
162
	 * Contains all INSERT entities of the dwg file
163
	 * (these entities must be processed in a second pass)
164
	 *
165
	 * */
166
	private List insertList;
167

  
168
	private List blockList;
169

  
170

  
171
	/**
172
	 * Constructor.
173
	 * @param fileName an absolute path to the DWG file
174
	 */
175
	public DwgFile(String fileName) {
176
		this.fileName = fileName;
177

  
178
		dwgSectionOffsets = new ArrayList();
179
		dwgObjectOffsets = new ArrayList();
180
		headerVars = new HashMap();
181

  
182
		dwgClasses = new ArrayList();
183

  
184
		dwgObjects = new ArrayList();
185
		handle_objects = new HashMap();
186

  
187
		layerTable = new HashMap();
188

  
189
		dwgPolylines = new ArrayList();
190
		insertList = new ArrayList();
191

  
192
		blockList = new ArrayList();
193

  
194
	}
195

  
196
	public String getDwgVersion() {
197
		return dwgVersion;
198
	}
199

  
200
	/**
201
	 * Reads a DWG file and put its objects in the dwgObjects Vector
202
	 * This method is version independent
203
	 *
204
	 * @throws IOException If the file location is wrong
205
	 */
206
	public void read() throws IOException,
207
				DwgVersionNotSupportedException
208
	{
209
		setDwgVersion();
210
		if (dwgVersion.equalsIgnoreCase("Autocad R2000, R2000i, R2002")) {
211
			dwgReader = new DwgFileV15Reader();
212
		}else if (dwgVersion.equalsIgnoreCase("Autocad pre-R14")||
213
				dwgVersion.equalsIgnoreCase("Autocad R14") ||
214
				dwgVersion.equalsIgnoreCase("Autocad R13")) {
215
			dwgReader = new DwgFileV14Reader();
216
		}else if (dwgVersion.equalsIgnoreCase("Autocad R2004, R2005, R2006")){
217
			dwgReader = new DwgFileVR2004Reader();
218
		} else if (dwgVersion.equalsIgnoreCase("Autocad R12")||
219
				dwgVersion.equalsIgnoreCase("Autocad pre-R13 a") ||
220
				dwgVersion.equalsIgnoreCase("Autocad pre-R13 b")) {
221

  
222
			boolean isR13 = true;
223
			if(dwgVersion.equalsIgnoreCase("Autocad R12"))
224
					isR13 = false;
225
			dwgReader = new DwgFileV12Reader(isR13);
226
		}else {
227
			DwgVersionNotSupportedException exception =
228
				new DwgVersionNotSupportedException("Version de DWG no soportada");
229
			exception.setDwgVersion(dwgVersion);
230
			throw exception;
231
		}
232
		try{
233
		dwgReader.read(this, bb);
234
		}catch(Throwable t){
235
			t.printStackTrace();
236
			throw new IOException("Error leyendo dwg");
237
		}
238
	}
239

  
240
	private void setDwgVersion() throws IOException {
241
		File file = new File(fileName);
242
		FileInputStream fileInputStream = new FileInputStream(file);
243
		FileChannel fileChannel = fileInputStream.getChannel();
244
		long channelSize = fileChannel.size();
245
		bb = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, channelSize);
246
		byte[] versionBytes = {bb.get(0),
247
								bb.get(1),
248
								bb.get(2),
249
								bb.get(3),
250
								bb.get(4),
251
								bb.get(5)};
252
		ByteBuffer versionByteBuffer = ByteBuffer.wrap(versionBytes);
253
		String[] bs = new String[versionByteBuffer.capacity()];
254
		String versionString = "";
255
		for (int i=0; i<versionByteBuffer.capacity(); i++) {
256
			bs[i] = new String(new byte[]{(byte)(versionByteBuffer.get(i))});
257
			versionString = versionString + bs[i];
258
		}
259
		String version = (String) acadVersions.get(versionString);
260
		if(version == null)
261
			version = "Unknown Dwg format";
262
		this.dwgVersion = version;
263
	}
264

  
265
	public void setHeader(String key, Object value){
266
		headerVars.put(key, value);
267
	}
268

  
269
	public Object getHeader(String key){
270
		return headerVars.get(key);
271
	}
272

  
273
	/*
274
	 * A DwgLayer is a DWG drawing entity, so all DwgLayer objects are
275
	 * saved in dwgObjects collection.
276
	 * Instead of iterate over the full collection, is faster check every object
277
	 * and save all the DwgLayer instances in their own collection.
278
	 *
279
	 */
280
	protected void addDwgLayer(DwgLayer dwgLayer){
281
		layerTable.put(new Integer(dwgLayer.getHandle().getOffset()),
282
				dwgLayer);
283
	}
284

  
285
	private void printInfoOfAObject (DwgObject entity){
286
		logger.info("index = "+entity.getIndex() + " entity.type = " + entity.type + " entityClassName = "+ entity.getClass().getName());
287
		logger.info("handleCode = "+entity.getHandle().getCode());
288
		logger.info("entityLayerHandle = "+entity.getHandle().getOffset());
289
		if(entity.hasLayerHandle()){
290
			logger.info("layerHandleCode = "+entity.getLayerHandle().getCode());
291
			logger.info("layerHandle = "+entity.getLayerHandle().getOffset());
292
		}
293
		if(entity.hasSubEntityHandle()){
294
			logger.info("subEntityHandleCode = "+entity.getSubEntityHandle().getCode());
295
			logger.info("subEntityHandle = "+entity.getSubEntityHandle().getOffset());
296
		}
297
		if(entity.hasNextHandle()){
298
			logger.info("nextHandleCode = "+entity.getNextHandle().getCode());
299
			logger.info("nextHandle = "+entity.getNextHandle().getOffset());
300
		}
301
		if(entity.hasPreviousHandle()){
302
			logger.info ("previousHandleCode = "+entity.getPreviousHandle().getCode());
303
			logger.info ("previousHandle = "+entity.getPreviousHandle().getOffset());
304
		}
305
		if(entity.hasXDicObjHandle()){
306
			logger.info ("xDicObjHandleCode = "+entity.getXDicObjHandle());
307
			logger.info ("xDicObjHandle = "+entity.getXDicObjHandle());
308
		}
309
		if(entity.hasReactorsHandles()){
310
			ArrayList reactorsHandles = entity.getReactorsHandles();
311
			int size = reactorsHandles.size();
312
			logger.info ("NUMERO DE reactors = "+size);
313
			DwgHandleReference hr;
314
			for(int i=0; i<size; i++){
315
				hr=(DwgHandleReference)reactorsHandles.get(i);
316
				logger.info ("reactorHandleCode = "+hr.getCode());
317
				logger.info (" reactorHandle = "+hr.getOffset());
318
			}
319
		}
320

  
321
	}
322
	public DwgLayer getDwgLayer(DwgObject entity){
323
		DwgHandleReference handle = entity.getLayerHandle();
324
		if(handle == null){
325
			return null;
326
		}
327
		int	handleCode = handle.getCode();
328
		int	entityLayerHandle = entity.getLayerHandle().getOffset();
329
		int layerHandle = -1;
330

  
331
		int entityRecord;
332
		DwgObject object;
333

  
334

  
335
		/*
336
		 * OpenDWG spec, v3, page 11. HANDLE REFERENCES
337
		 *
338
		 * A handle is formed by this fields:
339
		 * a) CODE (4 bits)
340
		 * b) COUNTER (4 bits)
341
		 * c) OFFSET of the object (handle itself).
342
		 *
343
		 * CODE could take these values:
344
		 * 1) 0x2, 0x3, 0x4, 0x5 -> offset is the handle of the layer
345
		 * 2) 0x6 -> offset is the next object handle
346
		 * 3) 0x8 -> offset is the previous object handle
347
		 * 4) 0xA -> result is reference handle plus offset
348
 		 * 5) 0xC -> result is reference handle minus offset
349
		 *
350
		 * */
351

  
352
		// FIXME: Esto no esta terminado. Falta considerar los codigo
353
		// 0x2, 0x3, 0x6, 0xA que no han aparecido en los archivos de prueba.
354
		switch(handleCode){
355
		case 0x4:
356
			if (entity.hasNextHandle()){
357
				int nextHandleCode = entity.getNextHandle().getCode();
358
				if (nextHandleCode == 0x5) {
359
					layerHandle = entity.getNextHandle().getOffset();
360
				} else {
361
					//TODO: No se han previsto nextHandleCode != 0x5
362
//					System.out.println ("DwgFile.getDwgLayer: handleCode "+handleCode+
363
//							" con nextHandleCode "+ nextHandleCode +" no implementado.");
364
				}
365
			} else {
366
				layerHandle = entity.getLayerHandle().getOffset();
367
			}
368
			break;
369
		case 0x5:
370
			layerHandle = entity.getLayerHandle().getOffset();
371
			break;
372
		case 0x8:
373
			if (entity.hasNextHandle()){
374
				int nextHandleCode = entity.getNextHandle().getCode();
375
				if (nextHandleCode == 0x5) {
376
					layerHandle = entity.getNextHandle().getOffset();
377
				} else {
378
					//TODO No se han previsto nextHandleCode != 0x5
379
//					System.out.println ("DwgFile.getDwgLayer: handleCode "+handleCode+
380
//							" con nextHandleCode "+ nextHandleCode +" no implementado.");
381
				}
382
			} else {
383
				layerHandle = entity.getHandle().getOffset() - 1;
384
			}
385
			break;
386
		case 0xC:
387
			if (entity.hasNextHandle()){
388
				int nextHandleCode = entity.getNextHandle().getCode();
389
				if (nextHandleCode == 0x5) {
390
					layerHandle = entity.getNextHandle().getOffset();
391
				} else {
392
					//TODO: No se han previsto nextHandleCode != 0x5
393
//					System.out.println ("DwgFile.getDwgLayer: handleCode "+handleCode+
394
//							" con nextHandleCode "+ nextHandleCode +" no implementado.");
395
				}
396
			} else {
397
				layerHandle = entity.getHandle().getOffset() - entity.getLayerHandle().getOffset() + 1;
398
			}
399
			break;
400
		default:
401
//			System.out.println ("DwgFile.getDwgLayer: handleCode "+handleCode+" no implementado. entityLayerHandle="+entityLayerHandle);
402
		}
403

  
404
		if(layerHandle != -1){
405
			Iterator lyrIterator = layerTable.values().iterator();
406
			while(lyrIterator.hasNext()){
407
				DwgLayer lyr = (DwgLayer) lyrIterator.next();
408
				int lyrHdl = lyr.getHandle().getOffset();
409
				if (lyrHdl == layerHandle){
410
					return lyr;
411
				}
412
			}
413
		}
414
//		System.out.println("NO SE HA ENCONTRADO UNA CAPA CON HANDLE " + layerHandle);
415
//		printInfoOfAObject(entity);
416
		return null;
417
	}
418

  
419
	public DwgObject getDwgSuperEntity(DwgObject entity) {
420
		if(entity.hasSubEntityHandle()){
421
			int handleCode = entity.subEntityHandle.getCode();
422
			int offset = entity.subEntityHandle.getOffset();
423
			int handle = -1;
424

  
425
			DwgObject object;
426

  
427
			switch(handleCode){
428
			// TODO: case 0x2:
429
			// TODO: case 0x3:
430
			case 0x4:
431
			case 0x5:
432
				handle = offset;
433
				break;
434
			// TODO: case 0x6:
435
			case 0x8:
436
				handle=entity.getHandle().getOffset() - 1;
437
				break;
438
			case 0xA:
439
				handle = entity.getHandle().getOffset() + offset;
440
				break;
441
			case 0xC:
442
				handle = entity.getHandle().getOffset() - offset;
443
				break;
444
			default:
445
				logger.warn ("DwgObject.getDwgSuperEntity: handleCode "+handleCode+" no implementado. offset = "+offset);
446
			}
447
			if(handle != -1){
448
				object = getDwgObjectFromHandle(handle);
449
				if(object != null)
450
					return object;
451
			}
452
		}
453
		return null;
454
	}
455

  
456
	public String getLayerName(DwgObject entity) {
457
		DwgLayer dwgLayer = getDwgLayer(entity);
458
		if(dwgLayer == null){
459
			return "";
460
		}else{
461
			return dwgLayer.getName();
462
		}
463
	}
464

  
465
	/**
466
     * Returns the color of the layer of a DWG object
467
	 *
468
     * @param entity DWG object which we want to know its layer color
469
	 * @return int Layer color of the DWG object in the Autocad color code
470
	 */
471
	public int getColorByLayer(DwgObject entity) {
472
		int colorByLayer;
473
		DwgLayer dwgLyr = getDwgLayer(entity);
474
		if(dwgLyr == null)
475
			colorByLayer = 0;
476
		else
477
			colorByLayer = dwgLyr.getColor();
478
		return colorByLayer;
479
	}
480
	/**
481
	 * Configure the geometry of the polylines in a DWG file from the vertex list in
482
	 * this DWG file. This geometry is given by an array of Points.
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff