Statistics
| Revision:

root / trunk / libraries / libDwg / src / com / iver / cit / jdwglib / dwg / readers / DwgFileV15Reader.java @ 10112

History | View | Annotate | Download (15.3 KB)

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

    
37
import java.io.IOException;
38
import java.nio.ByteBuffer;
39
import java.nio.ByteOrder;
40
import java.util.ArrayList;
41
import java.util.logging.Logger;
42

    
43
import com.iver.cit.gvsig.fmap.drivers.dgn.ByteUtils;
44
import com.iver.cit.jdwglib.dwg.CorruptedDwgEntityException;
45
import com.iver.cit.jdwglib.dwg.DwgFile;
46
import com.iver.cit.jdwglib.dwg.DwgHandleReference;
47
import com.iver.cit.jdwglib.dwg.DwgObject;
48
import com.iver.cit.jdwglib.dwg.DwgObjectFactory;
49
import com.iver.cit.jdwglib.dwg.DwgObjectOffset;
50
import com.iver.cit.jdwglib.dwg.DwgUtil;
51

    
52
import freenet.support.HexUtil;
53

    
54
/**
55
 * The DwgFileV15Reader reads the DWG version 15 format
56
 * 
57
 * @author jmorell
58
 */
59
public class DwgFileV15Reader implements IDwgFileReader {
60
        protected DwgFile dwgFile;
61

    
62
        protected ByteBuffer bb;
63

    
64
        /**
65
         * Reads the DWG version 15 format
66
         * 
67
         * @param dwgFile
68
         *            Represents the DWG file that we want to read
69
         * @throws IOException
70
         *             When DWG file path is wrong
71
         */
72
        public void read(DwgFile dwgFile, ByteBuffer bb) throws IOException {
73
                this.dwgFile = dwgFile;
74
                this.bb = bb;
75

    
76
                readDwgSectionOffsets();
77
                try {
78
                        readDwgObjectOffsets();
79
                        //readDwgClasses(bb);
80
                } catch (Exception e) {
81
                        //                    System.out.println("Error leyendo offsets y classes. Posible
82
                        // corrupci?n en" +
83
                        //                                    "el DWG file ...");
84
                }
85
                readDwgObjects();
86
        }
87

    
88
        /**
89
         * It read the SECTIONS from the header of the DWG file
90
         */
91
        protected void readDwgSectionOffsets() {
92
                bb.position(19);
93
                bb.order(ByteOrder.LITTLE_ENDIAN);
94
                short codePage = bb.getShort();
95
                int count = bb.getInt();
96
                for (int i = 0; i < count; i++) {
97
                        byte rec = bb.get();
98
                        int seek = bb.getInt();
99
                        int size = bb.getInt();
100
                        if (rec == 0) {
101
                                dwgFile.addDwgSectionOffset("HEADERS", seek, size);
102
                        } else if (rec == 1) {
103
                                dwgFile.addDwgSectionOffset("CLASSES", seek, size);
104
                        } else if (rec == 2) {
105
                                dwgFile.addDwgSectionOffset("OBJECTS", seek, size);
106
                        } else if (rec == 3) {
107
                                dwgFile.addDwgSectionOffset("UNKNOWN", seek, size);
108
                        } else if (rec == 4) {
109
                                dwgFile.addDwgSectionOffset("R14DATA", seek, size);
110
                        } else if (rec == 5) {
111
                                dwgFile.addDwgSectionOffset("R14REC5", seek, size);
112
                        } else {
113
                                //                                System.out.println("ERROR: C?digo de n?mero de registro
114
                                // no soportado: " + rec);
115
                        }
116
                }
117
        }
118

    
119
        /**
120
         * OpenDWG spec says: This section -object map- is a table which gives the
121
         * location of each object in the DWG file. This table is broken into
122
         * sections. It is basically a list of handle/file loc pairs. It could be
123
         * readed with this pseudocode:
124
         * 
125
         * Set lastHandle to all 0 and last loc to 0L. Repeat until section size ==
126
         * 2 section size = read short (in bigendian order) Repeat until out of data
127
         * for this section offset of this handle form last handle as modular char
128
         * offset of location in file from last location as modular char End repeat
129
         * End repeat
130
         *  
131
         */
132
        protected void readDwgObjectOffsets() throws Exception {
133
                int offset = dwgFile.getDwgSectionOffset("OBJECTS");
134
                bb.position(offset);
135
                while (true) {
136
                        bb.order(ByteOrder.BIG_ENDIAN);
137
                        /*
138
                         * We read the size of the next section. If size == 2, break (it is
139
                         * the last empty -except crc- section)
140
                         */
141
                        short size = bb.getShort();
142
                        if (size == 2)
143
                                break;
144
                        bb.order(ByteOrder.LITTLE_ENDIAN);
145
                        byte[] dataBytes = new byte[size];
146
                        for (int i = 0; i < dataBytes.length; i++) {
147
                                dataBytes[i] = bb.get();
148
                        }
149
                        int[] data = DwgUtil.bytesToMachineBytes(dataBytes);
150
                        int lastHandle = 0;
151
                        int lastLoc = 0;
152
                        int bitPos = 0;
153
                        int bitMax = (size - 2) * 8;
154
                        while (bitPos < bitMax) {
155
                                ArrayList v = DwgUtil.getModularChar(data, bitPos);
156
                                bitPos = ((Integer) v.get(0)).intValue();
157
                                lastHandle = lastHandle + ((Integer) v.get(1)).intValue();
158
                                v = DwgUtil.getModularChar(data, bitPos);
159
                                bitPos = ((Integer) v.get(0)).intValue();
160
                                lastLoc = lastLoc + ((Integer) v.get(1)).intValue();
161
                                dwgFile.addDwgObjectOffset(lastHandle, lastLoc);
162
                        }//while
163
                }//while
164
        }
165

    
166
        /*
167
         * Unused.
168
         * 
169
         * Dwg spec says that drawing entities (objects) that has not a fixed type
170
         * must read its type from this section
171
         * 
172
         *  
173
         */
174
        protected void readDwgClasses() throws Exception {
175
                int offset = dwgFile.getDwgSectionOffset("CLASSES");
176
                // Por ahora nos saltamos los 16 bytes de control
177
                bb.position(offset + 16);
178
                bb.order(ByteOrder.LITTLE_ENDIAN);
179
                int size = bb.getInt();
180
                byte[] dataBytes = new byte[size];
181
                for (int i = 0; i < dataBytes.length; i++) {
182
                        dataBytes[i] = bb.get();
183
                }
184
                int[] data = DwgUtil.bytesToMachineBytes(dataBytes);
185
                for (int i = 0; i < data.length; i++) {
186
                        data[i] = (byte) ByteUtils.getUnsigned((byte) data[i]);
187
                }
188
                bb.position(bb.position() + 2 + 16);
189
                int maxbit = size * 8;
190
                int bitPos = 0;
191
                while ((bitPos + 8) < maxbit) {
192
                        ArrayList v = DwgUtil.getBitShort(data, bitPos);
193
                        bitPos = ((Integer) v.get(0)).intValue();
194
                        v = DwgUtil.getBitShort(data, bitPos);
195
                        bitPos = ((Integer) v.get(0)).intValue();
196
                        v = DwgUtil.getTextString(data, bitPos);
197
                        bitPos = ((Integer) v.get(0)).intValue();
198
                        v = DwgUtil.getTextString(data, bitPos);
199
                        bitPos = ((Integer) v.get(0)).intValue();
200
                        v = DwgUtil.getTextString(data, bitPos);
201
                        bitPos = ((Integer) v.get(0)).intValue();
202
                        v = DwgUtil.testBit(data, bitPos);
203
                        bitPos = ((Integer) v.get(0)).intValue();
204
                        v = DwgUtil.getBitShort(data, bitPos);
205
                        bitPos = ((Integer) v.get(0)).intValue();
206
                }
207
        }
208

    
209
        /**
210
         * Reads all the object referenced in the object map section of the DWG file
211
         * (using their object file obsets)
212
         */
213
        protected void readDwgObjects() {
214
                for (int i = 0; i < dwgFile.getDwgObjectOffsets().size(); i++) {
215
                        DwgObjectOffset doo = (DwgObjectOffset) dwgFile
216
                                        .getDwgObjectOffsets().get(i);
217
                        
218
                        DwgObject obj = readDwgObject(doo.getOffset(), i);
219
                        /*
220
                         * azabala: las entidades DWG no implementadas no nos aportan nada
221
                         * (aunque la sigo leyendo por si aparecen problemas de puntero de
222
                         * fichero) No considero por tanto los DwgObject if (obj != null) {
223
                         * dwgFile.addDwgObject(obj); }
224
                         */
225
                        if (obj != null && obj.getClass() != DwgObject.class) {
226
                                dwgFile.addDwgObject(obj);
227
                        }
228
                }
229
        }
230

    
231
        /**
232
         * Reads the header of an object in a DWG file Version 15
233
         * 
234
         * @param data
235
         *            Array of unsigned bytes obtained from the DWG binary file
236
         * @param offset
237
         *            The current bit offset where the value begins
238
         * @return int New offset
239
         */
240
        public int readObjectHeader(int[] data, int offset, DwgObject dwgObject) {
241
                int bitPos = offset;
242
                Integer mode = (Integer) DwgUtil.getBits(data, 2, bitPos);
243
                bitPos = bitPos + 2;
244
                dwgObject.setMode(mode.intValue());
245

    
246
                ArrayList v = DwgUtil.getBitLong(data, bitPos);
247
                bitPos = ((Integer) v.get(0)).intValue();
248
                int rnum = ((Integer) v.get(1)).intValue();
249
                dwgObject.setNumReactors(rnum);
250

    
251
                v = DwgUtil.testBit(data, bitPos);
252
                bitPos = ((Integer) v.get(0)).intValue();
253
                boolean nolinks = ((Boolean) v.get(1)).booleanValue();
254
                dwgObject.setNoLinks(nolinks);
255

    
256
                v = DwgUtil.getBitShort(data, bitPos);
257
                bitPos = ((Integer) v.get(0)).intValue();
258
                int color = ((Integer) v.get(1)).intValue();
259
                dwgObject.setColor(color);
260

    
261
                v = DwgUtil.getBitDouble(data, bitPos);
262
                bitPos = ((Integer) v.get(0)).intValue();
263
                float ltscale = ((Double) v.get(1)).floatValue();
264

    
265
                Integer ltflag = (Integer) DwgUtil.getBits(data, 2, bitPos);
266
                bitPos = bitPos + 2;
267

    
268
                Integer psflag = (Integer) DwgUtil.getBits(data, 2, bitPos);
269
                bitPos = bitPos + 2;
270

    
271
                v = DwgUtil.getBitShort(data, bitPos);
272
                bitPos = ((Integer) v.get(0)).intValue();
273
                int invis = ((Integer) v.get(1)).intValue();
274

    
275
                v = DwgUtil.getRawChar(data, bitPos);
276
                bitPos = ((Integer) v.get(0)).intValue();
277
                int weight = ((Integer) v.get(1)).intValue();
278

    
279
                return bitPos;
280
        }
281

    
282
        /**
283
         * Reads the tail of an object in a DWG file Version 15
284
         * 
285
         * @param data
286
         *            Array of bytes obtained from the DWG binary file
287
         * @param offset
288
         *            Offset for this array of bytes
289
         * @return int New offset
290
         * @throws CorruptedDwgEntityException 
291
         * @throws RuntimeException 
292
         */
293
        public int readObjectTailer(int[] data, int offset, DwgObject dwgObject) throws RuntimeException, CorruptedDwgEntityException {
294
                int bitPos = offset;
295
                /*
296
                 * Subentity ref handle. Esto se aplica sobre VERTEX, ATTRIB, SEQEND
297
                 */
298
                if (dwgObject.getMode() == 0x0) {
299
                        DwgHandleReference subEntityHandle = new DwgHandleReference();
300
                        bitPos = subEntityHandle.read(data, bitPos);
301
                        dwgObject.setSubEntityHandle(subEntityHandle);
302
                        System.out.println("subEntityHandle: code = "+subEntityHandle.getCode()+" offset = "+subEntityHandle.getOffset());
303
                }
304

    
305
                /*
306
                 * Reactors handles TODO No se est?n usando para setear nada en
307
                 * DwgObject
308
                 */
309
                DwgHandleReference reactorHandle;
310
                for (int i = 0; i < dwgObject.getNumReactors(); i++) {
311
                        reactorHandle = new DwgHandleReference();
312
                        bitPos = reactorHandle.read(data, bitPos);
313
                        dwgObject.addReactorHandle(reactorHandle);
314
                        System.out.println("reactorHandle "+i+": code = "+reactorHandle.getCode()+" offset = "+reactorHandle.getOffset());
315
                }
316

    
317
                /*
318
                 * XDICOBJHANDLE
319
                 */
320
                DwgHandleReference xDicObjHandle = new DwgHandleReference();
321
                bitPos = xDicObjHandle.read(data, bitPos);
322
                dwgObject.setXDicObjHandle(xDicObjHandle);
323
                System.out.println("xDicObjHandle: code = "+xDicObjHandle.getCode()+" offset = "+xDicObjHandle.getOffset());
324
                
325
                /*
326
                 * Layer Handle code
327
                 */
328
                
329
                DwgHandleReference handle = new DwgHandleReference();
330
                bitPos = handle.read(data, bitPos);
331
                dwgObject.setLayerHandle(handle);
332
                System.out.println("layerHandle: code = "+handle.getCode()+" offset = "+handle.getOffset());
333
                
334
//                System.out.println(cadena + " ==> " + handle);
335

    
336
                if (!dwgObject.isNoLinks()) {
337

    
338
                        DwgHandleReference previousHandle = new DwgHandleReference();
339
                        bitPos = previousHandle.read(data, bitPos);
340
                        dwgObject.setPreviousHandle(previousHandle);
341
                        System.out.println("previousHandle: code = "+previousHandle.getCode()+" offset = "+previousHandle.getOffset());
342
        
343
                        DwgHandleReference nextHandle = new DwgHandleReference();
344
                        bitPos = nextHandle.read(data, bitPos);
345
                        dwgObject.setNextHandle(nextHandle);
346
                        System.out.println("nextHandle: code = "+nextHandle.getCode()+" offset = "+nextHandle.getOffset());
347

    
348
                }
349

    
350
                if (dwgObject.getLinetypeFlags() == 0x3) {
351
                        DwgHandleReference lineTypeHandle = new DwgHandleReference();
352
                        bitPos = lineTypeHandle.read(data, bitPos);
353
                        dwgObject.setLineTypeHandle(lineTypeHandle);
354
                        System.out.println("lineTypeHandle: code = "+lineTypeHandle.getCode()+" offset = "+lineTypeHandle.getOffset());
355

    
356
                }
357

    
358
                if (dwgObject.getPlotstyleFlags() == 0x3) {
359
                        DwgHandleReference plotStyleHandle = new DwgHandleReference();
360
                        bitPos = plotStyleHandle.read(data, bitPos);
361
                        dwgObject.setPlotStyleHandle(plotStyleHandle);
362
                        System.out.println("plotStyleHandle: code = "+plotStyleHandle.getCode()+" offset = "+plotStyleHandle.getOffset());
363

    
364
                }
365
                return bitPos;
366
        }
367

    
368
        /**
369
         * Return a dwg object from its index in the dwg file
370
         * 
371
         * @param index
372
         *            of the requested dwg object in the dwg file
373
         *  
374
         */
375
        public DwgObject getDwgObjectByIndex(int index) {
376
                DwgObjectOffset doo = (DwgObjectOffset) dwgFile.getDwgObjectOffsets()
377
                                .get(index);
378
                return readDwgObject(doo.getOffset(), index);
379
        }
380

    
381
        /**
382
         * Reads a dwg drawing entity (dwg object) given its offset in the file
383
         */
384

    
385
        protected DwgObject readDwgObject(int offset, int index) {
386
                DwgObject obj = null;
387
                try {
388
                        bb.position(offset);
389
                        int size = DwgUtil.getModularShort(bb);
390

    
391
                        bb.order(ByteOrder.LITTLE_ENDIAN);
392
                        byte[] dataBytes = new byte[size];
393
                        String[] dataMachValString = new String[size];
394
                        int[] data = new int[size];
395
                        for (int i = 0; i < size; i++) {
396
                                dataBytes[i] = bb.get();
397
                                dataMachValString[i] = HexUtil
398
                                                .bytesToHex(new byte[] { dataBytes[i] });
399
                                Integer dataMachValShort = Integer.decode("0x"
400
                                                + dataMachValString[i]);
401
                                data[i] = dataMachValShort.byteValue();
402
                                data[i] = ByteUtils.getUnsigned((byte) data[i]);
403
                        }
404

    
405
                        int bitPos = 0;
406
                        ArrayList v = DwgUtil.getBitShort(data, bitPos);
407
                        bitPos = ((Integer) v.get(0)).intValue();
408
                        int type = ((Integer) v.get(1)).intValue();
409

    
410
                        obj = DwgObjectFactory.getInstance().create(type, index);
411
                        obj.setDwgFile(this.dwgFile);
412

    
413
                        v = DwgUtil.getRawLong(data, bitPos);
414
                        bitPos = ((Integer) v.get(0)).intValue();
415
                        int objBSize = ((Integer) v.get(1)).intValue();
416
                        obj.setSizeInBits(objBSize);
417

    
418
                        DwgHandleReference entityHandle = new DwgHandleReference();
419
                        bitPos = entityHandle.read(data, bitPos);
420
                        obj.setHandle(entityHandle);
421
                        System.out.println("entityHandle:code = " + entityHandle.getCode() +" offset = "+entityHandle.getOffset());
422

    
423
                        v = DwgUtil.readExtendedData(data, bitPos);
424
                        bitPos = ((Integer) v.get(0)).intValue();
425
                        ArrayList extData = (ArrayList) v.get(1);
426
                        obj.setExtendedData(extData);
427

    
428
                        boolean gflag = false;
429
                        gflag = obj.isGraphicsFlag();
430
                        if (gflag) {
431
                                //lee un flag boolean
432
                                v = DwgUtil.testBit(data, bitPos);
433
                                bitPos = ((Integer) v.get(0)).intValue();
434
                                boolean val = ((Boolean) v.get(1)).booleanValue();
435
                                //si hay imagen asociada, se lee por completo
436
                                if (val) {
437
                                        v = DwgUtil.getRawLong(data, bitPos);
438
                                        bitPos = ((Integer) v.get(0)).intValue();
439
                                        size = ((Integer) v.get(1)).intValue();
440
                                        int bgSize = size * 8;
441
                                        Integer giData = (Integer) DwgUtil.getBits(data, bgSize,
442
                                                        bitPos);
443
                                        obj.setGraphicData(giData.intValue());
444
                                        bitPos = bitPos + bgSize;
445
                                }
446
                        }
447
                                if(obj.getClass() != DwgObject.class)
448
                                        readSpecificObject(obj, data, bitPos);
449
//                                else
450
//                                        System.out.println("Dwg Object desconocido:"+obj.getType());
451
                } catch (RuntimeException e) {
452
                        e.printStackTrace();
453
                } catch (CorruptedDwgEntityException e) {
454
                        // TODO Auto-generated catch block
455
                        e.printStackTrace();
456
                        return null;
457
                        
458
                }
459
                return obj;
460
        }
461

    
462
        /*
463
         * TODO Esto est? pesimamente dise?ado. Cada objeto DwgObject debe tener un
464
         * metodo readSpecificObject(data,bitPos)
465
         *  
466
         */
467
        protected void readSpecificObject(DwgObject obj, int[] data, int bitPos)
468
                        throws RuntimeException, CorruptedDwgEntityException {
469
                        DwgObjectReaderPool pool = DwgObjectReaderPool.getInstance();
470
                        IDwgObjectReader reader = pool.get(obj, "15");
471
                        if(reader != null){
472
                                reader.setFileReader(this);
473
                                reader.readSpecificObj(data, bitPos, obj);
474
                        }else{
475
                                System.out.println("No se ha implementado la lectura de "+obj.getClass().getName()+", code="+obj.getType());
476
                        }
477
        }
478
}