Statistics
| Revision:

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

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

    
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
import com.iver.cit.jdwglib.dwg.objects.DwgBlock;
52
import com.iver.cit.jdwglib.dwg.objects.DwgBlockControl;
53
import com.iver.cit.jdwglib.dwg.objects.DwgBlockHeader;
54

    
55
import freenet.support.HexUtil;
56

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

    
65
        protected ByteBuffer bb;
66

    
67

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

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

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

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

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

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

    
269
//                        }
270
                }
271
        }
272

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

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

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

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

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

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

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

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

    
327
                return bitPos;
328
        }
329

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

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

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

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

    
394
                }
395

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

    
402
                }
403

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

    
410
                }
411
                return bitPos;
412
        }
413

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

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

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

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

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

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

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

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

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

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

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

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