Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libDwg / src / com / iver / cit / jdwglib / dwg / readers / DwgFileV15Reader.java @ 10386

History | View | Annotate | Download (16.9 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.LinkedList;
42
import java.util.List;
43

    
44
import com.iver.cit.gvsig.fmap.drivers.dgn.ByteUtils;
45
import com.iver.cit.jdwglib.dwg.CorruptedDwgEntityException;
46
import com.iver.cit.jdwglib.dwg.DwgFile;
47
import com.iver.cit.jdwglib.dwg.DwgHandleReference;
48
import com.iver.cit.jdwglib.dwg.DwgObject;
49
import com.iver.cit.jdwglib.dwg.DwgObjectFactory;
50
import com.iver.cit.jdwglib.dwg.DwgObjectOffset;
51
import com.iver.cit.jdwglib.dwg.DwgUtil;
52
import com.iver.cit.jdwglib.dwg.objects.DwgBlock;
53
import com.iver.cit.jdwglib.dwg.objects.DwgBlockControl;
54
import com.iver.cit.jdwglib.dwg.objects.DwgBlockHeader;
55

    
56
import freenet.support.HexUtil;
57

    
58
/**
59
 * The DwgFileV15Reader reads the DWG version 15 format
60
 * 
61
 * @author jmorell
62
 */
63
public class DwgFileV15Reader implements IDwgFileReader {
64
        protected DwgFile dwgFile;
65

    
66
        protected ByteBuffer bb;
67

    
68

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

    
81
                readDwgSectionOffsets();
82
                try {
83
                        readDwgObjectOffsets();
84
                        //readDwgClasses(bb);
85
                } catch (Exception e) {
86
                        //                    System.out.println("Error leyendo offsets y classes. Posible
87
                        // corrupci?n en" +
88
                        //                                    "el DWG file ...");
89
                }
90
                readDwgObjects();
91
                //checkSuperentities();
92
        }
93
        
94
        /*
95
         *TODO: Eliminar esto cuando terminemos con el testeo
96
         */
97
        protected void checkSuperentities(){
98
                System.out.println("***** CHEQUEANDO LAS SUPERENTIDADES *****");
99
                List objects = dwgFile.getDwgObjects();
100
                DwgObject obj;
101
                DwgObject superEnt;
102
                boolean buscado=false;
103
                boolean perdidos=false;
104
                int j=0;
105
                for (int i=0; i<objects.size(); i++){
106
                        obj = (DwgObject)objects.get(i);
107
                        if (obj.hasSubEntityHandle()){
108
                                buscado = true;
109
                                superEnt = dwgFile.getDwgSuperEntity(obj);
110
                                if (superEnt == null){
111
                                        j++;
112
                                }
113
                        }
114
                }
115
                if(j!=0) {
116
                        System.out.println("+++++ SE HAN PERDIDO LAS SUPERENTIDADES DE "+ j+" OBJETOS +++++");
117
                }
118
                System.out.println("***** FIN DEL CHEQUEO DE LAS SUPERENTIDADES *****");
119
                
120
        }
121
        
122

    
123
        /**
124
         * It read the SECTIONS from the header of the DWG file
125
         */
126
        protected void readDwgSectionOffsets() {
127
                bb.position(19);
128
                bb.order(ByteOrder.LITTLE_ENDIAN);
129
                short codePage = bb.getShort();
130
                int count = bb.getInt();
131
                for (int i = 0; i < count; i++) {
132
                        byte rec = bb.get();
133
                        int seek = bb.getInt();
134
                        int size = bb.getInt();
135
                        if (rec == 0) {
136
                                dwgFile.addDwgSectionOffset("HEADERS", seek, size);
137
                        } else if (rec == 1) {
138
                                dwgFile.addDwgSectionOffset("CLASSES", seek, size);
139
                        } else if (rec == 2) {
140
                                dwgFile.addDwgSectionOffset("OBJECTS", seek, size);
141
                        } else if (rec == 3) {
142
                                dwgFile.addDwgSectionOffset("UNKNOWN", seek, size);
143
                        } else if (rec == 4) {
144
                                dwgFile.addDwgSectionOffset("R14DATA", seek, size);
145
                        } else if (rec == 5) {
146
                                dwgFile.addDwgSectionOffset("R14REC5", seek, size);
147
                        } else {
148
                                //                                System.out.println("ERROR: C?digo de n?mero de registro
149
                                // no soportado: " + rec);
150
                        }
151
                }
152
        }
153

    
154
        /**
155
         * OpenDWG spec says: This section -object map- is a table which gives the
156
         * location of each object in the DWG file. This table is broken into
157
         * sections. It is basically a list of handle/file loc pairs. It could be
158
         * readed with this pseudocode:
159
         * 
160
         * Set lastHandle to all 0 and last loc to 0L. Repeat until section size ==
161
         * 2 section size = read short (in bigendian order) Repeat until out of data
162
         * for this section offset of this handle form last handle as modular char
163
         * offset of location in file from last location as modular char End repeat
164
         * End repeat
165
         *  
166
         */
167
        protected void readDwgObjectOffsets() throws Exception {
168
                int offset = dwgFile.getDwgSectionOffset("OBJECTS");
169
                bb.position(offset);
170
                while (true) {
171
                        bb.order(ByteOrder.BIG_ENDIAN);
172
                        /*
173
                         * We read the size of the next section. If size == 2, break (it is
174
                         * the last empty -except crc- section)
175
                         */
176
                        short size = bb.getShort();
177
                        if (size == 2)
178
                                break;
179
                        bb.order(ByteOrder.LITTLE_ENDIAN);
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
                        int lastHandle = 0;
186
                        int lastLoc = 0;
187
                        int bitPos = 0;
188
                        int bitMax = (size - 2) * 8;
189
                        while (bitPos < bitMax) {
190
                                ArrayList v = DwgUtil.getModularChar(data, bitPos);
191
                                bitPos = ((Integer) v.get(0)).intValue();
192
                                lastHandle = lastHandle + ((Integer) v.get(1)).intValue();
193
                                v = DwgUtil.getModularChar(data, bitPos);
194
                                bitPos = ((Integer) v.get(0)).intValue();
195
                                lastLoc = lastLoc + ((Integer) v.get(1)).intValue();
196
                                dwgFile.addDwgObjectOffset(lastHandle, lastLoc);
197
                        }//while
198
                }//while
199
        }
200

    
201
        /*
202
         * Unused.
203
         * 
204
         * Dwg spec says that drawing entities (objects) that has not a fixed type
205
         * must read its type from this section
206
         * 
207
         *  
208
         */
209
        protected void readDwgClasses() throws Exception {
210
                int offset = dwgFile.getDwgSectionOffset("CLASSES");
211
                // Por ahora nos saltamos los 16 bytes de control
212
                bb.position(offset + 16);
213
                bb.order(ByteOrder.LITTLE_ENDIAN);
214
                int size = bb.getInt();
215
                byte[] dataBytes = new byte[size];
216
                for (int i = 0; i < dataBytes.length; i++) {
217
                        dataBytes[i] = bb.get();
218
                }
219
                int[] data = DwgUtil.bytesToMachineBytes(dataBytes);
220
                for (int i = 0; i < data.length; i++) {
221
                        data[i] = (byte) ByteUtils.getUnsigned((byte) data[i]);
222
                }
223
                bb.position(bb.position() + 2 + 16);
224
                int maxbit = size * 8;
225
                int bitPos = 0;
226
                while ((bitPos + 8) < maxbit) {
227
                        ArrayList v = DwgUtil.getBitShort(data, bitPos);
228
                        bitPos = ((Integer) v.get(0)).intValue();
229
                        v = DwgUtil.getBitShort(data, bitPos);
230
                        bitPos = ((Integer) v.get(0)).intValue();
231
                        v = DwgUtil.getTextString(data, bitPos);
232
                        bitPos = ((Integer) v.get(0)).intValue();
233
                        v = DwgUtil.getTextString(data, bitPos);
234
                        bitPos = ((Integer) v.get(0)).intValue();
235
                        v = DwgUtil.getTextString(data, bitPos);
236
                        bitPos = ((Integer) v.get(0)).intValue();
237
                        v = DwgUtil.testBit(data, bitPos);
238
                        bitPos = ((Integer) v.get(0)).intValue();
239
                        v = DwgUtil.getBitShort(data, bitPos);
240
                        bitPos = ((Integer) v.get(0)).intValue();
241
                }
242
        }
243

    
244
        /**
245
         * Reads all the object referenced in the object map section of the DWG file
246
         * (using their object file obsets)
247
         */
248
        protected void readDwgObjects() {
249
                for (int i = 0; i < dwgFile.getDwgObjectOffsets().size(); i++) {
250
                        DwgObjectOffset doo = (DwgObjectOffset) dwgFile
251
                                        .getDwgObjectOffsets().get(i);
252
                        
253
                        DwgObject obj = readDwgObject(doo.getOffset(), i);
254
                        /*
255
                         * azabala: las entidades DWG no implementadas no nos aportan nada
256
                         * (aunque la sigo leyendo por si aparecen problemas de puntero de
257
                         * fichero) No considero por tanto los DwgObject if (obj != null) {
258
                         * dwgFile.addDwgObject(obj); }
259
                         *        
260
                         * paco: propongo reconsiderar esto. Si no cargamos todos los objetos
261
                         * podemos tener problemas con las subentities.
262
                         */
263
                        if (obj != null && obj.getClass() != DwgObject.class) {
264
                                dwgFile.addDwgObject(obj);
265
//                            DwgObject superEnt = dwgFile.getDwgSuperEntity(obj);
266
//                            if(superEnt != null){
267
//                              System.out.println(superEnt.getClass().getName() + "(TIPO " +Integer.toHexString(superEnt.getType())+") ES SUPERENTITY DE "+obj.getClass().getName());
268
                            } 
269

    
270
//                        }
271
                }
272
        }
273

    
274
        /**
275
         * Reads the header of an object in a DWG file Version 15
276
         * 
277
         * @param data
278
         *            Array of unsigned bytes obtained from the DWG binary file
279
         * @param offset
280
         *            The current bit offset where the value begins
281
         * @return int New offset
282
         */
283
        public int readObjectHeader(int[] data, int offset, DwgObject dwgObject) {
284
                int bitPos = offset;
285
                Integer mode = (Integer) DwgUtil.getBits(data, 2, bitPos);
286
                bitPos = bitPos + 2;
287
                dwgObject.setMode(mode.intValue());
288

    
289
                /*
290
                ArrayList v = DwgUtil.getBitLong(data, bitPos);
291
                bitPos = ((Integer) v.get(0)).intValue();
292
                int rnum = ((Integer) v.get(1)).intValue();
293
                dwgObject.setNumReactors(rnum);
294
                */
295
                ArrayList v = DwgUtil.getBitShort(data, bitPos);
296
                bitPos = ((Integer) v.get(0)).intValue();
297
                int rnum = ((Integer) v.get(1)).intValue();
298
                dwgObject.setNumReactors(rnum);
299
                
300
                v = DwgUtil.testBit(data, bitPos);
301
                bitPos = ((Integer) v.get(0)).intValue();
302
                boolean nolinks = ((Boolean) v.get(1)).booleanValue();
303
                dwgObject.setNoLinks(nolinks);
304

    
305
                v = DwgUtil.getBitShort(data, bitPos);
306
                bitPos = ((Integer) v.get(0)).intValue();
307
                int color = ((Integer) v.get(1)).intValue();
308
                dwgObject.setColor(color);
309

    
310
                v = DwgUtil.getBitDouble(data, bitPos);
311
                bitPos = ((Integer) v.get(0)).intValue();
312
                float ltscale = ((Double) v.get(1)).floatValue();
313

    
314
                Integer ltflag = (Integer) DwgUtil.getBits(data, 2, bitPos);
315
                bitPos = bitPos + 2;
316

    
317
                Integer psflag = (Integer) DwgUtil.getBits(data, 2, bitPos);
318
                bitPos = bitPos + 2;
319

    
320
                v = DwgUtil.getBitShort(data, bitPos);
321
                bitPos = ((Integer) v.get(0)).intValue();
322
                int invis = ((Integer) v.get(1)).intValue();
323

    
324
                v = DwgUtil.getRawChar(data, bitPos);
325
                bitPos = ((Integer) v.get(0)).intValue();
326
                int weight = ((Integer) v.get(1)).intValue();
327

    
328
                return bitPos;
329
        }
330

    
331
        /**
332
         * Reads the tail of an object in a DWG file Version 15
333
         * 
334
         * @param data
335
         *            Array of bytes obtained from the DWG binary file
336
         * @param offset
337
         *            Offset for this array of bytes
338
         * @return int New offset
339
         * @throws CorruptedDwgEntityException 
340
         * @throws RuntimeException 
341
         */
342
        public int readObjectTailer(int[] data, int offset, DwgObject dwgObject) throws RuntimeException, CorruptedDwgEntityException {
343
                int bitPos = offset;
344
                /*
345
                 * Subentity ref handle. Esto se aplica sobre VERTEX, ATTRIB, SEQEND
346
                 */
347
                if (dwgObject.getMode() == 0x0) {
348
                        DwgHandleReference subEntityHandle = new DwgHandleReference();
349
                        bitPos = subEntityHandle.read(data, bitPos);
350
                        dwgObject.setSubEntityHandle(subEntityHandle);
351
//                        System.out.println("subEntityHandle: code = "+subEntityHandle.getCode()+" offset = "+subEntityHandle.getOffset());
352
                }
353

    
354
                /*
355
                 * Reactors handles TODO No se est?n usando para setear nada en
356
                 * DwgObject
357
                 */
358
                DwgHandleReference reactorHandle;
359
                for (int i = 0; i < dwgObject.getNumReactors(); i++) {
360
                        reactorHandle = new DwgHandleReference();
361
                        bitPos = reactorHandle.read(data, bitPos);
362
                        dwgObject.addReactorHandle(reactorHandle);
363
//                        System.out.println("reactorHandle "+i+": code = "+reactorHandle.getCode()+" offset = "+reactorHandle.getOffset());
364
                }
365

    
366
                /*
367
                 * XDICOBJHANDLE
368
                 */
369
                DwgHandleReference xDicObjHandle = new DwgHandleReference();
370
                bitPos = xDicObjHandle.read(data, bitPos);
371
                dwgObject.setXDicObjHandle(xDicObjHandle);
372
//                System.out.println("xDicObjHandle: code = "+xDicObjHandle.getCode()+" offset = "+xDicObjHandle.getOffset());
373
                
374
                /*
375
                 * Layer Handle code
376
                 */
377
                
378
                DwgHandleReference handle = new DwgHandleReference();
379
                bitPos = handle.read(data, bitPos);
380
                dwgObject.setLayerHandle(handle);
381
//                System.out.println("layerHandle: code = "+handle.getCode()+" offset = "+handle.getOffset());
382
                
383
                if (!dwgObject.isNoLinks()) {
384

    
385
                        DwgHandleReference previousHandle = new DwgHandleReference();
386
                        bitPos = previousHandle.read(data, bitPos);
387
                        dwgObject.setPreviousHandle(previousHandle);
388
//                        System.out.println("previousHandle: code = "+previousHandle.getCode()+" offset = "+previousHandle.getOffset());
389
        
390
                        DwgHandleReference nextHandle = new DwgHandleReference();
391
                        bitPos = nextHandle.read(data, bitPos);
392
                        dwgObject.setNextHandle(nextHandle);
393
//                        System.out.println("nextHandle: code = "+nextHandle.getCode()+" offset = "+nextHandle.getOffset());
394

    
395
                }
396

    
397
                if (dwgObject.getLinetypeFlags() == 0x3) {
398
                        DwgHandleReference lineTypeHandle = new DwgHandleReference();
399
                        bitPos = lineTypeHandle.read(data, bitPos);
400
                        dwgObject.setLineTypeHandle(lineTypeHandle);
401
//                        System.out.println("lineTypeHandle: code = "+lineTypeHandle.getCode()+" offset = "+lineTypeHandle.getOffset());
402

    
403
                }
404

    
405
                if (dwgObject.getPlotstyleFlags() == 0x3) {
406
                        DwgHandleReference plotStyleHandle = new DwgHandleReference();
407
                        bitPos = plotStyleHandle.read(data, bitPos);
408
                        dwgObject.setPlotStyleHandle(plotStyleHandle);
409
//                        System.out.println("plotStyleHandle: code = "+plotStyleHandle.getCode()+" offset = "+plotStyleHandle.getOffset());
410

    
411
                }
412
                return bitPos;
413
        }
414

    
415
        /**
416
         * Return a dwg object from its index in the dwg file
417
         * 
418
         * @param index
419
         *            of the requested dwg object in the dwg file
420
         *  
421
         */
422
        public DwgObject getDwgObjectByIndex(int index) {
423
                DwgObjectOffset doo = (DwgObjectOffset) dwgFile.getDwgObjectOffsets()
424
                                .get(index);
425
                return readDwgObject(doo.getOffset(), index);
426
        }
427

    
428
        /**
429
         * Reads a dwg drawing entity (dwg object) given its offset in the file
430
         */
431

    
432
        protected DwgObject readDwgObject(int offset, int index) {
433
                DwgObject obj = null;
434
                try {
435
                        bb.position(offset);
436
                        int size = DwgUtil.getModularShort(bb);
437

    
438
                        bb.order(ByteOrder.LITTLE_ENDIAN);
439
                        byte[] dataBytes = new byte[size];
440
                        String[] dataMachValString = new String[size];
441
                        int[] data = new int[size];
442
                        for (int i = 0; i < size; i++) {
443
                                dataBytes[i] = bb.get();
444
                                dataMachValString[i] = HexUtil
445
                                                .bytesToHex(new byte[] { dataBytes[i] });
446
                                Integer dataMachValShort = Integer.decode("0x"
447
                                                + dataMachValString[i]);
448
                                data[i] = dataMachValShort.byteValue();
449
                                data[i] = ByteUtils.getUnsigned((byte) data[i]);
450
                        }
451

    
452
                        int bitPos = 0;
453
                        ArrayList v = DwgUtil.getBitShort(data, bitPos);
454
                        bitPos = ((Integer) v.get(0)).intValue();
455
                        int type = ((Integer) v.get(1)).intValue();
456

    
457
                        obj = DwgObjectFactory.getInstance().create(type, index);
458

    
459
//                        System.out.println("SE HA CREADO UN OBJETO DEL TIPO = "+type+" =>> "+obj.getClass().getName());
460
                        if(obj == null)
461
                                return null;
462

    
463
                        v = DwgUtil.getRawLong(data, bitPos);
464
                        bitPos = ((Integer) v.get(0)).intValue();
465
                        int objBSize = ((Integer) v.get(1)).intValue();
466
                        obj.setSizeInBits(objBSize);
467

    
468
                        DwgHandleReference entityHandle = new DwgHandleReference();
469
                        bitPos = entityHandle.read(data, bitPos);
470
                        obj.setHandle(entityHandle);
471
//                        System.out.println("entityHandle:code = " + entityHandle.getCode() +" offset = "+entityHandle.getOffset());
472

    
473
                        v = DwgUtil.readExtendedData(data, bitPos);
474
                        bitPos = ((Integer) v.get(0)).intValue();
475
                        ArrayList extData = (ArrayList) v.get(1);
476
                        obj.setExtendedData(extData);
477

    
478
                        boolean gflag = false;
479
                        gflag = obj.isGraphicsFlag();
480
                        if (gflag) {
481
                                //lee un flag boolean
482
                                v = DwgUtil.testBit(data, bitPos);
483
                                bitPos = ((Integer) v.get(0)).intValue();
484
                                boolean val = ((Boolean) v.get(1)).booleanValue();
485
                                //si hay imagen asociada, se lee por completo
486
                                if (val) {
487
                                        v = DwgUtil.getRawLong(data, bitPos);
488
                                        bitPos = ((Integer) v.get(0)).intValue();
489
                                        size = ((Integer) v.get(1)).intValue();
490
                                        int bgSize = size * 8;
491
                                        Integer giData = (Integer) DwgUtil.getBits(data, bgSize,
492
                                                        bitPos);
493
                                        obj.setGraphicData(giData.intValue());
494
                                        bitPos = bitPos + bgSize;
495
                                }
496
                        }
497
                                if(obj.getClass() != DwgObject.class)
498
                                        readSpecificObject(obj, data, bitPos);
499
//                                else
500
//                                        System.out.println("Dwg Object desconocido:"+obj.getType());
501
                } catch (RuntimeException e) {
502
                        e.printStackTrace();
503
                } catch (CorruptedDwgEntityException e) {
504
                        // TODO Auto-generated catch block
505
                        e.printStackTrace();
506
                        return null;        
507
                }
508
                return obj;
509
        }
510

    
511
        /*
512
         * TODO Esto est? pesimamente dise?ado. Cada objeto DwgObject debe tener un
513
         * metodo readSpecificObject(data,bitPos)
514
         *  
515
         */
516
        protected void readSpecificObject(DwgObject obj, int[] data, int bitPos)
517
                        throws RuntimeException, CorruptedDwgEntityException {
518
                        DwgObjectReaderPool pool = DwgObjectReaderPool.getInstance();
519
                        IDwgObjectReader reader = pool.get(obj, "15");
520
                        if(reader != null){
521
                                reader.setFileReader(this);
522
                                reader.readSpecificObj(data, bitPos, obj);
523
                        }else{
524
                                System.out.println("No se ha implementado la lectura de "+obj.getClass().getName()+", code="+obj.getType());
525
                        }
526
        }
527
}