1 
2 /******************************************************************************
3 **  libDXFrw - Library to read/write DXF files (ascii & binary)              **
4 **                                                                           **
5 **  Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com               **
6 **                                                                           **
7 **  This library is free software, licensed under the terms of the GNU       **
8 **  General Public License as published by the Free Software Foundation,     **
9 **  either version 2 of the License, or (at your option) any later version.  **
10 **  You should have received a copy of the GNU General Public License        **
11 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.    **
12 ******************************************************************************/
13 
14 #include <cstdlib>
15 #include <iostream>
16 #include <fstream>
17 #include <string>
18 #include <sstream>
19 
20 #include "dwgreader15.h"
21 #include "drw_textcodec.h"
22 
23 #include "../libdwgr.h"
24 
25 #include "qgslogger.h"
26 
readMetaData()27 bool dwgReader15::readMetaData()
28 {
29   QgsDebugMsg( "Entering." );
30   version = parent->getVersion();
31   decoder.setVersion( version, false );
32 
33   if ( ! fileBuf->setPosition( 13 ) )
34     return false;
35   previewImagePos = fileBuf->getRawLong32();
36   QgsDebugMsg( QString( "previewImagePos (seekerImageData) = %1" ).arg( previewImagePos ) );
37   /* MEASUREMENT system variable 2 bytes*/
38   duint16 meas = fileBuf->getRawShort16();
39   QgsDebugMsg( QString( "MEASUREMENT (0 = English, 1 = Metric)= %1" ).arg( meas ) );
40   Q_UNUSED( meas );
41   duint16 cp = fileBuf->getRawShort16();
42   QgsDebugMsg( QString( "codepage= %1" ).arg( cp ) );
43 
44   if ( cp == 29 ) //TODO RLZ: locate wath code page and correct this
45     decoder.setCodePage( "ANSI_1252", false );
46   if ( cp == 30 )
47     decoder.setCodePage( "ANSI_1252", false );
48   return true;
49 }
50 
readFileHeader()51 bool dwgReader15::readFileHeader()
52 {
53   QgsDebugMsg( "Entering." );
54   bool ret = true;
55   if ( ! fileBuf->setPosition( 21 ) )
56     return false;
57   duint32 count = fileBuf->getRawLong32();
58   QgsDebugMsg( QString( "count records=%1" ).arg( count ) );
59 
60   for ( unsigned int i = 0; i < count; i++ )
61   {
62     duint8 rec = fileBuf->getRawChar8();
63     duint32 address = fileBuf->getRawLong32();
64     duint32 size = fileBuf->getRawLong32();
65     dwgSectionInfo si;
66     si.Id = rec;
67     si.size = size;
68     si.address = address;
69     if ( rec == 0 )
70     {
71       QgsDebugMsg( QString( "Section HEADERS address=%1 size=%2" ).arg( address ).arg( size ) );
72       sections[secEnum::HEADER] = si;
73     }
74     else if ( rec == 1 )
75     {
76       QgsDebugMsg( QString( "Section CLASSES address=%1 size=%2" ).arg( address ).arg( size ) );
77       sections[secEnum::CLASSES] = si;
78     }
79     else if ( rec == 2 )
80     {
81       QgsDebugMsg( QString( "Section OBJECTS (handles) address=%1 size=%2" ).arg( address ).arg( size ) );
82       sections[secEnum::HANDLES] = si;
83     }
84     else if ( rec == 3 )
85     {
86       QgsDebugMsg( QString( "Section UNKNOWN address=%1 size=%2" ).arg( address ).arg( size ) );
87       sections[secEnum::UNKNOWNS] = si;
88     }
89     else if ( rec == 4 )
90     {
91       QgsDebugMsg( QString( "Section R14DATA (AcDb::Template) address=%1 size=%2" ).arg( address ).arg( size ) );
92       sections[secEnum::TEMPLATE] = si;
93     }
94     else if ( rec == 5 )
95     {
96       QgsDebugMsg( QString( "Section R14REC5 (AcDb::AuxHeader) address=%1 size=%2" ).arg( address ).arg( size ) );
97       sections[secEnum::AUXHEADER] = si;
98     }
99     else
100     {
101       std::cerr << "\nUnsupported section number\n";
102     }
103   }
104   if ( ! fileBuf->isGood() )
105     return false;
106 
107   QgsDebugMsg( QString( "position after read section locator records=%1, bit are=%2" ).arg( fileBuf->getPosition() ).arg( fileBuf->getBitPos() ) );
108   duint32 ckcrc = fileBuf->crc8( 0, 0, fileBuf->getPosition() );
109   QgsDebugMsg( QString( "file header crc8 0 result=%1" ).arg( ckcrc ) );
110   switch ( count )
111   {
112     case 3:
113       ckcrc = ckcrc ^ 0xA598;
114       break;
115     case 4:
116       ckcrc = ckcrc ^ 0x8101;
117       break;
118     case 5:
119       ckcrc = ckcrc ^ 0x3CC4;
120       break;
121     case 6:
122       ckcrc = ckcrc ^ 0x8461;
123   }
124 
125   int headercrc = fileBuf->getRawShort16();
126   QgsDebugMsg( QString( "file header crc8 xor result=%1, file header CRC=%2" ).arg( ckcrc ).arg( headercrc ) );
127   Q_UNUSED( headercrc );
128 
129   checkSentinel( fileBuf, secEnum::FILEHEADER, false );
130 
131   QgsDebugMsg( QString( "position after read file header sentinel=%1, bit pos=%2" ).arg( fileBuf->getPosition() ).arg( fileBuf->getBitPos() ) );
132 
133   QgsDebugMsg( "Leaving." );
134 
135   return ret;
136 }
137 
readDwgHeader(DRW_Header & hdr)138 bool dwgReader15::readDwgHeader( DRW_Header &hdr )
139 {
140   QgsDebugMsg( "Entering." );
141 
142   dwgSectionInfo si = sections[secEnum::HEADER];
143   if ( si.Id < 0 )//not found, ends
144     return false;
145   if ( !fileBuf->setPosition( si.address ) )
146     return false;
147   duint8 *tmpByteStr = new duint8[si.size];
148   fileBuf->getBytes( tmpByteStr, si.size );
149   dwgBuffer buff( tmpByteStr, si.size, &decoder );
150 
151   QgsDebugMsg( "checksentinel" );
152   checkSentinel( &buff, secEnum::HEADER, true );
153   bool ret = dwgReader::readDwgHeader( hdr, &buff, &buff );
154   delete[]tmpByteStr;
155   return ret;
156 }
157 
158 
readDwgClasses()159 bool dwgReader15::readDwgClasses()
160 {
161   QgsDebugMsg( "Entering." );
162 
163   dwgSectionInfo si = sections[secEnum::CLASSES];
164   if ( si.Id < 0 )//not found, ends
165     return false;
166   if ( !fileBuf->setPosition( si.address ) )
167     return false;
168 
169   QgsDebugMsg( "classes section sentinel" );
170   checkSentinel( fileBuf, secEnum::CLASSES, true );
171 
172   duint32 size = fileBuf->getRawLong32();
173   if ( size != ( si.size - 38 ) )
174   {
175     QgsDebugMsg( QString( "size is %1 and secSize - 38 are %1" ).arg( size ).arg( si.size - 38 ) );
176   }
177   duint8 *tmpByteStr = new duint8[size];
178   fileBuf->getBytes( tmpByteStr, size );
179   dwgBuffer buff( tmpByteStr, size, &decoder );
180   size--; //reduce 1 byte instead of check pos + bitPos
181   while ( size > buff.getPosition() )
182   {
183     DRW_Class *cl = new DRW_Class();
184     cl->parseDwg( version, &buff, &buff );
185     classesmap[cl->classNum] = cl;
186   }
187   int crc = fileBuf->getRawShort16();
188   QgsDebugMsg( QString( "crc=%1, classes section end sentinel" ).arg( crc ) );
189   Q_UNUSED( crc );
190 
191   checkSentinel( fileBuf, secEnum::CLASSES, false );
192 
193   bool ret = buff.isGood();
194   delete[]tmpByteStr;
195   return ret;
196 }
197 
readDwgHandles()198 bool dwgReader15::readDwgHandles()
199 {
200   QgsDebugMsg( "Entering." );
201   dwgSectionInfo si = sections[secEnum::HANDLES];
202   if ( si.Id < 0 )//not found, ends
203     return false;
204 
205   bool ret = dwgReader::readDwgHandles( fileBuf, si.address, si.size );
206   return ret;
207 }
208 
209 /*********** objects ************************/
210 
211 /**
212  * Reads all the object referenced in the object map section of the DWG file
213  * (using their object file offsets)
214  */
readDwgTables(DRW_Header & hdr)215 bool dwgReader15::readDwgTables( DRW_Header &hdr )
216 {
217   bool ret = dwgReader::readDwgTables( hdr, fileBuf );
218 
219   return ret;
220 }
221 
222 /**
223  * Reads all the object referenced in the object map section of the DWG file
224  * (using their object file offsets)
225  */
readDwgBlocks(DRW_Interface & intfa)226 bool dwgReader15::readDwgBlocks( DRW_Interface &intfa )
227 {
228   bool ret = true;
229   ret = dwgReader::readDwgBlocks( intfa, fileBuf );
230   return ret;
231 }
232 
233