1 /*******************************************************************************
2  *  Project: libopencad
3  *  Purpose: OpenSource CAD formats support library
4  *  Author: Alexandr Borzykh, mush3d at gmail.com
5  *  Author: Dmitry Baryshnikov, bishop.dev@gmail.com
6  *  Language: C++
7  *******************************************************************************
8  *  The MIT License (MIT)
9  *
10  *  Copyright (c) 2016 Alexandr Borzykh
11  *  Copyright (c) 2016-2018 NextGIS, <info@nextgis.com>
12  *
13  *  Permission is hereby granted, free of charge, to any person obtaining a copy
14  *  of this software and associated documentation files (the "Software"), to deal
15  *  in the Software without restriction, including without limitation the rights
16  *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17  *  copies of the Software, and to permit persons to whom the Software is
18  *  furnished to do so, subject to the following conditions:
19  *
20  *  The above copyright notice and this permission notice shall be included in all
21  *  copies or substantial portions of the Software.
22  *
23  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24  *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26  *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28  *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29  *  SOFTWARE.
30  *******************************************************************************/
31 #include "cadgeometry.h"
32 #include "cadobjects.h"
33 #include "opencad_api.h"
34 #include "r2000.h"
35 
36 #include <cassert>
37 #include <cstring>
38 #include <iostream>
39 #include <limits>
40 #include <memory>
41 #include <string>
42 
43 #if ((defined(__sun__) || defined(__FreeBSD__)) && __GNUC__ == 4 && __GNUC_MINOR__ == 8) || defined(__ANDROID__)
44 // gcc 4.8 on Solaris 11.3 or FreeBSD 11 doesn't have std::string
45 #include <sstream>
46 namespace std
47 {
to_string(T val)48 template <typename T> std::string to_string(T val)
49 {
50     std::ostringstream os;
51     os << val;
52     return os.str();
53 }
54 }
55 #endif
56 
57 #define UNKNOWN1 CADHeader::MAX_HEADER_CONSTANT + 1
58 #define UNKNOWN2 CADHeader::MAX_HEADER_CONSTANT + 2
59 #define UNKNOWN3 CADHeader::MAX_HEADER_CONSTANT + 3
60 #define UNKNOWN4 CADHeader::MAX_HEADER_CONSTANT + 4
61 #define UNKNOWN5 CADHeader::MAX_HEADER_CONSTANT + 5
62 #define UNKNOWN6 CADHeader::MAX_HEADER_CONSTANT + 6
63 #define UNKNOWN7 CADHeader::MAX_HEADER_CONSTANT + 7
64 #define UNKNOWN8 CADHeader::MAX_HEADER_CONSTANT + 8
65 #define UNKNOWN9 CADHeader::MAX_HEADER_CONSTANT + 9
66 #define UNKNOWN10 CADHeader::MAX_HEADER_CONSTANT + 10
67 #define UNKNOWN11 CADHeader::MAX_HEADER_CONSTANT + 11
68 #define UNKNOWN12 CADHeader::MAX_HEADER_CONSTANT + 12
69 #define UNKNOWN13 CADHeader::MAX_HEADER_CONSTANT + 13
70 #define UNKNOWN14 CADHeader::MAX_HEADER_CONSTANT + 14
71 #define UNKNOWN15 CADHeader::MAX_HEADER_CONSTANT + 15
72 
73 using namespace std;
74 
ReadHeader(OpenOptions eOptions)75 int DWGFileR2000::ReadHeader( OpenOptions eOptions )
76 {
77     char bufferPre[255];
78     unsigned dHeaderVarsSectionLength = 0;
79     constexpr size_t dSizeOfSectionSize = sizeof(dHeaderVarsSectionLength);
80 
81     pFileIO->Seek( sectionLocatorRecords[0].dSeeker, CADFileIO::SeekOrigin::BEG );
82     size_t readSize = pFileIO->Read( bufferPre, DWGConstants::SentinelLength );
83     if(readSize < DWGConstants::SentinelLength)
84     {
85         DebugMsg( "File is corrupted (size is less than sentinel length)" );
86 
87         return CADErrorCodes::HEADER_SECTION_READ_FAILED;
88     }
89 
90 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
91     if( memcmp( bufferPre, DWGConstants::HeaderVariablesStart,
92                            DWGConstants::SentinelLength ) )
93     {
94         DebugMsg( "File is corrupted (wrong pointer to HEADER_VARS section,"
95                           "or HEADERVARS starting sentinel corrupted.)" );
96 
97         return CADErrorCodes::HEADER_SECTION_READ_FAILED;
98     }
99 #endif
100 
101     readSize = pFileIO->Read( &dHeaderVarsSectionLength, dSizeOfSectionSize );
102     const auto dHeaderVarsSectionLengthOriginal = dHeaderVarsSectionLength;
103     FromLSB(dHeaderVarsSectionLength);
104     DebugMsg( "Header variables section length: %d\n",
105               static_cast<int>(dHeaderVarsSectionLength) );
106     if(readSize != dSizeOfSectionSize || dHeaderVarsSectionLength > 65536) //NOTE: maybe header section may be bigger
107     {
108         DebugMsg( "File is corrupted (HEADER_VARS section length too big)" );
109         return CADErrorCodes::HEADER_SECTION_READ_FAILED;
110     }
111 
112     CADBuffer buffer(dHeaderVarsSectionLength + dSizeOfSectionSize + 10);
113     buffer.WriteRAW(&dHeaderVarsSectionLengthOriginal, dSizeOfSectionSize);
114     readSize = pFileIO->Read(buffer.GetRawBuffer(), dHeaderVarsSectionLength + 2 );
115     if(readSize != dHeaderVarsSectionLength + 2)
116     {
117         DebugMsg( "Failed to read %d byte of file. Read only %d",
118                   static_cast<int>(dHeaderVarsSectionLength + 2),
119                   static_cast<int>(readSize) );
120         return CADErrorCodes::HEADER_SECTION_READ_FAILED;
121     }
122 
123     if( eOptions == OpenOptions::READ_ALL )
124     {
125         oHeader.addValue( UNKNOWN1, buffer.ReadBITDOUBLE() );
126         oHeader.addValue( UNKNOWN2, buffer.ReadBITDOUBLE() );
127         oHeader.addValue( UNKNOWN3, buffer.ReadBITDOUBLE() );
128         oHeader.addValue( UNKNOWN4, buffer.ReadBITDOUBLE() );
129         oHeader.addValue( UNKNOWN5, buffer.ReadTV() );
130         oHeader.addValue( UNKNOWN6, buffer.ReadTV() );
131         oHeader.addValue( UNKNOWN7, buffer.ReadTV() );
132         oHeader.addValue( UNKNOWN8, buffer.ReadTV() );
133         oHeader.addValue( UNKNOWN9, buffer.ReadBITLONG() );
134         oHeader.addValue( UNKNOWN10, buffer.ReadBITLONG() );
135     }
136     else
137     {
138         buffer.SkipBITDOUBLE();
139         buffer.SkipBITDOUBLE();
140         buffer.SkipBITDOUBLE();
141         buffer.SkipBITDOUBLE();
142         buffer.SkipTV();
143         buffer.SkipTV();
144         buffer.SkipTV();
145         buffer.SkipTV();
146         buffer.SkipBITLONG();
147         buffer.SkipBITLONG();
148     }
149 
150     CADHandle stCurrentViewportTable = buffer.ReadHANDLE();
151     oTables.AddTable( CADTables::CurrentViewportTable, stCurrentViewportTable );
152 
153     if( eOptions == OpenOptions::READ_ALL )
154     {
155         oHeader.addValue( CADHeader::DIMASO, buffer.ReadBIT() );     // 1
156         oHeader.addValue( CADHeader::DIMSHO, buffer.ReadBIT() );     // 2
157         oHeader.addValue( CADHeader::PLINEGEN, buffer.ReadBIT() );   // 3
158         oHeader.addValue( CADHeader::ORTHOMODE, buffer.ReadBIT() );  // 4
159         oHeader.addValue( CADHeader::REGENMODE, buffer.ReadBIT() );  // 5
160         oHeader.addValue( CADHeader::FILLMODE, buffer.ReadBIT() );   // 6
161         oHeader.addValue( CADHeader::QTEXTMODE, buffer.ReadBIT() );  // 7
162         oHeader.addValue( CADHeader::PSLTSCALE, buffer.ReadBIT() );  // 8
163         oHeader.addValue( CADHeader::LIMCHECK, buffer.ReadBIT() );   // 9
164         oHeader.addValue( CADHeader::USRTIMER, buffer.ReadBIT() );   // 10
165         oHeader.addValue( CADHeader::SKPOLY, buffer.ReadBIT() );     // 11
166         oHeader.addValue( CADHeader::ANGDIR, buffer.ReadBIT() );     // 12
167         oHeader.addValue( CADHeader::SPLFRAME, buffer.ReadBIT() );   // 13
168         oHeader.addValue( CADHeader::MIRRTEXT, buffer.ReadBIT() );   // 14
169         oHeader.addValue( CADHeader::WORDLVIEW, buffer.ReadBIT() );  // 15
170         oHeader.addValue( CADHeader::TILEMODE, buffer.ReadBIT() );   // 16
171         oHeader.addValue( CADHeader::PLIMCHECK, buffer.ReadBIT() );  // 17
172         oHeader.addValue( CADHeader::VISRETAIN, buffer.ReadBIT() );  // 18
173         oHeader.addValue( CADHeader::DISPSILH, buffer.ReadBIT() );   // 19
174         oHeader.addValue( CADHeader::PELLIPSE, buffer.ReadBIT() );   // 20
175     }
176     else
177     {
178         buffer.Seek(20);
179     }
180 
181     if( eOptions == OpenOptions::READ_ALL )
182     {
183         oHeader.addValue( CADHeader::PROXYGRAPHICS, buffer.ReadBITSHORT() ); // 1
184         oHeader.addValue( CADHeader::TREEDEPTH, buffer.ReadBITSHORT() );     // 2
185         oHeader.addValue( CADHeader::LUNITS, buffer.ReadBITSHORT() );        // 3
186         oHeader.addValue( CADHeader::LUPREC, buffer.ReadBITSHORT() );        // 4
187         oHeader.addValue( CADHeader::AUNITS, buffer.ReadBITSHORT() );        // 5
188         oHeader.addValue( CADHeader::AUPREC, buffer.ReadBITSHORT() );        // 6
189     } else
190     {
191         for( char i = 0; i < 6; ++i )
192             buffer.SkipBITSHORT();
193     }
194 
195     oHeader.addValue( CADHeader::ATTMODE, buffer.ReadBITSHORT() );
196     oHeader.addValue( CADHeader::PDMODE, buffer.ReadBITSHORT() );
197 
198     if( eOptions == OpenOptions::READ_ALL )
199     {
200         oHeader.addValue( CADHeader::USERI1, buffer.ReadBITSHORT() );    // 1
201         oHeader.addValue( CADHeader::USERI2, buffer.ReadBITSHORT() );    // 2
202         oHeader.addValue( CADHeader::USERI3, buffer.ReadBITSHORT() );    // 3
203         oHeader.addValue( CADHeader::USERI4, buffer.ReadBITSHORT() );    // 4
204         oHeader.addValue( CADHeader::USERI5, buffer.ReadBITSHORT() );    // 5
205         oHeader.addValue( CADHeader::SPLINESEGS, buffer.ReadBITSHORT() );// 6
206         oHeader.addValue( CADHeader::SURFU, buffer.ReadBITSHORT() );     // 7
207         oHeader.addValue( CADHeader::SURFV, buffer.ReadBITSHORT() );     // 8
208         oHeader.addValue( CADHeader::SURFTYPE, buffer.ReadBITSHORT() );  // 9
209         oHeader.addValue( CADHeader::SURFTAB1, buffer.ReadBITSHORT() );  // 10
210         oHeader.addValue( CADHeader::SURFTAB2, buffer.ReadBITSHORT() );  // 11
211         oHeader.addValue( CADHeader::SPLINETYPE, buffer.ReadBITSHORT() );// 12
212         oHeader.addValue( CADHeader::SHADEDGE, buffer.ReadBITSHORT() );  // 13
213         oHeader.addValue( CADHeader::SHADEDIF, buffer.ReadBITSHORT() );  // 14
214         oHeader.addValue( CADHeader::UNITMODE, buffer.ReadBITSHORT() );  // 15
215         oHeader.addValue( CADHeader::MAXACTVP, buffer.ReadBITSHORT() );  // 16
216         oHeader.addValue( CADHeader::ISOLINES, buffer.ReadBITSHORT() );  // 17
217         oHeader.addValue( CADHeader::CMLJUST, buffer.ReadBITSHORT() );   // 18
218         oHeader.addValue( CADHeader::TEXTQLTY, buffer.ReadBITSHORT() );  // 19
219     }
220     else
221     {
222         for( char i = 0; i < 19; ++i )
223             buffer.SkipBITSHORT();
224     }
225 
226     oHeader.addValue( CADHeader::LTSCALE, buffer.ReadBITDOUBLE() );
227     oHeader.addValue( CADHeader::TEXTSIZE, buffer.ReadBITDOUBLE() );
228     oHeader.addValue( CADHeader::TRACEWID, buffer.ReadBITDOUBLE() );
229     oHeader.addValue( CADHeader::SKETCHINC, buffer.ReadBITDOUBLE() );
230     oHeader.addValue( CADHeader::FILLETRAD, buffer.ReadBITDOUBLE() );
231     oHeader.addValue( CADHeader::THICKNESS, buffer.ReadBITDOUBLE() );
232     oHeader.addValue( CADHeader::ANGBASE, buffer.ReadBITDOUBLE() );
233     oHeader.addValue( CADHeader::PDSIZE, buffer.ReadBITDOUBLE() );
234     oHeader.addValue( CADHeader::PLINEWID, buffer.ReadBITDOUBLE() );
235 
236     if( eOptions == OpenOptions::READ_ALL )
237     {
238         oHeader.addValue( CADHeader::USERR1, buffer.ReadBITDOUBLE() );   // 1
239         oHeader.addValue( CADHeader::USERR2, buffer.ReadBITDOUBLE() );   // 2
240         oHeader.addValue( CADHeader::USERR3, buffer.ReadBITDOUBLE() );   // 3
241         oHeader.addValue( CADHeader::USERR4, buffer.ReadBITDOUBLE() );   // 4
242         oHeader.addValue( CADHeader::USERR5, buffer.ReadBITDOUBLE() );   // 5
243         oHeader.addValue( CADHeader::CHAMFERA, buffer.ReadBITDOUBLE() ); // 6
244         oHeader.addValue( CADHeader::CHAMFERB, buffer.ReadBITDOUBLE() ); // 7
245         oHeader.addValue( CADHeader::CHAMFERC, buffer.ReadBITDOUBLE() ); // 8
246         oHeader.addValue( CADHeader::CHAMFERD, buffer.ReadBITDOUBLE() ); // 9
247         oHeader.addValue( CADHeader::FACETRES, buffer.ReadBITDOUBLE() ); // 10
248         oHeader.addValue( CADHeader::CMLSCALE, buffer.ReadBITDOUBLE() ); // 11
249         oHeader.addValue( CADHeader::CELTSCALE, buffer.ReadBITDOUBLE() );// 12
250 
251         oHeader.addValue( CADHeader::MENU, buffer.ReadTV() );
252     } else
253     {
254         for( char i = 0; i < 12; ++i )
255             buffer.SkipBITDOUBLE();
256         buffer.SkipTV();
257     }
258 
259     long juliandate, millisec;
260     juliandate = buffer.ReadBITLONG();
261     millisec   = buffer.ReadBITLONG();
262     oHeader.addValue( CADHeader::TDCREATE, juliandate, millisec );
263     juliandate = buffer.ReadBITLONG();
264     millisec   = buffer.ReadBITLONG();
265     oHeader.addValue( CADHeader::TDUPDATE, juliandate, millisec );
266     juliandate = buffer.ReadBITLONG();
267     millisec   = buffer.ReadBITLONG();
268     oHeader.addValue( CADHeader::TDINDWG, juliandate, millisec );
269     juliandate = buffer.ReadBITLONG();
270     millisec   = buffer.ReadBITLONG();
271     oHeader.addValue( CADHeader::TDUSRTIMER, juliandate, millisec );
272 
273     oHeader.addValue( CADHeader::CECOLOR, buffer.ReadBITSHORT() );
274 
275     oHeader.addValue( CADHeader::HANDSEED, buffer.ReadHANDLE() );
276 
277     oHeader.addValue( CADHeader::CLAYER, buffer.ReadHANDLE() );
278     oHeader.addValue( CADHeader::TEXTSTYLE, buffer.ReadHANDLE() );
279     oHeader.addValue( CADHeader::CELTYPE, buffer.ReadHANDLE() );
280     oHeader.addValue( CADHeader::DIMSTYLE, buffer.ReadHANDLE() );
281     oHeader.addValue( CADHeader::CMLSTYLE, buffer.ReadHANDLE() );
282 
283     oHeader.addValue( CADHeader::PSVPSCALE, buffer.ReadBITDOUBLE() );
284     double dX, dY, dZ;
285     dX = buffer.ReadBITDOUBLE();
286     dY = buffer.ReadBITDOUBLE();
287     dZ = buffer.ReadBITDOUBLE();
288     oHeader.addValue( CADHeader::PINSBASE, dX, dY, dZ );
289 
290     dX = buffer.ReadBITDOUBLE();
291     dY = buffer.ReadBITDOUBLE();
292     dZ = buffer.ReadBITDOUBLE();
293     oHeader.addValue( CADHeader::PEXTMIN, dX, dY, dZ );
294     dX = buffer.ReadBITDOUBLE();
295     dY = buffer.ReadBITDOUBLE();
296     dZ = buffer.ReadBITDOUBLE();
297     oHeader.addValue( CADHeader::PEXTMAX, dX, dY, dZ );
298     dX = buffer.ReadRAWDOUBLE();
299     dY = buffer.ReadRAWDOUBLE();
300     oHeader.addValue( CADHeader::PLIMMIN, dX, dY );
301     dX = buffer.ReadRAWDOUBLE();
302     dY = buffer.ReadRAWDOUBLE();
303     oHeader.addValue( CADHeader::PLIMMAX, dX, dY );
304 
305     oHeader.addValue( CADHeader::PELEVATION, buffer.ReadBITDOUBLE() );
306 
307     dX = buffer.ReadBITDOUBLE();
308     dY = buffer.ReadBITDOUBLE();
309     dZ = buffer.ReadBITDOUBLE();
310     oHeader.addValue( CADHeader::PUCSORG, dX, dY, dZ );
311     dX = buffer.ReadBITDOUBLE();
312     dY = buffer.ReadBITDOUBLE();
313     dZ = buffer.ReadBITDOUBLE();
314     oHeader.addValue( CADHeader::PUCSXDIR, dX, dY, dZ );
315     dX = buffer.ReadBITDOUBLE();
316     dY = buffer.ReadBITDOUBLE();
317     dZ = buffer.ReadBITDOUBLE();
318     oHeader.addValue( CADHeader::PUCSYDIR, dX, dY, dZ );
319 
320     oHeader.addValue( CADHeader::PUCSNAME, buffer.ReadHANDLE() );
321     oHeader.addValue( CADHeader::PUCSORTHOREF, buffer.ReadHANDLE() );
322 
323     oHeader.addValue( CADHeader::PUCSORTHOVIEW, buffer.ReadBITSHORT() );
324     oHeader.addValue( CADHeader::PUCSBASE, buffer.ReadHANDLE() );
325 
326     dX = buffer.ReadBITDOUBLE();
327     dY = buffer.ReadBITDOUBLE();
328     dZ = buffer.ReadBITDOUBLE();
329     oHeader.addValue( CADHeader::PUCSORGTOP, dX, dY, dZ );
330     dX = buffer.ReadBITDOUBLE();
331     dY = buffer.ReadBITDOUBLE();
332     dZ = buffer.ReadBITDOUBLE();
333     oHeader.addValue( CADHeader::PUCSORGBOTTOM, dX, dY, dZ );
334     dX = buffer.ReadBITDOUBLE();
335     dY = buffer.ReadBITDOUBLE();
336     dZ = buffer.ReadBITDOUBLE();
337     oHeader.addValue( CADHeader::PUCSORGLEFT, dX, dY, dZ );
338     dX = buffer.ReadBITDOUBLE();
339     dY = buffer.ReadBITDOUBLE();
340     dZ = buffer.ReadBITDOUBLE();
341     oHeader.addValue( CADHeader::PUCSORGRIGHT, dX, dY, dZ );
342     dX = buffer.ReadBITDOUBLE();
343     dY = buffer.ReadBITDOUBLE();
344     dZ = buffer.ReadBITDOUBLE();
345     oHeader.addValue( CADHeader::PUCSORGFRONT, dX, dY, dZ );
346     dX = buffer.ReadBITDOUBLE();
347     dY = buffer.ReadBITDOUBLE();
348     dZ = buffer.ReadBITDOUBLE();
349     oHeader.addValue( CADHeader::PUCSORGBACK, dX, dY, dZ );
350 
351     dX = buffer.ReadBITDOUBLE();
352     dY = buffer.ReadBITDOUBLE();
353     dZ = buffer.ReadBITDOUBLE();
354     oHeader.addValue( CADHeader::INSBASE, dX, dY, dZ );
355     dX = buffer.ReadBITDOUBLE();
356     dY = buffer.ReadBITDOUBLE();
357     dZ = buffer.ReadBITDOUBLE();
358     oHeader.addValue( CADHeader::EXTMIN, dX, dY, dZ );
359     dX = buffer.ReadBITDOUBLE();
360     dY = buffer.ReadBITDOUBLE();
361     dZ = buffer.ReadBITDOUBLE();
362     oHeader.addValue( CADHeader::EXTMAX, dX, dY, dZ );
363     dX = buffer.ReadRAWDOUBLE();
364     dY = buffer.ReadRAWDOUBLE();
365     oHeader.addValue( CADHeader::LIMMIN, dX, dY );
366     dX = buffer.ReadRAWDOUBLE();
367     dY = buffer.ReadRAWDOUBLE();
368     oHeader.addValue( CADHeader::LIMMAX, dX, dY );
369 
370     oHeader.addValue( CADHeader::ELEVATION, buffer.ReadBITDOUBLE() );
371     dX = buffer.ReadBITDOUBLE();
372     dY = buffer.ReadBITDOUBLE();
373     dZ = buffer.ReadBITDOUBLE();
374     oHeader.addValue( CADHeader::UCSORG, dX, dY, dZ );
375     dX = buffer.ReadBITDOUBLE();
376     dY = buffer.ReadBITDOUBLE();
377     dZ = buffer.ReadBITDOUBLE();
378     oHeader.addValue( CADHeader::UCSXDIR, dX, dY, dZ );
379     dX = buffer.ReadBITDOUBLE();
380     dY = buffer.ReadBITDOUBLE();
381     dZ = buffer.ReadBITDOUBLE();
382     oHeader.addValue( CADHeader::UCSYDIR, dX, dY, dZ );
383 
384     oHeader.addValue( CADHeader::UCSNAME, buffer.ReadHANDLE() );
385     oHeader.addValue( CADHeader::UCSORTHOREF, buffer.ReadHANDLE() );
386 
387     oHeader.addValue( CADHeader::UCSORTHOVIEW, buffer.ReadBITSHORT() );
388 
389     oHeader.addValue( CADHeader::UCSBASE, buffer.ReadHANDLE() );
390 
391     dX = buffer.ReadBITDOUBLE();
392     dY = buffer.ReadBITDOUBLE();
393     dZ = buffer.ReadBITDOUBLE();
394     oHeader.addValue( CADHeader::UCSORGTOP, dX, dY, dZ );
395     dX = buffer.ReadBITDOUBLE();
396     dY = buffer.ReadBITDOUBLE();
397     dZ = buffer.ReadBITDOUBLE();
398     oHeader.addValue( CADHeader::UCSORGBOTTOM, dX, dY, dZ );
399     dX = buffer.ReadBITDOUBLE();
400     dY = buffer.ReadBITDOUBLE();
401     dZ = buffer.ReadBITDOUBLE();
402     oHeader.addValue( CADHeader::UCSORGLEFT, dX, dY, dZ );
403     dX = buffer.ReadBITDOUBLE();
404     dY = buffer.ReadBITDOUBLE();
405     dZ = buffer.ReadBITDOUBLE();
406     oHeader.addValue( CADHeader::UCSORGRIGHT, dX, dY, dZ );
407     dX = buffer.ReadBITDOUBLE();
408     dY = buffer.ReadBITDOUBLE();
409     dZ = buffer.ReadBITDOUBLE();
410     oHeader.addValue( CADHeader::UCSORGFRONT, dX, dY, dZ );
411     dX = buffer.ReadBITDOUBLE();
412     dY = buffer.ReadBITDOUBLE();
413     dZ = buffer.ReadBITDOUBLE();
414     oHeader.addValue( CADHeader::UCSORGBACK, dX, dY, dZ );
415 
416     if( eOptions == OpenOptions::READ_ALL )
417     {
418         oHeader.addValue( CADHeader::DIMPOST, buffer.ReadTV() );
419         oHeader.addValue( CADHeader::DIMAPOST, buffer.ReadTV() );
420 
421         oHeader.addValue( CADHeader::DIMSCALE, buffer.ReadBITDOUBLE() ); // 1
422         oHeader.addValue( CADHeader::DIMASZ, buffer.ReadBITDOUBLE() );   // 2
423         oHeader.addValue( CADHeader::DIMEXO, buffer.ReadBITDOUBLE() );   // 3
424         oHeader.addValue( CADHeader::DIMDLI, buffer.ReadBITDOUBLE() );   // 4
425         oHeader.addValue( CADHeader::DIMEXE, buffer.ReadBITDOUBLE() );   // 5
426         oHeader.addValue( CADHeader::DIMRND, buffer.ReadBITDOUBLE() );   // 6
427         oHeader.addValue( CADHeader::DIMDLE, buffer.ReadBITDOUBLE() );   // 7
428         oHeader.addValue( CADHeader::DIMTP, buffer.ReadBITDOUBLE() );    // 8
429         oHeader.addValue( CADHeader::DIMTM, buffer.ReadBITDOUBLE() );    // 9
430 
431         oHeader.addValue( CADHeader::DIMTOL, buffer.ReadBIT() );
432         oHeader.addValue( CADHeader::DIMLIM, buffer.ReadBIT() );
433         oHeader.addValue( CADHeader::DIMTIH, buffer.ReadBIT() );
434         oHeader.addValue( CADHeader::DIMTOH, buffer.ReadBIT() );
435         oHeader.addValue( CADHeader::DIMSE1, buffer.ReadBIT() );
436         oHeader.addValue( CADHeader::DIMSE2, buffer.ReadBIT() );
437 
438         oHeader.addValue( CADHeader::DIMTAD, buffer.ReadBITSHORT() );
439         oHeader.addValue( CADHeader::DIMZIN, buffer.ReadBITSHORT() );
440         oHeader.addValue( CADHeader::DIMAZIN, buffer.ReadBITSHORT() );
441 
442         oHeader.addValue( CADHeader::DIMTXT, buffer.ReadBITDOUBLE() );   // 1
443         oHeader.addValue( CADHeader::DIMCEN, buffer.ReadBITDOUBLE() );   // 2
444         oHeader.addValue( CADHeader::DIMTSZ, buffer.ReadBITDOUBLE() );   // 3
445         oHeader.addValue( CADHeader::DIMALTF, buffer.ReadBITDOUBLE() );  // 4
446         oHeader.addValue( CADHeader::DIMLFAC, buffer.ReadBITDOUBLE() );  // 5
447         oHeader.addValue( CADHeader::DIMTVP, buffer.ReadBITDOUBLE() );   // 6
448         oHeader.addValue( CADHeader::DIMTFAC, buffer.ReadBITDOUBLE() );  // 7
449         oHeader.addValue( CADHeader::DIMGAP, buffer.ReadBITDOUBLE() );   // 8
450         oHeader.addValue( CADHeader::DIMALTRND, buffer.ReadBITDOUBLE() );// 9
451 
452         oHeader.addValue( CADHeader::DIMALT, buffer.ReadBIT() );
453 
454         oHeader.addValue( CADHeader::DIMALTD, buffer.ReadBITSHORT() );
455 
456         oHeader.addValue( CADHeader::DIMTOFL, buffer.ReadBIT() );
457         oHeader.addValue( CADHeader::DIMSAH, buffer.ReadBIT() );
458         oHeader.addValue( CADHeader::DIMTIX, buffer.ReadBIT() );
459         oHeader.addValue( CADHeader::DIMSOXD, buffer.ReadBIT() );
460 
461         oHeader.addValue( CADHeader::DIMCLRD, buffer.ReadBITSHORT() );   // 1
462         oHeader.addValue( CADHeader::DIMCLRE, buffer.ReadBITSHORT() );   // 2
463         oHeader.addValue( CADHeader::DIMCLRT, buffer.ReadBITSHORT() );   // 3
464         oHeader.addValue( CADHeader::DIMADEC, buffer.ReadBITSHORT() );   // 4
465         oHeader.addValue( CADHeader::DIMDEC, buffer.ReadBITSHORT() );    // 5
466         oHeader.addValue( CADHeader::DIMTDEC, buffer.ReadBITSHORT() );   // 6
467         oHeader.addValue( CADHeader::DIMALTU, buffer.ReadBITSHORT() );   // 7
468         oHeader.addValue( CADHeader::DIMALTTD, buffer.ReadBITSHORT() );  // 8
469         oHeader.addValue( CADHeader::DIMAUNIT, buffer.ReadBITSHORT() );  // 9
470         oHeader.addValue( CADHeader::DIMFRAC, buffer.ReadBITSHORT() );   // 10
471         oHeader.addValue( CADHeader::DIMLUNIT, buffer.ReadBITSHORT() );  // 11
472         oHeader.addValue( CADHeader::DIMDSEP, buffer.ReadBITSHORT() );   // 12
473         oHeader.addValue( CADHeader::DIMTMOVE, buffer.ReadBITSHORT() );  // 13
474         oHeader.addValue( CADHeader::DIMJUST, buffer.ReadBITSHORT() );   // 14
475 
476         oHeader.addValue( CADHeader::DIMSD1, buffer.ReadBIT() );
477         oHeader.addValue( CADHeader::DIMSD2, buffer.ReadBIT() );
478 
479         oHeader.addValue( CADHeader::DIMTOLJ, buffer.ReadBITSHORT() );
480         oHeader.addValue( CADHeader::DIMTZIN, buffer.ReadBITSHORT() );
481         oHeader.addValue( CADHeader::DIMALTZ, buffer.ReadBITSHORT() );
482         oHeader.addValue( CADHeader::DIMALTTZ, buffer.ReadBITSHORT() );
483 
484         oHeader.addValue( CADHeader::DIMUPT, buffer.ReadBIT() );
485 
486         oHeader.addValue( CADHeader::DIMATFIT, buffer.ReadBITSHORT() );
487 
488         oHeader.addValue( CADHeader::DIMTXSTY, buffer.ReadHANDLE() );
489         oHeader.addValue( CADHeader::DIMLDRBLK, buffer.ReadHANDLE() );
490         oHeader.addValue( CADHeader::DIMBLK, buffer.ReadHANDLE() );
491         oHeader.addValue( CADHeader::DIMBLK1, buffer.ReadHANDLE() );
492         oHeader.addValue( CADHeader::DIMBLK2, buffer.ReadHANDLE() );
493 
494         oHeader.addValue( CADHeader::DIMLWD, buffer.ReadBITSHORT() );
495         oHeader.addValue( CADHeader::DIMLWE, buffer.ReadBITSHORT() );
496     } else
497     {
498         buffer.SkipTV();
499         buffer.SkipTV();
500 
501         for( char i = 0; i < 9; ++i )
502             buffer.SkipBITDOUBLE();
503 
504         buffer.Seek(6);
505 
506         for( char i = 0; i < 3; ++i )
507             buffer.SkipBITSHORT();
508 
509         for( char i = 0; i < 9; ++i )
510             buffer.SkipBITDOUBLE();
511 
512         buffer.Seek(1);
513 
514         buffer.SkipBITSHORT();
515 
516         buffer.Seek(4);
517 
518         for( char i = 0; i < 14; ++i )
519             buffer.SkipBITSHORT();
520 
521         buffer.Seek(2);
522 
523         for( char i = 0; i < 4; ++i )
524             buffer.SkipBITSHORT();
525 
526         buffer.Seek(1);
527         buffer.SkipBITSHORT();
528 
529         for( char i = 0; i < 5; ++i )
530             buffer.SkipHANDLE();
531 
532         buffer.SkipBITSHORT();
533         buffer.SkipBITSHORT();
534     }
535 
536     CADHandle stBlocksTable = buffer.ReadHANDLE();
537     oTables.AddTable( CADTables::BlocksTable, stBlocksTable );
538 
539     CADHandle stLayersTable = buffer.ReadHANDLE();
540     oTables.AddTable( CADTables::LayersTable, stLayersTable );
541 
542     CADHandle stStyleTable = buffer.ReadHANDLE();
543     oTables.AddTable( CADTables::StyleTable, stStyleTable );
544 
545     CADHandle stLineTypesTable = buffer.ReadHANDLE();
546     oTables.AddTable( CADTables::LineTypesTable, stLineTypesTable );
547 
548     CADHandle stViewTable = buffer.ReadHANDLE();
549     oTables.AddTable( CADTables::ViewTable, stViewTable );
550 
551     CADHandle stUCSTable = buffer.ReadHANDLE();
552     oTables.AddTable( CADTables::UCSTable, stUCSTable );
553 
554     CADHandle stViewportTable = buffer.ReadHANDLE();
555     oTables.AddTable( CADTables::ViewportTable, stViewportTable );
556 
557     CADHandle stAPPIDTable = buffer.ReadHANDLE();
558     oTables.AddTable( CADTables::APPIDTable, stAPPIDTable );
559 
560     if( eOptions == OpenOptions::READ_ALL )
561     {
562         oHeader.addValue( CADHeader::DIMSTYLE, buffer.ReadHANDLE() );
563     }
564     else
565     {
566         buffer.SkipHANDLE();
567     }
568 
569     CADHandle stEntityTable = buffer.ReadHANDLE();
570     oTables.AddTable( CADTables::EntityTable, stEntityTable );
571 
572     CADHandle stACADGroupDict = buffer.ReadHANDLE();
573     oTables.AddTable( CADTables::ACADGroupDict, stACADGroupDict );
574 
575     CADHandle stACADMLineStyleDict = buffer.ReadHANDLE();
576     oTables.AddTable( CADTables::ACADMLineStyleDict, stACADMLineStyleDict );
577 
578     CADHandle stNamedObjectsDict = buffer.ReadHANDLE();
579     oTables.AddTable( CADTables::NamedObjectsDict, stNamedObjectsDict );
580 
581     if( eOptions == OpenOptions::READ_ALL )
582     {
583         oHeader.addValue( CADHeader::TSTACKALIGN, buffer.ReadBITSHORT() );
584         oHeader.addValue( CADHeader::TSTACKSIZE,  buffer.ReadBITSHORT() );
585     } else
586     {
587         buffer.SkipBITSHORT();
588         buffer.SkipBITSHORT();
589     }
590 
591     oHeader.addValue( CADHeader::HYPERLINKBASE, buffer.ReadTV() );
592     oHeader.addValue( CADHeader::STYLESHEET, buffer.ReadTV() );
593 
594     CADHandle stLayoutsDict = buffer.ReadHANDLE();
595     oTables.AddTable( CADTables::LayoutsDict, stLayoutsDict );
596 
597     CADHandle stPlotSettingsDict = buffer.ReadHANDLE();
598     oTables.AddTable( CADTables::PlotSettingsDict, stPlotSettingsDict );
599 
600     CADHandle stPlotStylesDict = buffer.ReadHANDLE();
601     oTables.AddTable( CADTables::PlotStylesDict, stPlotStylesDict );
602 
603     if( eOptions == OpenOptions::READ_ALL )
604     {
605         int Flags = buffer.ReadBITLONG();
606         oHeader.addValue( CADHeader::CELWEIGHT, Flags & 0x001F );
607         oHeader.addValue( CADHeader::ENDCAPS, ( Flags & 0x0060 ) != 0 );
608         oHeader.addValue( CADHeader::JOINSTYLE, (Flags & 0x0180) != 0);
609         oHeader.addValue( CADHeader::LWDISPLAY, ( Flags & 0x0200 ) == 0);
610         oHeader.addValue( CADHeader::XEDIT, ( Flags & 0x0400 ) == 0);
611         oHeader.addValue( CADHeader::EXTNAMES, ( Flags & 0x0800 ) != 0 );
612         oHeader.addValue( CADHeader::PSTYLEMODE, ( Flags & 0x2000 ) != 0 );
613         oHeader.addValue( CADHeader::OLESTARTUP, ( Flags & 0x4000 ) != 0);
614     }
615     else
616     {
617         buffer.SkipBITLONG();
618     }
619 
620     oHeader.addValue( CADHeader::INSUNITS, buffer.ReadBITSHORT() );
621     short nCEPSNTYPE = buffer.ReadBITSHORT();
622     oHeader.addValue( CADHeader::CEPSNTYPE, nCEPSNTYPE );
623 
624     if( nCEPSNTYPE == 3 )
625         oHeader.addValue( CADHeader::CEPSNID, buffer.ReadHANDLE() );
626 
627     oHeader.addValue( CADHeader::FINGERPRINTGUID, buffer.ReadTV() );
628     oHeader.addValue( CADHeader::VERSIONGUID, buffer.ReadTV() );
629 
630     CADHandle stBlockRecordPaperSpace = buffer.ReadHANDLE();
631     oTables.AddTable( CADTables::BlockRecordPaperSpace, stBlockRecordPaperSpace );
632     // TODO: is this part of the header?
633     CADHandle stBlockRecordModelSpace = buffer.ReadHANDLE();
634     oTables.AddTable( CADTables::BlockRecordModelSpace, stBlockRecordModelSpace );
635 
636     if( eOptions == OpenOptions::READ_ALL )
637     {
638         // Is this part of the header?
639 
640         /*CADHandle LTYPE_BYLAYER = */buffer.ReadHANDLE();
641         /*CADHandle LTYPE_BYBLOCK = */buffer.ReadHANDLE();
642         /*CADHandle LTYPE_CONTINUOUS = */buffer.ReadHANDLE();
643 
644         oHeader.addValue( UNKNOWN11, buffer.ReadBITSHORT() );
645         oHeader.addValue( UNKNOWN12, buffer.ReadBITSHORT() );
646         oHeader.addValue( UNKNOWN13, buffer.ReadBITSHORT() );
647         oHeader.addValue( UNKNOWN14, buffer.ReadBITSHORT() );
648     } else
649     {
650         buffer.SkipHANDLE();
651         buffer.SkipHANDLE();
652         buffer.SkipHANDLE();
653         buffer.SkipBITSHORT();
654         buffer.SkipBITSHORT();
655         buffer.SkipBITSHORT();
656         buffer.SkipBITSHORT();
657     }
658 
659     int returnCode = CADErrorCodes::SUCCESS;
660     unsigned short dSectionCRC = validateEntityCRC( buffer,
661         static_cast<unsigned int>(dHeaderVarsSectionLength + dSizeOfSectionSize), "HEADERVARS" );
662 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
663     (void)dSectionCRC;
664 #else
665     if(dSectionCRC == 0)
666     {
667         std::cerr << "File is corrupted (HEADERVARS section CRC doesn't match.)\n";
668         return CADErrorCodes::HEADER_SECTION_READ_FAILED;
669     }
670 #endif
671     pFileIO->Read( bufferPre, DWGConstants::SentinelLength );
672 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
673     if( memcmp( bufferPre, DWGConstants::HeaderVariablesEnd,
674                          DWGConstants::SentinelLength ) )
675     {
676         std::cerr << "File is corrupted (HEADERVARS section ending sentinel "
677                           "doesn't match.)\n";
678         returnCode = CADErrorCodes::HEADER_SECTION_READ_FAILED;
679     }
680 #endif
681     return returnCode;
682 }
683 
ReadClasses(enum OpenOptions eOptions)684 int DWGFileR2000::ReadClasses( enum OpenOptions eOptions )
685 {
686     if( eOptions == OpenOptions::READ_ALL || eOptions == OpenOptions::READ_FAST )
687     {
688         char   bufferPre[255];
689         unsigned dSectionSize = 0;
690         constexpr size_t dSizeOfSectionSize = sizeof(dSectionSize);
691 
692         pFileIO->Seek( sectionLocatorRecords[1].dSeeker, CADFileIO::SeekOrigin::BEG );
693 
694         pFileIO->Read( bufferPre, DWGConstants::SentinelLength );
695 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
696         if( memcmp( bufferPre, DWGConstants::DSClassesStart,
697                                DWGConstants::SentinelLength ) )
698         {
699             std::cerr << "File is corrupted (wrong pointer to CLASSES section,"
700                     "or CLASSES starting sentinel corrupted.)\n";
701 
702             return CADErrorCodes::CLASSES_SECTION_READ_FAILED;
703         }
704 #endif
705 
706         pFileIO->Read( &dSectionSize, dSizeOfSectionSize );
707         const auto dSectionSizeOriginal = dSectionSize;
708         FromLSB(dSectionSize);
709         DebugMsg("Classes section length: %d\n",
710                   static_cast<int>(dSectionSize) );
711         if(dSectionSize > 65535) {
712             DebugMsg("File is corrupted (CLASSES section is too large: %d\n",
713                      static_cast<int>(dSectionSize));
714 
715             return CADErrorCodes::CLASSES_SECTION_READ_FAILED;
716         }
717 
718         CADBuffer buffer(dSectionSize + dSizeOfSectionSize + 10);
719         buffer.WriteRAW(&dSectionSizeOriginal, dSizeOfSectionSize);
720         size_t readSize = pFileIO->Read( buffer.GetRawBuffer(), dSectionSize + 2 );
721         if(readSize != dSectionSize + 2)
722         {
723             DebugMsg( "Failed to read %d byte of file. Read only %d",
724                       static_cast<int>(dSectionSize + 2),
725                       static_cast<int>(readSize) );
726             return CADErrorCodes::CLASSES_SECTION_READ_FAILED;
727         }
728 
729         const size_t dSectionBitSize = (dSectionSize + dSizeOfSectionSize) * 8;
730         while( buffer.PositionBit() < dSectionBitSize - 8)
731         {
732             CADClass stClass;
733             stClass.dClassNum        = buffer.ReadBITSHORT();
734             stClass.dProxyCapFlag    = buffer.ReadBITSHORT();
735             stClass.sApplicationName = buffer.ReadTV();
736             stClass.sCppClassName    = buffer.ReadTV();
737             stClass.sDXFRecordName   = buffer.ReadTV();
738             stClass.bWasZombie       = buffer.ReadBIT();
739             stClass.bIsEntity        = buffer.ReadBITSHORT() == 0x1F2;
740 
741             oClasses.addClass( stClass );
742         }
743 
744         buffer.Seek(dSectionBitSize, CADBuffer::BEG);
745         unsigned short dSectionCRC = validateEntityCRC( buffer,
746                     static_cast<unsigned int>(dSectionSize + dSizeOfSectionSize),
747                                                         "CLASSES" );
748 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
749         (void)dSectionCRC;
750 #else
751         if(dSectionCRC == 0)
752         {
753             std::cerr << "File is corrupted (CLASSES section CRC doesn't match.)\n";
754             return CADErrorCodes::CLASSES_SECTION_READ_FAILED;
755         }
756 #endif
757 
758         pFileIO->Read( bufferPre, DWGConstants::SentinelLength );
759 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
760         if( memcmp( bufferPre, DWGConstants::DSClassesEnd,
761                                DWGConstants::SentinelLength ) )
762         {
763             std::cerr << "File is corrupted (CLASSES section ending sentinel "
764                     "doesn't match.)\n";
765             return CADErrorCodes::CLASSES_SECTION_READ_FAILED;
766         }
767 #endif
768     }
769     return CADErrorCodes::SUCCESS;
770 }
771 
CreateFileMap()772 int DWGFileR2000::CreateFileMap()
773 {
774     size_t nSection = 0;
775 
776     typedef pair<long, long> ObjHandleOffset;
777     ObjHandleOffset          previousObjHandleOffset;
778     ObjHandleOffset          tmpOffset;
779 
780     mapObjects.clear();
781 
782     // Seek to the beginning of the objects map
783     pFileIO->Seek( sectionLocatorRecords[2].dSeeker, CADFileIO::SeekOrigin::BEG );
784 
785     while( true )
786     {
787         unsigned short dSectionSize = 0;
788         constexpr size_t dSizeOfSectionSize = sizeof(dSectionSize);
789 
790         // Read section size
791 
792         pFileIO->Read( &dSectionSize, dSizeOfSectionSize );
793         const unsigned short dSectionSizeOriginal = dSectionSize;
794 #if !defined(CAD_MSB)
795         SwapEndianness( dSectionSize, sizeof( dSectionSize ) );
796 #endif
797 
798         DebugMsg( "Object map section #%d size: %d\n",
799                   static_cast<int>(++nSection), dSectionSize );
800 
801         if( dSectionSize <= dSizeOfSectionSize )
802             break; // Last section is empty.
803 
804         CADBuffer buffer(dSectionSize + dSizeOfSectionSize + 10);
805         buffer.WriteRAW(&dSectionSizeOriginal, dSizeOfSectionSize);
806         size_t nRecordsInSection   = 0;
807 
808         // Read section datsa
809         size_t readSize = pFileIO->Read( buffer.GetRawBuffer(), dSectionSize );
810         if(readSize != dSectionSize)
811         {
812             DebugMsg( "Failed to read %d byte of file. Read only %d",
813                       static_cast<int>(dSectionSize),
814                       static_cast<int>(readSize) );
815             return CADErrorCodes::OBJECTS_SECTION_READ_FAILED;
816         }
817         unsigned int dSectionBitSize = dSectionSize * 8;
818 
819         while( buffer.PositionBit() < dSectionBitSize )
820         {
821             tmpOffset.first  = buffer.ReadUMCHAR(); // 8 + 8*8
822             tmpOffset.second = buffer.ReadMCHAR(); // 8 + 8*8
823 
824             if( 0 == nRecordsInSection )
825             {
826                 previousObjHandleOffset = tmpOffset;
827             }
828             else
829             {
830                 if( (tmpOffset.first >= 0 &&
831                      std::numeric_limits<long>::max() - tmpOffset.first > previousObjHandleOffset.first) ||
832                     (tmpOffset.first < 0 &&
833                      std::numeric_limits<long>::min() - tmpOffset.first <= previousObjHandleOffset.first) )
834                 {
835                     previousObjHandleOffset.first += tmpOffset.first;
836                 }
837                 if( (tmpOffset.second >= 0 &&
838                      std::numeric_limits<long>::max() - tmpOffset.second > previousObjHandleOffset.second) ||
839                     (tmpOffset.second < 0 &&
840                      std::numeric_limits<long>::min() - tmpOffset.second <= previousObjHandleOffset.second) )
841                 {
842                     previousObjHandleOffset.second += tmpOffset.second;
843                 }
844             }
845 #ifdef _DEBUG
846             assert( mapObjects.find( previousObjHandleOffset.first ) ==
847                                                                 mapObjects.end() );
848 #endif //_DEBUG
849             mapObjects.insert( previousObjHandleOffset );
850             ++nRecordsInSection;
851         }
852 
853         unsigned short dSectionCRC = validateEntityCRC( buffer,
854                     static_cast<unsigned int>(dSectionSize), "OBJECTMAP", true );
855 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
856         (void)dSectionCRC;
857 #else
858         if(dSectionCRC == 0)
859         {
860             std::cerr << "File is corrupted (OBJECTMAP section CRC doesn't match.)\n";
861             return CADErrorCodes::OBJECTS_SECTION_READ_FAILED;
862         }
863 #endif
864     }
865 
866     return CADErrorCodes::SUCCESS;
867 }
868 
GetObject(long dHandle,bool bHandlesOnly)869 CADObject * DWGFileR2000::GetObject( long dHandle, bool bHandlesOnly )
870 {
871     CADBuffer buffer(8);
872 
873     pFileIO->Seek( mapObjects[dHandle], CADFileIO::SeekOrigin::BEG );
874     pFileIO->Read( buffer.GetRawBuffer(), 8 );
875     unsigned int dObjectSize = buffer.ReadMSHORT();
876 
877     // FIXME: Limit object size to 64kB
878     if( dObjectSize > 65536 )
879         return nullptr;
880 
881     // And read whole data chunk into memory for future parsing.
882     // + nBitOffsetFromStart/8 + 2 is because dObjectSize doesn't cover CRC and itself.
883     dObjectSize += static_cast<unsigned int>(buffer.PositionBit() / 8 + 2);
884 
885     CADBuffer objectBuffer(dObjectSize + 64);
886 
887     pFileIO->Seek( mapObjects[dHandle], CADFileIO::SeekOrigin::BEG );
888     size_t readSize = pFileIO->Read( objectBuffer.GetRawBuffer(),
889                                      static_cast<size_t>(dObjectSize) );
890     if(readSize != static_cast<size_t>(dObjectSize))
891     {
892         DebugMsg( "Failed to read %d byte of file. Read only %d",
893                   static_cast<int>(dObjectSize),
894                   static_cast<int>(readSize) );
895         return nullptr;
896     }
897 
898     /* Unused dObjectSize = */ objectBuffer.ReadMSHORT();
899     short dObjectType = objectBuffer.ReadBITSHORT();
900     if( dObjectType >= 500 )
901     {
902         CADClass cadClass = oClasses.getClassByNum( dObjectType );
903         // FIXME: replace strcmp() with C++ analog
904         if( !strcmp( cadClass.sCppClassName.c_str(), "AcDbRasterImage" ) )
905         {
906             dObjectType = CADObject::IMAGE;
907         }
908         else if( !strcmp( cadClass.sCppClassName.c_str(), "AcDbRasterImageDef" ) )
909         {
910             dObjectType = CADObject::IMAGEDEF;
911         }
912         else if( !strcmp( cadClass.sCppClassName.c_str(), "AcDbRasterImageDefReactor" ) )
913         {
914             dObjectType = CADObject::IMAGEDEFREACTOR;
915         }
916         else if( !strcmp( cadClass.sCppClassName.c_str(), "AcDbWipeout" ) )
917         {
918             dObjectType = CADObject::WIPEOUT;
919         }
920     }
921 
922     // Entities handling
923     if( isCommonEntityType( dObjectType ) )
924     {
925         struct CADCommonED stCommonEntityData; // Common for all entities
926 
927         stCommonEntityData.nObjectSizeInBits = objectBuffer.ReadRAWLONG();
928         stCommonEntityData.hObjectHandle     = objectBuffer.ReadHANDLE();
929 
930         short  dEEDSize;
931         CADEed dwgEed;
932         while( ( dEEDSize = objectBuffer.ReadBITSHORT() ) != 0 )
933         {
934             dwgEed.dLength      = dEEDSize;
935             dwgEed.hApplication = objectBuffer.ReadHANDLE();
936 
937             if(dEEDSize < 0)
938             {
939                 return nullptr;
940             }
941 
942             for( short i = 0; i < dEEDSize; ++i )
943             {
944                 dwgEed.acData.push_back( objectBuffer.ReadCHAR() );
945             }
946 
947             stCommonEntityData.aEED.push_back( dwgEed );
948         }
949 
950         stCommonEntityData.bGraphicsPresented = objectBuffer.ReadBIT();
951         if( stCommonEntityData.bGraphicsPresented )
952         {
953             const auto rawLong = objectBuffer.ReadRAWLONG();
954             if( rawLong < 0 )
955                 return nullptr;
956             size_t nGraphicsDataSize = static_cast<size_t>(rawLong);
957             if( nGraphicsDataSize > std::numeric_limits<size_t>::max() / 8 )
958                 return nullptr;
959             // Skip read graphics data
960             buffer.Seek(nGraphicsDataSize * 8);
961         }
962         stCommonEntityData.bbEntMode        = objectBuffer.Read2B();
963         stCommonEntityData.nNumReactors     = objectBuffer.ReadBITLONG();
964         if(stCommonEntityData.nNumReactors < 0 ||
965            stCommonEntityData.nNumReactors > 5000)
966         {
967             return nullptr;
968         }
969         stCommonEntityData.bNoLinks         = objectBuffer.ReadBIT();
970         stCommonEntityData.nCMColor         = objectBuffer.ReadBITSHORT();
971         stCommonEntityData.dfLTypeScale     = objectBuffer.ReadBITDOUBLE();
972         stCommonEntityData.bbLTypeFlags     = objectBuffer.Read2B();
973         stCommonEntityData.bbPlotStyleFlags = objectBuffer.Read2B();
974         stCommonEntityData.nInvisibility    = objectBuffer.ReadBITSHORT();
975         stCommonEntityData.nLineWeight      = objectBuffer.ReadCHAR();
976 
977         // Skip entitity-specific data, we don't need it if bHandlesOnly == true
978         if( bHandlesOnly == true )
979         {
980             return getEntity( dObjectType, dObjectSize, stCommonEntityData, objectBuffer);
981         }
982 
983         switch( dObjectType )
984         {
985             case CADObject::BLOCK:
986                 return getBlock( dObjectSize, stCommonEntityData, objectBuffer);
987 
988             case CADObject::ELLIPSE:
989                 return getEllipse( dObjectSize, stCommonEntityData, objectBuffer);
990 
991             case CADObject::MLINE:
992                 return getMLine( dObjectSize, stCommonEntityData, objectBuffer);
993 
994             case CADObject::SOLID:
995                 return getSolid( dObjectSize, stCommonEntityData, objectBuffer);
996 
997             case CADObject::POINT:
998                 return getPoint( dObjectSize, stCommonEntityData, objectBuffer);
999 
1000             case CADObject::POLYLINE3D:
1001                 return getPolyLine3D( dObjectSize, stCommonEntityData, objectBuffer);
1002 
1003             case CADObject::RAY:
1004                 return getRay( dObjectSize, stCommonEntityData, objectBuffer);
1005 
1006             case CADObject::XLINE:
1007                 return getXLine( dObjectSize, stCommonEntityData, objectBuffer);
1008 
1009             case CADObject::LINE:
1010                 return getLine( dObjectSize, stCommonEntityData, objectBuffer);
1011 
1012             case CADObject::TEXT:
1013                 return getText( dObjectSize, stCommonEntityData, objectBuffer);
1014 
1015             case CADObject::VERTEX3D:
1016                 return getVertex3D( dObjectSize, stCommonEntityData, objectBuffer);
1017 
1018             case CADObject::CIRCLE:
1019                 return getCircle( dObjectSize, stCommonEntityData, objectBuffer);
1020 
1021             case CADObject::ENDBLK:
1022                 return getEndBlock( dObjectSize, stCommonEntityData, objectBuffer);
1023 
1024             case CADObject::POLYLINE2D:
1025                 return getPolyline2D( dObjectSize, stCommonEntityData, objectBuffer);
1026 
1027             case CADObject::ATTRIB:
1028                 return getAttributes( dObjectSize, stCommonEntityData, objectBuffer);
1029 
1030             case CADObject::ATTDEF:
1031                 return getAttributesDefn( dObjectSize, stCommonEntityData, objectBuffer);
1032 
1033             case CADObject::LWPOLYLINE:
1034                 return getLWPolyLine( dObjectSize, stCommonEntityData, objectBuffer);
1035 
1036             case CADObject::ARC:
1037                 return getArc( dObjectSize, stCommonEntityData, objectBuffer);
1038 
1039             case CADObject::SPLINE:
1040                 return getSpline( dObjectSize, stCommonEntityData, objectBuffer);
1041 
1042             case CADObject::POLYLINE_PFACE:
1043                 return getPolylinePFace( dObjectSize, stCommonEntityData, objectBuffer);
1044 
1045             case CADObject::IMAGE:
1046                 return getImage( dObjectSize, stCommonEntityData, objectBuffer);
1047 
1048             case CADObject::FACE3D:
1049                 return get3DFace( dObjectSize, stCommonEntityData, objectBuffer);
1050 
1051             case CADObject::VERTEX_MESH:
1052                 return getVertexMesh( dObjectSize, stCommonEntityData, objectBuffer);
1053 
1054             case CADObject::VERTEX_PFACE:
1055                 return getVertexPFace( dObjectSize, stCommonEntityData,
1056                                        objectBuffer);
1057 
1058             case CADObject::MTEXT:
1059                 return getMText( dObjectSize, stCommonEntityData,
1060                                  objectBuffer);
1061 
1062             case CADObject::DIMENSION_RADIUS:
1063             case CADObject::DIMENSION_DIAMETER:
1064             case CADObject::DIMENSION_ALIGNED:
1065             case CADObject::DIMENSION_ANG_3PT:
1066             case CADObject::DIMENSION_ANG_2LN:
1067             case CADObject::DIMENSION_ORDINATE:
1068             case CADObject::DIMENSION_LINEAR:
1069                 return getDimension( dObjectType, dObjectSize, stCommonEntityData,
1070                                      objectBuffer);
1071 
1072             case CADObject::INSERT:
1073                 return getInsert( dObjectType, dObjectSize, stCommonEntityData,
1074                                   objectBuffer);
1075 
1076             default:
1077                 return getEntity( dObjectType, dObjectSize, stCommonEntityData,
1078                                   objectBuffer);
1079         }
1080     }
1081     else
1082     {
1083         switch( dObjectType )
1084         {
1085             case CADObject::DICTIONARY:
1086                 return getDictionary( dObjectSize, objectBuffer);
1087 
1088             case CADObject::LAYER:
1089                 return getLayerObject( dObjectSize, objectBuffer);
1090 
1091             case CADObject::LAYER_CONTROL_OBJ:
1092                 return getLayerControl( dObjectSize, objectBuffer);
1093 
1094             case CADObject::BLOCK_CONTROL_OBJ:
1095                 return getBlockControl( dObjectSize, objectBuffer);
1096 
1097             case CADObject::BLOCK_HEADER:
1098                 return getBlockHeader( dObjectSize, objectBuffer);
1099 
1100             case CADObject::LTYPE_CONTROL_OBJ:
1101                 return getLineTypeControl( dObjectSize, objectBuffer);
1102 
1103             case CADObject::LTYPE1:
1104                 return getLineType1( dObjectSize, objectBuffer);
1105 
1106             case CADObject::IMAGEDEF:
1107                 return getImageDef( dObjectSize, objectBuffer);
1108 
1109             case CADObject::IMAGEDEFREACTOR:
1110                 return getImageDefReactor( dObjectSize, objectBuffer);
1111 
1112             case CADObject::XRECORD:
1113                 return getXRecord( dObjectSize, objectBuffer);
1114         }
1115     }
1116 
1117     return nullptr;
1118 }
1119 
GetGeometry(size_t iLayerIndex,long dHandle,long dBlockRefHandle)1120 CADGeometry * DWGFileR2000::GetGeometry( size_t iLayerIndex, long dHandle, long dBlockRefHandle )
1121 {
1122     CADGeometry * poGeometry = nullptr;
1123     unique_ptr<CADObject> pCADEntityObject( GetObject( dHandle ) );
1124     CADEntityObject* readObject =
1125                 dynamic_cast<CADEntityObject *>( pCADEntityObject.get() );
1126 
1127     if( !readObject )
1128     {
1129         return nullptr;
1130     }
1131 
1132     switch( readObject->getType() )
1133     {
1134         case CADObject::ARC:
1135         {
1136             CADArc * arc = new CADArc();
1137             CADArcObject * cadArc = static_cast<CADArcObject *>(
1138                     readObject);
1139 
1140             arc->setPosition( cadArc->vertPosition );
1141             arc->setExtrusion( cadArc->vectExtrusion );
1142             arc->setRadius( cadArc->dfRadius );
1143             arc->setThickness( cadArc->dfThickness );
1144             arc->setStartingAngle( cadArc->dfStartAngle );
1145             arc->setEndingAngle( cadArc->dfEndAngle );
1146 
1147             poGeometry = arc;
1148             break;
1149         }
1150 
1151         case CADObject::POINT:
1152         {
1153             CADPoint3D * point = new CADPoint3D();
1154             CADPointObject * cadPoint = static_cast<CADPointObject *>(
1155                     readObject);
1156 
1157             point->setPosition( cadPoint->vertPosition );
1158             point->setExtrusion( cadPoint->vectExtrusion );
1159             point->setXAxisAng( cadPoint->dfXAxisAng );
1160             point->setThickness( cadPoint->dfThickness );
1161 
1162             poGeometry = point;
1163             break;
1164         }
1165 
1166         case CADObject::POLYLINE3D:
1167         {
1168             CADPolyline3D * polyline = new CADPolyline3D();
1169             CADPolyline3DObject * cadPolyline3D = static_cast<CADPolyline3DObject *>(
1170                     readObject);
1171 
1172             // TODO: code can be much simplified if CADHandle will be used.
1173             // to do so, == and ++ operators should be implemented.
1174             unique_ptr<CADVertex3DObject> vertex;
1175             long currentVertexH = cadPolyline3D->hVertices[0].getAsLong();
1176             while( currentVertexH != 0 )
1177             {
1178                 CADObject *poCADVertexObject = GetObject( currentVertexH );
1179                 vertex.reset( dynamic_cast<CADVertex3DObject *>( poCADVertexObject ) );
1180 
1181                 if( !vertex )
1182                 {
1183                     delete poCADVertexObject;
1184                     break;
1185                 }
1186 
1187                 currentVertexH = vertex->stCed.hObjectHandle.getAsLong();
1188                 polyline->addVertex( vertex->vertPosition );
1189                 if( vertex->stCed.bNoLinks == true )
1190                 {
1191                     ++currentVertexH;
1192                 }
1193                 else
1194                 {
1195                     currentVertexH = vertex->stChed.hNextEntity.getAsLong(
1196                                 vertex->stCed.hObjectHandle );
1197                 }
1198 
1199                 // Last vertex is reached. Read it and break reading.
1200                 if( currentVertexH == cadPolyline3D->hVertices[1].getAsLong() )
1201                 {
1202                     CADObject *poCADVertex3DObject = GetObject( currentVertexH );
1203                     vertex.reset( dynamic_cast<CADVertex3DObject *>(
1204                                           poCADVertex3DObject) );
1205                     if( vertex)
1206                     {
1207                         polyline->addVertex( vertex->vertPosition );
1208                     }
1209                     else
1210                     {
1211                         delete poCADVertex3DObject;
1212                     }
1213                     break;
1214                 }
1215             }
1216 
1217             poGeometry = polyline;
1218             break;
1219         }
1220 
1221         case CADObject::LWPOLYLINE:
1222         {
1223             CADLWPolyline * lwPolyline = new CADLWPolyline();
1224             CADLWPolylineObject * cadlwPolyline = static_cast<CADLWPolylineObject *>(
1225                     readObject);
1226 
1227             lwPolyline->setBulges( cadlwPolyline->adfBulges );
1228             lwPolyline->setClosed( cadlwPolyline->bClosed );
1229             lwPolyline->setConstWidth( cadlwPolyline->dfConstWidth );
1230             lwPolyline->setElevation( cadlwPolyline->dfElevation );
1231             for( const CADVector& vertex : cadlwPolyline->avertVertices )
1232                 lwPolyline->addVertex( vertex );
1233             lwPolyline->setVectExtrusion( cadlwPolyline->vectExtrusion );
1234             lwPolyline->setWidths( cadlwPolyline->astWidths );
1235 
1236             poGeometry = lwPolyline;
1237             break;
1238         }
1239 
1240         case CADObject::CIRCLE:
1241         {
1242             CADCircle * circle = new CADCircle();
1243             CADCircleObject * cadCircle = static_cast<CADCircleObject *>(
1244                     readObject);
1245 
1246             circle->setPosition( cadCircle->vertPosition );
1247             circle->setExtrusion( cadCircle->vectExtrusion );
1248             circle->setRadius( cadCircle->dfRadius );
1249             circle->setThickness( cadCircle->dfThickness );
1250 
1251             poGeometry = circle;
1252             break;
1253         }
1254 
1255         case CADObject::ATTRIB:
1256         {
1257             CADAttrib * attrib = new CADAttrib();
1258             CADAttribObject * cadAttrib = static_cast<CADAttribObject *>(
1259                     readObject );
1260 
1261             attrib->setPosition( cadAttrib->vertInsetionPoint );
1262             attrib->setExtrusion( cadAttrib->vectExtrusion );
1263             attrib->setRotationAngle( cadAttrib->dfRotationAng );
1264             attrib->setAlignmentPoint( cadAttrib->vertAlignmentPoint );
1265             attrib->setElevation( cadAttrib->dfElevation );
1266             attrib->setHeight( cadAttrib->dfHeight );
1267             attrib->setObliqueAngle( cadAttrib->dfObliqueAng );
1268             attrib->setPositionLocked( cadAttrib->bLockPosition );
1269             attrib->setTag( cadAttrib->sTag );
1270             attrib->setTextValue( cadAttrib->sTextValue );
1271             attrib->setThickness( cadAttrib->dfThickness );
1272 
1273             poGeometry = attrib;
1274             break;
1275         }
1276 
1277         case CADObject::ATTDEF:
1278         {
1279             CADAttdef * attdef = new CADAttdef();
1280             CADAttdefObject * cadAttrib = static_cast<CADAttdefObject*>(
1281                     readObject );
1282 
1283             attdef->setPosition( cadAttrib->vertInsetionPoint );
1284             attdef->setExtrusion( cadAttrib->vectExtrusion );
1285             attdef->setRotationAngle( cadAttrib->dfRotationAng );
1286             attdef->setAlignmentPoint( cadAttrib->vertAlignmentPoint );
1287             attdef->setElevation( cadAttrib->dfElevation );
1288             attdef->setHeight( cadAttrib->dfHeight );
1289             attdef->setObliqueAngle( cadAttrib->dfObliqueAng );
1290             attdef->setPositionLocked( cadAttrib->bLockPosition );
1291             attdef->setTag( cadAttrib->sTag );
1292             attdef->setTextValue( cadAttrib->sTextValue );
1293             attdef->setThickness( cadAttrib->dfThickness );
1294             attdef->setPrompt( cadAttrib->sPrompt );
1295 
1296             poGeometry = attdef;
1297             break;
1298         }
1299 
1300         case CADObject::ELLIPSE:
1301         {
1302             CADEllipse * ellipse = new CADEllipse();
1303             CADEllipseObject * cadEllipse = static_cast<CADEllipseObject *>(
1304                     readObject);
1305 
1306             ellipse->setPosition( cadEllipse->vertPosition );
1307             ellipse->setSMAxis( cadEllipse->vectSMAxis );
1308             ellipse->setAxisRatio( cadEllipse->dfAxisRatio );
1309             ellipse->setEndingAngle( cadEllipse->dfEndAngle );
1310             ellipse->setStartingAngle( cadEllipse->dfBegAngle );
1311 
1312             poGeometry = ellipse;
1313             break;
1314         }
1315 
1316         case CADObject::LINE:
1317         {
1318             CADLineObject * cadLine = static_cast<CADLineObject *>(
1319                     readObject);
1320 
1321             CADPoint3D ptBeg( cadLine->vertStart, cadLine->dfThickness );
1322             CADPoint3D ptEnd( cadLine->vertEnd, cadLine->dfThickness );
1323 
1324             CADLine * line = new CADLine( ptBeg, ptEnd );
1325 
1326             poGeometry = line;
1327             break;
1328         }
1329 
1330         case CADObject::RAY:
1331         {
1332             CADRay * ray = new CADRay();
1333             CADRayObject * cadRay = static_cast<CADRayObject *>(
1334                     readObject);
1335 
1336             ray->setVectVector( cadRay->vectVector );
1337             ray->setPosition( cadRay->vertPosition );
1338 
1339             poGeometry = ray;
1340             break;
1341         }
1342 
1343         case CADObject::SPLINE:
1344         {
1345             CADSpline * spline = new CADSpline();
1346             CADSplineObject * cadSpline = static_cast<CADSplineObject *>(
1347                     readObject);
1348 
1349             spline->setScenario( cadSpline->dScenario );
1350             spline->setDegree( cadSpline->dDegree );
1351             if( spline->getScenario() == 2 )
1352             {
1353                 spline->setFitTolerance( cadSpline->dfFitTol );
1354             }
1355             else if( spline->getScenario() == 1 )
1356             {
1357                 spline->setRational( cadSpline->bRational );
1358                 spline->setClosed( cadSpline->bClosed );
1359                 spline->setWeight( cadSpline->bWeight );
1360             }
1361             for( double weight : cadSpline->adfCtrlPointsWeight )
1362                 spline->addControlPointsWeight( weight );
1363 
1364             for( const CADVector& pt : cadSpline->averFitPoints )
1365                 spline->addFitPoint( pt );
1366 
1367             for( const CADVector& pt : cadSpline->avertCtrlPoints )
1368                 spline->addControlPoint( pt );
1369 
1370             poGeometry = spline;
1371             break;
1372         }
1373 
1374         case CADObject::TEXT:
1375         {
1376             CADText * text = new CADText();
1377             CADTextObject * cadText = static_cast<CADTextObject *>(
1378                     readObject);
1379 
1380             text->setPosition( cadText->vertInsetionPoint );
1381             text->setTextValue( cadText->sTextValue );
1382             text->setRotationAngle( cadText->dfRotationAng );
1383             text->setObliqueAngle( cadText->dfObliqueAng );
1384             text->setThickness( cadText->dfThickness );
1385             text->setHeight( cadText->dfElevation );
1386 
1387             poGeometry = text;
1388             break;
1389         }
1390 
1391         case CADObject::SOLID:
1392         {
1393             CADSolid * solid = new CADSolid();
1394             CADSolidObject * cadSolid = static_cast<CADSolidObject *>(
1395                     readObject);
1396 
1397             solid->setElevation( cadSolid->dfElevation );
1398             solid->setThickness( cadSolid->dfThickness );
1399             for( const CADVector& corner : cadSolid->avertCorners )
1400                 solid->addCorner( corner );
1401             solid->setExtrusion( cadSolid->vectExtrusion );
1402 
1403             poGeometry = solid;
1404             break;
1405         }
1406 
1407         case CADObject::IMAGE:
1408         {
1409             CADImageObject * cadImage = static_cast<CADImageObject *>(
1410                     readObject);
1411 
1412             CADObject *pCADImageDefObject = GetObject( cadImage->hImageDef.getAsLong() );
1413             unique_ptr<CADImageDefObject> cadImageDef(
1414                 dynamic_cast<CADImageDefObject *>( pCADImageDefObject ) );
1415 
1416             if(cadImageDef)
1417             {
1418                 CADImage * image = new CADImage();
1419                 image->setClippingBoundaryType( cadImage->dClipBoundaryType );
1420                 image->setFilePath( cadImageDef->sFilePath );
1421                 image->setVertInsertionPoint( cadImage->vertInsertion );
1422                 CADVector imageSize( cadImage->dfSizeX, cadImage->dfSizeY );
1423                 image->setImageSize( imageSize );
1424                 CADVector imageSizeInPx( cadImageDef->dfXImageSizeInPx, cadImageDef->dfYImageSizeInPx );
1425                 image->setImageSizeInPx( imageSizeInPx );
1426                 CADVector pixelSizeInACADUnits( cadImageDef->dfXPixelSize, cadImageDef->dfYPixelSize );
1427                 image->setPixelSizeInACADUnits( pixelSizeInACADUnits );
1428                 image->setResolutionUnits(
1429                     static_cast<CADImage::ResolutionUnit>( cadImageDef->dResUnits ) );
1430                 bool bTransparency = (cadImage->dDisplayProps & 0x08) != 0;
1431                 image->setOptions( bTransparency,
1432                                    cadImage->bClipping,
1433                                    cadImage->dBrightness,
1434                                    cadImage->dContrast );
1435                 for( const CADVector& clipPt : cadImage->avertClippingPolygonVertices )
1436                 {
1437                     image->addClippingPoint( clipPt );
1438                 }
1439 
1440                 poGeometry = image;
1441             }
1442             else
1443             {
1444                 delete pCADImageDefObject;
1445             }
1446             break;
1447         }
1448 
1449         case CADObject::MLINE:
1450         {
1451             CADMLine * mline = new CADMLine();
1452             CADMLineObject * cadmLine = static_cast<CADMLineObject *>(
1453                     readObject);
1454 
1455             mline->setScale( cadmLine->dfScale );
1456             mline->setOpened( cadmLine->dOpenClosed == 1 ? true : false );
1457             for( const CADMLineVertex& vertex : cadmLine->avertVertices )
1458                 mline->addVertex( vertex.vertPosition );
1459 
1460             poGeometry = mline;
1461             break;
1462         }
1463 
1464         case CADObject::MTEXT:
1465         {
1466             CADMText * mtext = new CADMText();
1467             CADMTextObject * cadmText = static_cast<CADMTextObject *>(
1468                     readObject);
1469 
1470             mtext->setTextValue( cadmText->sTextValue );
1471             mtext->setXAxisAng( cadmText->vectXAxisDir.getX() ); //TODO: is this needed?
1472 
1473             mtext->setPosition( cadmText->vertInsertionPoint );
1474             mtext->setExtrusion( cadmText->vectExtrusion );
1475 
1476             mtext->setHeight( cadmText->dfTextHeight );
1477             mtext->setRectWidth( cadmText->dfRectWidth );
1478             mtext->setExtents( cadmText->dfExtents );
1479             mtext->setExtentsWidth( cadmText->dfExtentsWidth );
1480 
1481             poGeometry = mtext;
1482             break;
1483         }
1484 
1485         case CADObject::POLYLINE_PFACE:
1486         {
1487             CADPolylinePFace * polyline = new CADPolylinePFace();
1488             CADPolylinePFaceObject * cadpolyPface = static_cast<CADPolylinePFaceObject *>(
1489                     readObject);
1490 
1491             // TODO: code can be much simplified if CADHandle will be used.
1492             // to do so, == and ++ operators should be implemented.
1493             unique_ptr<CADVertexPFaceObject> vertex;
1494             auto dCurrentEntHandle = cadpolyPface->hVertices[0].getAsLong();
1495             auto dLastEntHandle = cadpolyPface->hVertices[1].getAsLong();
1496             while( true )
1497             {
1498                 CADObject *pCADVertexPFaceObject = GetObject( dCurrentEntHandle );
1499                 vertex.reset( dynamic_cast<CADVertexPFaceObject *>(
1500                                       pCADVertexPFaceObject ) );
1501                 /* TODO: this check is excessive, but if something goes wrong way -
1502              * some part of geometries will be parsed. */
1503                 if( !vertex )
1504                 {
1505                     delete pCADVertexPFaceObject;
1506                     break;
1507                 }
1508 
1509                 polyline->addVertex( vertex->vertPosition );
1510 
1511                 /* FIXME: somehow one more vertex which isnot presented is read.
1512              * so, checking the number of added vertices */
1513                 /*TODO: is this needed - check on real data
1514             if ( polyline->hVertices.size() == cadpolyPface->nNumVertices )
1515             {
1516                 delete( vertex );
1517                 break;
1518             }*/
1519 
1520                 if( vertex->stCed.bNoLinks )
1521                     ++dCurrentEntHandle;
1522                 else
1523                     dCurrentEntHandle = vertex->stChed.hNextEntity.getAsLong( vertex->stCed.hObjectHandle );
1524 
1525                 if( dCurrentEntHandle == dLastEntHandle )
1526                 {
1527                     CADObject *pCADVertexPFaceObjectV = GetObject( dCurrentEntHandle );
1528                     vertex.reset( dynamic_cast<CADVertexPFaceObject *>(
1529                                           pCADVertexPFaceObjectV) );
1530                     if(vertex)
1531                     {
1532                         polyline->addVertex( vertex->vertPosition );
1533                     }
1534                     else
1535                     {
1536                         delete pCADVertexPFaceObjectV;
1537                     }
1538                     break;
1539                 }
1540             }
1541 
1542             poGeometry = polyline;
1543             break;
1544         }
1545 
1546         case CADObject::XLINE:
1547         {
1548             CADXLine * xline = new CADXLine();
1549             CADXLineObject * cadxLine = static_cast<CADXLineObject *>(
1550                     readObject);
1551 
1552             xline->setVectVector( cadxLine->vectVector );
1553             xline->setPosition( cadxLine->vertPosition );
1554 
1555             poGeometry = xline;
1556             break;
1557         }
1558 
1559         case CADObject::FACE3D:
1560         {
1561             CADFace3D * face = new CADFace3D();
1562             CAD3DFaceObject * cad3DFace = static_cast<CAD3DFaceObject *>(
1563                     readObject);
1564 
1565             for( const CADVector& corner : cad3DFace->avertCorners )
1566                 face->addCorner( corner );
1567             face->setInvisFlags( cad3DFace->dInvisFlags );
1568 
1569             poGeometry = face;
1570             break;
1571         }
1572 
1573         case CADObject::POLYLINE_MESH:
1574         case CADObject::VERTEX_MESH:
1575         case CADObject::VERTEX_PFACE_FACE:
1576         default:
1577             std::cerr << "Asked geometry has unsupported type.\n";
1578             poGeometry = new CADUnknown();
1579             break;
1580     }
1581 
1582     if( poGeometry == nullptr )
1583         return nullptr;
1584 
1585     // Applying color
1586     if( readObject->stCed.nCMColor == 256 ) // BYLAYER CASE
1587     {
1588         CADLayer& oCurrentLayer = this->GetLayer( iLayerIndex );
1589         poGeometry->setColor( getCADACIColor( oCurrentLayer.getColor() ) );
1590     }
1591     else if( readObject->stCed.nCMColor <= 255 &&
1592              readObject->stCed.nCMColor >= 0 ) // Excessive check until BYBLOCK case will not be implemented
1593     {
1594         poGeometry->setColor( getCADACIColor( readObject->stCed.nCMColor ) );
1595     }
1596 
1597     // Applying EED
1598     // Casting object's EED to a vector of strings
1599     vector<string> asEED;
1600     for( auto citer = readObject->stCed.aEED.cbegin();
1601          citer != readObject->stCed.aEED.cend(); ++citer )
1602     {
1603         string sEED = "";
1604         // Detect the type of EED entity
1605         switch( citer->acData[0] )
1606         {
1607             case 0: // String
1608             {
1609                 if( citer->acData.size() > 1 )
1610                 {
1611                     unsigned char nStrSize = citer->acData[1];
1612                     // +2 = skip CodePage, no idea how to use it anyway
1613 
1614                     if(nStrSize > 0)
1615                     {
1616                         for( size_t i = 0; i < nStrSize &&
1617                             i + 4 < citer->acData.size(); ++i )
1618                         {
1619                             sEED += citer->acData[i + 4];
1620                         }
1621                     }
1622                 }
1623                 break;
1624             }
1625             case 1: // Invalid
1626             {
1627                 DebugMsg( "Error: EED obj type is 1, error in R2000::getGeometry()" );
1628                 break;
1629             }
1630             case 2: // { or }
1631             {
1632                 if( citer->acData.size() > 1 )
1633                 {
1634                     sEED += citer->acData[1] == 0 ? '{' : '}';
1635                 }
1636                 break;
1637             }
1638             case 3: // Layer table ref
1639             {
1640                 // FIXME: get CADHandle and return getAsLong() result.
1641                 sEED += "Layer table ref (handle):";
1642                 for( size_t i = 0; i < 8 && i + 1 < citer->acData.size(); ++i )
1643                 {
1644                     sEED += citer->acData[i + 1];
1645                 }
1646                 break;
1647             }
1648             case 4: // Binary chunk
1649             {
1650                 if( citer->acData.size() > 1 )
1651                 {
1652                     unsigned char nChunkSize = citer->acData[1];
1653                     sEED += "Binary chunk (chars):";
1654                     if(nChunkSize > 0)
1655                     {
1656                         for( size_t i = 0; i < nChunkSize &&
1657                             i + 2 < citer->acData.size(); ++i )
1658                         {
1659                             sEED += citer->acData[i + 2];
1660                         }
1661                     }
1662                     else
1663                     {
1664                         sEED += "?";
1665                     }
1666                 }
1667                 break;
1668             }
1669             case 5: // Entity handle ref
1670             {
1671                 // FIXME: Get CADHandle and return getAsLong() result.
1672                 sEED += "Entity handle ref (handle):";
1673                 for( size_t i = 0; i < 8 && i + 1 < citer->acData.size(); ++i )
1674                 {
1675                     sEED += citer->acData[i + 1];
1676                 }
1677                 break;
1678             }
1679             case 10:
1680             case 11:
1681             case 12:
1682             case 13:
1683             {
1684                 sEED += "Point: {";
1685                 double dfX = 0, dfY = 0, dfZ = 0;
1686                 if(citer->acData.size() > 24)
1687                 {
1688                     memcpy( & dfX, citer->acData.data() + 1, 8 );
1689                     memcpy( & dfY, citer->acData.data() + 9, 8 );
1690                     memcpy( & dfZ, citer->acData.data() + 17, 8 );
1691                 }
1692                 sEED += std::to_string( dfX );
1693                 sEED += ';';
1694                 sEED += std::to_string( dfY );
1695                 sEED += ';';
1696                 sEED += std::to_string( dfZ );
1697                 sEED += '}';
1698                 break;
1699             }
1700             case 40:
1701             case 41:
1702             case 42:
1703             {
1704                 sEED += "Double:";
1705                 double dfVal = 0;
1706                 if(citer->acData.size() > 8)
1707                     memcpy( & dfVal, citer->acData.data() + 1, 8 );
1708                 sEED += std::to_string( dfVal );
1709                 break;
1710             }
1711             case 70:
1712             {
1713                 sEED += "Short:";
1714                 int16_t dVal = 0;
1715                 if(citer->acData.size() > 2)
1716                     memcpy( & dVal, citer->acData.data() + 1, 2 );
1717                 sEED += std::to_string( dVal );
1718                 break;
1719             }
1720             case 71:
1721             {
1722                 sEED += "Long Int:";
1723                 int32_t dVal = 0;
1724                 if(citer->acData.size() > 4)
1725                     memcpy( & dVal, citer->acData.data() + 1, 4 );
1726                 sEED += std::to_string( dVal );
1727                 break;
1728             }
1729             default:
1730             {
1731                 DebugMsg( "Error in parsing geometry EED: undefined typecode: %d",
1732                           static_cast<int>(citer->acData[0]) );
1733             }
1734         }
1735         asEED.emplace_back( sEED );
1736     }
1737 
1738     // Getting block reference attributes.
1739     if( dBlockRefHandle != 0 )
1740     {
1741         vector<CADAttrib>           blockRefAttributes;
1742         CADObject *pCADInsertObject = GetObject( dBlockRefHandle );
1743         unique_ptr<CADInsertObject> spoBlockRef(
1744                     dynamic_cast<CADInsertObject *>( pCADInsertObject ) );
1745 
1746         if( spoBlockRef )
1747         {
1748             if( !spoBlockRef->hAttribs.empty() )
1749             {
1750                 long dCurrentEntHandle = spoBlockRef->hAttribs[0].getAsLong();
1751                 long dLastEntHandle    = spoBlockRef->hAttribs[0].getAsLong();
1752 
1753                 while( spoBlockRef->bHasAttribs )
1754                 {
1755                     CADObject *pCADAttDefObj = GetObject( dCurrentEntHandle, true );
1756 
1757                     CADEntityObject * attDefObj =
1758                             dynamic_cast<CADEntityObject *>( pCADAttDefObj );
1759 
1760                     if( dCurrentEntHandle == dLastEntHandle )
1761                     {
1762                         if( attDefObj == nullptr )
1763                         {
1764                             delete pCADAttDefObj;
1765                             break;
1766                         }
1767 
1768                         CADAttrib * attrib = static_cast<CADAttrib *>(
1769                                 GetGeometry( iLayerIndex, dCurrentEntHandle ) );
1770 
1771                         if( attrib )
1772                         {
1773                             blockRefAttributes.push_back( CADAttrib( * attrib ) );
1774                             delete attrib;
1775                         }
1776                         delete attDefObj;
1777                         break;
1778                     }
1779 
1780                     if( attDefObj != nullptr )
1781                     {
1782                         if( attDefObj->stCed.bNoLinks )
1783                             ++dCurrentEntHandle;
1784                         else
1785                             dCurrentEntHandle = attDefObj->stChed.hNextEntity.getAsLong( attDefObj->stCed.hObjectHandle );
1786 
1787                         CADAttrib * attrib = static_cast<CADAttrib *>(
1788                                 GetGeometry( iLayerIndex, dCurrentEntHandle ) );
1789 
1790                         if( attrib )
1791                         {
1792                             blockRefAttributes.push_back( CADAttrib( * attrib ) );
1793                             delete attrib;
1794                         }
1795                         delete attDefObj;
1796                     }
1797                     else
1798                     {
1799                         delete pCADAttDefObj;
1800                     }
1801                 }
1802                 poGeometry->setBlockAttributes( blockRefAttributes );
1803             }
1804         }
1805         else
1806         {
1807             delete pCADInsertObject;
1808         }
1809     }
1810 
1811     poGeometry->setEED( asEED );
1812     return poGeometry;
1813 }
1814 
getBlock(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)1815 CADBlockObject * DWGFileR2000::getBlock(unsigned int dObjectSize,
1816                                         const CADCommonED& stCommonEntityData,
1817                                         CADBuffer &buffer)
1818 {
1819     CADBlockObject * pBlock = new CADBlockObject();
1820 
1821     pBlock->setSize( dObjectSize );
1822     pBlock->stCed = stCommonEntityData;
1823 
1824     pBlock->sBlockName = buffer.ReadTV();
1825 
1826     fillCommonEntityHandleData( pBlock, buffer);
1827 
1828     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
1829     pBlock->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "BLOCK" ) );
1830 
1831     return pBlock;
1832 }
1833 
getEllipse(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)1834 CADEllipseObject * DWGFileR2000::getEllipse(unsigned int dObjectSize,
1835                                             const CADCommonED& stCommonEntityData,
1836                                             CADBuffer& buffer)
1837 {
1838     CADEllipseObject * ellipse = new CADEllipseObject();
1839 
1840     ellipse->setSize( dObjectSize );
1841     ellipse->stCed = stCommonEntityData;
1842 
1843     CADVector vertPosition = buffer.ReadVector();
1844 
1845     ellipse->vertPosition = vertPosition;
1846 
1847     CADVector vectSMAxis = buffer.ReadVector();
1848 
1849     ellipse->vectSMAxis = vectSMAxis;
1850 
1851     CADVector vectExtrusion = buffer.ReadVector();
1852 
1853     ellipse->vectExtrusion = vectExtrusion;
1854 
1855     ellipse->dfAxisRatio = buffer.ReadBITDOUBLE();
1856     ellipse->dfBegAngle  = buffer.ReadBITDOUBLE();
1857     ellipse->dfEndAngle  = buffer.ReadBITDOUBLE();
1858 
1859     fillCommonEntityHandleData(ellipse, buffer);
1860 
1861     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
1862     ellipse->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "ELLIPSE" ) );
1863 
1864     return ellipse;
1865 }
1866 
getSolid(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)1867 CADSolidObject * DWGFileR2000::getSolid(unsigned int dObjectSize,
1868                                         const CADCommonED& stCommonEntityData,
1869                                         CADBuffer &buffer)
1870 {
1871     CADSolidObject * solid = new CADSolidObject();
1872 
1873     solid->setSize( dObjectSize );
1874     solid->stCed = stCommonEntityData;
1875 
1876     solid->dfThickness = buffer.ReadBIT() ? 0.0f : buffer.ReadBITDOUBLE();
1877 
1878     solid->dfElevation = buffer.ReadBITDOUBLE();
1879 
1880     CADVector   oCorner;
1881     for( size_t i = 0; i < 4; ++i )
1882     {
1883         oCorner.setX( buffer.ReadRAWDOUBLE() );
1884         oCorner.setY( buffer.ReadRAWDOUBLE() );
1885         solid->avertCorners.push_back( oCorner );
1886     }
1887 
1888     if( buffer.ReadBIT() )
1889     {
1890         solid->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
1891     }
1892     else
1893     {
1894         CADVector vectExtrusion = buffer.ReadVector();
1895         solid->vectExtrusion = vectExtrusion;
1896     }
1897 
1898 
1899     fillCommonEntityHandleData( solid, buffer);
1900 
1901     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
1902     solid->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "SOLID" ) );
1903 
1904     return solid;
1905 }
1906 
getPoint(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)1907 CADPointObject * DWGFileR2000::getPoint(unsigned int dObjectSize,
1908                                         const CADCommonED& stCommonEntityData,
1909                                         CADBuffer& buffer)
1910 {
1911     CADPointObject * point = new CADPointObject();
1912 
1913     point->setSize( dObjectSize );
1914     point->stCed = stCommonEntityData;
1915 
1916     CADVector vertPosition = buffer.ReadVector();
1917 
1918     point->vertPosition = vertPosition;
1919 
1920     point->dfThickness = buffer.ReadBIT() ? 0.0f : buffer.ReadBITDOUBLE();
1921 
1922     if( buffer.ReadBIT() )
1923     {
1924         point->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
1925     }
1926     else
1927     {
1928         CADVector vectExtrusion = buffer.ReadVector();
1929         point->vectExtrusion = vectExtrusion;
1930     }
1931 
1932     point->dfXAxisAng = buffer.ReadBITDOUBLE();
1933 
1934     fillCommonEntityHandleData( point, buffer);
1935 
1936     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
1937     point->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "POINT" ) );
1938 
1939     return point;
1940 }
1941 
getPolyLine3D(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)1942 CADPolyline3DObject * DWGFileR2000::getPolyLine3D(unsigned int dObjectSize,
1943                                                   const CADCommonED& stCommonEntityData,
1944                                                   CADBuffer &buffer)
1945 {
1946     CADPolyline3DObject * polyline = new CADPolyline3DObject();
1947 
1948     polyline->setSize( dObjectSize );
1949     polyline->stCed = stCommonEntityData;
1950 
1951     polyline->SplinedFlags = buffer.ReadCHAR();
1952     polyline->ClosedFlags  = buffer.ReadCHAR();
1953 
1954     fillCommonEntityHandleData( polyline, buffer );
1955 
1956     polyline->hVertices.push_back( buffer.ReadHANDLE() ); // 1st vertex
1957     polyline->hVertices.push_back( buffer.ReadHANDLE() ); // last vertex
1958 
1959     polyline->hSeqend = buffer.ReadHANDLE();
1960 
1961     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
1962     polyline->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "POLYLINE" ) );
1963 
1964     return polyline;
1965 }
1966 
getRay(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)1967 CADRayObject * DWGFileR2000::getRay(unsigned int dObjectSize,
1968                                     const CADCommonED& stCommonEntityData,
1969                                     CADBuffer &buffer)
1970 {
1971     CADRayObject * ray = new CADRayObject();
1972 
1973     ray->setSize( dObjectSize );
1974     ray->stCed = stCommonEntityData;
1975 
1976     CADVector vertPosition = buffer.ReadVector();
1977 
1978     ray->vertPosition = vertPosition;
1979 
1980     CADVector vectVector = buffer.ReadVector();
1981     ray->vectVector = vectVector;
1982 
1983     fillCommonEntityHandleData( ray, buffer);
1984 
1985     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
1986     ray->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "RAY" ) );
1987 
1988     return ray;
1989 }
1990 
getXLine(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)1991 CADXLineObject * DWGFileR2000::getXLine(unsigned int dObjectSize,
1992                                         const CADCommonED& stCommonEntityData,
1993                                         CADBuffer &buffer)
1994 {
1995     CADXLineObject * xline = new CADXLineObject();
1996 
1997     xline->setSize( dObjectSize );
1998     xline->stCed = stCommonEntityData;
1999 
2000     CADVector vertPosition = buffer.ReadVector();
2001 
2002     xline->vertPosition = vertPosition;
2003 
2004     CADVector vectVector = buffer.ReadVector();
2005     xline->vectVector = vectVector;
2006 
2007     fillCommonEntityHandleData( xline, buffer);
2008 
2009     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2010     xline->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "XLINE" ) );
2011 
2012     return xline;
2013 }
2014 
getLine(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)2015 CADLineObject * DWGFileR2000::getLine(unsigned int dObjectSize,
2016                                       const CADCommonED& stCommonEntityData,
2017                                       CADBuffer &buffer)
2018 {
2019     CADLineObject * line = new CADLineObject();
2020 
2021     line->setSize( dObjectSize );
2022     line->stCed = stCommonEntityData;
2023 
2024     bool bZsAreZeros = buffer.ReadBIT();
2025 
2026     CADVector vertStart, vertEnd;
2027     vertStart.setX( buffer.ReadRAWDOUBLE() );
2028     vertEnd.setX( buffer.ReadBITDOUBLEWD(vertStart.getX() ) );
2029     vertStart.setY( buffer.ReadRAWDOUBLE() );
2030     vertEnd.setY( buffer.ReadBITDOUBLEWD(vertStart.getY() ) );
2031 
2032     if( !bZsAreZeros )
2033     {
2034         vertStart.setZ( buffer.ReadBITDOUBLE() );
2035         vertEnd.setZ( buffer.ReadBITDOUBLEWD(vertStart.getZ() ) );
2036     }
2037 
2038     line->vertStart = vertStart;
2039     line->vertEnd   = vertEnd;
2040 
2041     line->dfThickness = buffer.ReadBIT() ? 0.0f : buffer.ReadBITDOUBLE();
2042 
2043     if( buffer.ReadBIT() )
2044     {
2045         line->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
2046     } else
2047     {
2048         CADVector vectExtrusion = buffer.ReadVector();
2049         line->vectExtrusion = vectExtrusion;
2050     }
2051 
2052     fillCommonEntityHandleData( line, buffer);
2053 
2054     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2055     line->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "LINE" ) );
2056     return line;
2057 }
2058 
getText(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)2059 CADTextObject * DWGFileR2000::getText(unsigned int dObjectSize,
2060                                       const CADCommonED& stCommonEntityData,
2061                                       CADBuffer &buffer)
2062 {
2063     CADTextObject * text = new CADTextObject();
2064 
2065     text->setSize( dObjectSize );
2066     text->stCed = stCommonEntityData;
2067 
2068     text->DataFlags = buffer.ReadCHAR();
2069 
2070     if( !( text->DataFlags & 0x01 ) )
2071     {
2072         text->dfElevation = buffer.ReadRAWDOUBLE();
2073     }
2074 
2075     CADVector vertInsetionPoint = buffer.ReadRAWVector();
2076 
2077     text->vertInsetionPoint = vertInsetionPoint;
2078 
2079     if( !( text->DataFlags & 0x02 ) )
2080     {
2081         double x, y;
2082         x = buffer.ReadBITDOUBLEWD(vertInsetionPoint.getX() );
2083         y = buffer.ReadBITDOUBLEWD(vertInsetionPoint.getY() );
2084         CADVector vertAlignmentPoint( x, y );
2085         text->vertAlignmentPoint = vertAlignmentPoint;
2086     }
2087 
2088     if( buffer.ReadBIT() )
2089     {
2090         text->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
2091     }
2092     else
2093     {
2094         CADVector vectExtrusion = buffer.ReadVector();
2095         text->vectExtrusion = vectExtrusion;
2096     }
2097 
2098     text->dfThickness = buffer.ReadBIT() ? 0.0f : buffer.ReadBITDOUBLE();
2099 
2100     if( !( text->DataFlags & 0x04 ) )
2101         text->dfObliqueAng  = buffer.ReadRAWDOUBLE();
2102     if( !( text->DataFlags & 0x08 ) )
2103         text->dfRotationAng = buffer.ReadRAWDOUBLE();
2104 
2105     text->dfHeight = buffer.ReadRAWDOUBLE();
2106 
2107     if( !( text->DataFlags & 0x10 ) )
2108         text->dfWidthFactor = buffer.ReadRAWDOUBLE();
2109 
2110     text->sTextValue = buffer.ReadTV();
2111 
2112     if( !( text->DataFlags & 0x20 ) )
2113         text->dGeneration = buffer.ReadBITSHORT();
2114     if( !( text->DataFlags & 0x40 ) )
2115         text->dHorizAlign = buffer.ReadBITSHORT();
2116     if( !( text->DataFlags & 0x80 ) )
2117         text->dVertAlign  = buffer.ReadBITSHORT();
2118 
2119     fillCommonEntityHandleData( text, buffer);
2120 
2121     text->hStyle = buffer.ReadHANDLE();
2122 
2123     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2124     text->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "TEXT" ) );
2125 
2126     return text;
2127 }
2128 
getVertex3D(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)2129 CADVertex3DObject * DWGFileR2000::getVertex3D(unsigned int dObjectSize,
2130                                               const CADCommonED& stCommonEntityData,
2131                                               CADBuffer &buffer)
2132 {
2133     CADVertex3DObject * vertex = new CADVertex3DObject();
2134 
2135     vertex->setSize( dObjectSize );
2136     vertex->stCed = stCommonEntityData;
2137 
2138     /*unsigned char Flags = */buffer.ReadCHAR();
2139 
2140     CADVector vertPosition = buffer.ReadVector();
2141     vertex->vertPosition = vertPosition;
2142 
2143     fillCommonEntityHandleData( vertex, buffer);
2144 
2145     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2146     vertex->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "VERTEX" ) );
2147     return vertex;
2148 }
2149 
getCircle(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)2150 CADCircleObject * DWGFileR2000::getCircle(unsigned int dObjectSize,
2151                                           const CADCommonED& stCommonEntityData,
2152                                           CADBuffer &buffer)
2153 {
2154     CADCircleObject * circle = new CADCircleObject();
2155 
2156     circle->setSize( dObjectSize );
2157     circle->stCed = stCommonEntityData;
2158 
2159     CADVector vertPosition = buffer.ReadVector();
2160     circle->vertPosition = vertPosition;
2161     circle->dfRadius     = buffer.ReadBITDOUBLE();
2162     circle->dfThickness  = buffer.ReadBIT() ? 0.0f : buffer.ReadBITDOUBLE();
2163 
2164     if( buffer.ReadBIT() )
2165     {
2166         circle->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
2167     }
2168     else
2169     {
2170         CADVector vectExtrusion = buffer.ReadVector();
2171         circle->vectExtrusion = vectExtrusion;
2172     }
2173 
2174     fillCommonEntityHandleData( circle, buffer);
2175 
2176     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2177     circle->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "CIRCLE" ) );
2178     return circle;
2179 }
2180 
getEndBlock(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)2181 CADEndblkObject * DWGFileR2000::getEndBlock(unsigned int dObjectSize,
2182                                             const CADCommonED& stCommonEntityData,
2183                                             CADBuffer &buffer)
2184 {
2185     CADEndblkObject * endblk = new CADEndblkObject();
2186 
2187     endblk->setSize( dObjectSize );
2188     endblk->stCed = stCommonEntityData;
2189 
2190     fillCommonEntityHandleData( endblk, buffer);
2191 
2192     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2193     endblk->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "ENDBLK" ) );
2194     return endblk;
2195 }
2196 
getPolyline2D(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)2197 CADPolyline2DObject * DWGFileR2000::getPolyline2D(unsigned int dObjectSize,
2198                                                   const CADCommonED& stCommonEntityData,
2199                                                   CADBuffer &buffer)
2200 {
2201     CADPolyline2DObject * polyline = new CADPolyline2DObject();
2202 
2203     polyline->setSize( dObjectSize );
2204     polyline->stCed = stCommonEntityData;
2205 
2206     polyline->dFlags                = buffer.ReadBITSHORT();
2207     polyline->dCurveNSmoothSurfType = buffer.ReadBITSHORT();
2208 
2209     polyline->dfStartWidth = buffer.ReadBITDOUBLE();
2210     polyline->dfEndWidth   = buffer.ReadBITDOUBLE();
2211 
2212     polyline->dfThickness = buffer.ReadBIT() ? 0.0f : buffer.ReadBITDOUBLE();
2213 
2214     polyline->dfElevation = buffer.ReadBITDOUBLE();
2215 
2216     if( buffer.ReadBIT() )
2217     {
2218         polyline->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
2219     }
2220     else
2221     {
2222         CADVector vectExtrusion = buffer.ReadVector();
2223         polyline->vectExtrusion = vectExtrusion;
2224     }
2225 
2226     fillCommonEntityHandleData( polyline, buffer);
2227 
2228     polyline->hVertices.push_back( buffer.ReadHANDLE() ); // 1st vertex
2229     polyline->hVertices.push_back( buffer.ReadHANDLE() ); // last vertex
2230 
2231     polyline->hSeqend = buffer.ReadHANDLE();
2232 
2233     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2234     polyline->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "POLYLINE" ) );
2235     return polyline;
2236 }
2237 
getAttributes(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)2238 CADAttribObject * DWGFileR2000::getAttributes(unsigned int dObjectSize,
2239                                               const CADCommonED& stCommonEntityData,
2240                                               CADBuffer &buffer)
2241 {
2242     CADAttribObject * attrib = new CADAttribObject();
2243 
2244     attrib->setSize( dObjectSize );
2245     attrib->stCed     = stCommonEntityData;
2246     attrib->DataFlags = buffer.ReadCHAR();
2247 
2248     if( !( attrib->DataFlags & 0x01 ) )
2249         attrib->dfElevation = buffer.ReadRAWDOUBLE();
2250 
2251     double x, y;
2252 
2253     CADVector vertInsetionPoint = buffer.ReadRAWVector();
2254     attrib->vertInsetionPoint = vertInsetionPoint;
2255 
2256     if( !( attrib->DataFlags & 0x02 ) )
2257     {
2258         x = buffer.ReadBITDOUBLEWD( vertInsetionPoint.getX() );
2259         y = buffer.ReadBITDOUBLEWD( vertInsetionPoint.getY() );
2260         CADVector vertAlignmentPoint( x, y );
2261         attrib->vertAlignmentPoint = vertAlignmentPoint;
2262     }
2263 
2264     if( buffer.ReadBIT() )
2265     {
2266         attrib->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
2267     }
2268     else
2269     {
2270         CADVector vectExtrusion = buffer.ReadVector();
2271         attrib->vectExtrusion = vectExtrusion;
2272     }
2273 
2274     attrib->dfThickness = buffer.ReadBIT() ? 0.0f : buffer.ReadBITDOUBLE();
2275 
2276     if( !( attrib->DataFlags & 0x04 ) )
2277         attrib->dfObliqueAng  = buffer.ReadRAWDOUBLE();
2278     if( !( attrib->DataFlags & 0x08 ) )
2279         attrib->dfRotationAng = buffer.ReadRAWDOUBLE();
2280     attrib->dfHeight          = buffer.ReadRAWDOUBLE();
2281     if( !( attrib->DataFlags & 0x10 ) )
2282         attrib->dfWidthFactor = buffer.ReadRAWDOUBLE();
2283     attrib->sTextValue        = buffer.ReadTV();
2284     if( !( attrib->DataFlags & 0x20 ) )
2285         attrib->dGeneration   = buffer.ReadBITSHORT();
2286     if( !( attrib->DataFlags & 0x40 ) )
2287         attrib->dHorizAlign   = buffer.ReadBITSHORT();
2288     if( !( attrib->DataFlags & 0x80 ) )
2289         attrib->dVertAlign    = buffer.ReadBITSHORT();
2290 
2291     attrib->sTag         = buffer.ReadTV();
2292     attrib->nFieldLength = buffer.ReadBITSHORT();
2293     attrib->nFlags       = buffer.ReadCHAR();
2294 
2295     fillCommonEntityHandleData( attrib, buffer);
2296 
2297     attrib->hStyle = buffer.ReadHANDLE();
2298 
2299     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2300     attrib->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "ATTRIB" ) );
2301     return attrib;
2302 }
2303 
getAttributesDefn(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)2304 CADAttdefObject * DWGFileR2000::getAttributesDefn(unsigned int dObjectSize,
2305                                                   const CADCommonED& stCommonEntityData,
2306                                                   CADBuffer &buffer)
2307 {
2308     CADAttdefObject * attdef = new CADAttdefObject();
2309 
2310     attdef->setSize( dObjectSize );
2311     attdef->stCed     = stCommonEntityData;
2312     attdef->DataFlags = buffer.ReadCHAR();
2313 
2314     if( ( attdef->DataFlags & 0x01 ) == 0 )
2315         attdef->dfElevation = buffer.ReadRAWDOUBLE();
2316 
2317     CADVector vertInsetionPoint = buffer.ReadRAWVector();
2318     attdef->vertInsetionPoint = vertInsetionPoint;
2319 
2320     if( ( attdef->DataFlags & 0x02 ) == 0 )
2321     {
2322         double x = buffer.ReadBITDOUBLEWD( vertInsetionPoint.getX() );
2323         double y = buffer.ReadBITDOUBLEWD( vertInsetionPoint.getY() );
2324         CADVector vertAlignmentPoint( x, y );
2325         attdef->vertAlignmentPoint = vertAlignmentPoint;
2326     }
2327 
2328     if( buffer.ReadBIT() )
2329     {
2330         attdef->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
2331     }
2332     else
2333     {
2334         CADVector vectExtrusion = buffer.ReadVector();
2335         attdef->vectExtrusion = vectExtrusion;
2336     }
2337 
2338     attdef->dfThickness = buffer.ReadBIT() ? 0.0f :
2339                           buffer.ReadBITDOUBLE();
2340 
2341     if( ( attdef->DataFlags & 0x04 ) == 0 )
2342         attdef->dfObliqueAng  = buffer.ReadRAWDOUBLE();
2343     if( ( attdef->DataFlags & 0x08 ) == 0 )
2344         attdef->dfRotationAng = buffer.ReadRAWDOUBLE();
2345     attdef->dfHeight          = buffer.ReadRAWDOUBLE();
2346     if( ( attdef->DataFlags & 0x10 ) == 0 )
2347         attdef->dfWidthFactor = buffer.ReadRAWDOUBLE();
2348     attdef->sTextValue        = buffer.ReadTV();
2349     if( ( attdef->DataFlags & 0x20 ) == 0 )
2350         attdef->dGeneration   = buffer.ReadBITSHORT();
2351     if( ( attdef->DataFlags & 0x40 ) == 0 )
2352         attdef->dHorizAlign   = buffer.ReadBITSHORT();
2353     if( ( attdef->DataFlags & 0x80 ) == 0 )
2354         attdef->dVertAlign    = buffer.ReadBITSHORT();
2355 
2356     attdef->sTag         = buffer.ReadTV();
2357     attdef->nFieldLength = buffer.ReadBITSHORT();
2358     attdef->nFlags       = buffer.ReadCHAR();
2359 
2360     attdef->sPrompt = buffer.ReadTV();
2361 
2362     fillCommonEntityHandleData( attdef, buffer);
2363 
2364     attdef->hStyle = buffer.ReadHANDLE();
2365 
2366     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2367     attdef->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "ATTRDEF" ) );
2368     return attdef;
2369 }
2370 
getLWPolyLine(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)2371 CADLWPolylineObject * DWGFileR2000::getLWPolyLine(unsigned int dObjectSize,
2372                                                   const CADCommonED& stCommonEntityData,
2373                                                   CADBuffer &buffer)
2374 {
2375     CADLWPolylineObject * polyline = new CADLWPolylineObject();
2376     polyline->setSize( dObjectSize );
2377     polyline->stCed = stCommonEntityData;
2378 
2379     int    verticesCount = 0, nBulges = 0, nNumWidths = 0;
2380     short  dataFlag      = buffer.ReadBITSHORT();
2381     if( dataFlag & 4 )
2382         polyline->dfConstWidth = buffer.ReadBITDOUBLE();
2383     if( dataFlag & 8 )
2384         polyline->dfElevation  = buffer.ReadBITDOUBLE();
2385     if( dataFlag & 2 )
2386         polyline->dfThickness  = buffer.ReadBITDOUBLE();
2387     if( dataFlag & 1 )
2388     {
2389         CADVector vectExtrusion = buffer.ReadVector();
2390         polyline->vectExtrusion = vectExtrusion;
2391     }
2392 
2393     verticesCount = buffer.ReadBITLONG();
2394     if(verticesCount < 1)
2395     {
2396         delete polyline;
2397         return nullptr;
2398     }
2399     if( verticesCount < 100000 )
2400     {
2401         // For some reason reserving huge amounts cause later segfaults
2402         // whereas an exception would have been expected
2403         polyline->avertVertices.reserve( static_cast<size_t>(verticesCount) );
2404     }
2405 
2406     if( dataFlag & 16 )
2407     {
2408         nBulges = buffer.ReadBITLONG();
2409         if(nBulges < 0)
2410         {
2411             delete polyline;
2412             return nullptr;
2413         }
2414         if( nBulges < 100000 )
2415         {
2416             polyline->adfBulges.reserve( static_cast<size_t>(nBulges) );
2417         }
2418     }
2419 
2420     // TODO: tell ODA that R2000 contains nNumWidths flag
2421     if( dataFlag & 32 )
2422     {
2423         nNumWidths = buffer.ReadBITLONG();
2424         if(nNumWidths < 0)
2425         {
2426             delete polyline;
2427             return nullptr;
2428         }
2429         if( nNumWidths < 100000 )
2430         {
2431             polyline->astWidths.reserve( static_cast<size_t>(nNumWidths) );
2432         }
2433     }
2434 
2435     if( dataFlag & 512 )
2436     {
2437         polyline->bClosed = true;
2438     }
2439     else
2440     {
2441         polyline->bClosed = false;
2442     }
2443 
2444     // First of all, read first vertex.
2445     CADVector vertex = buffer.ReadRAWVector();
2446     polyline->avertVertices.push_back( vertex );
2447 
2448     // All the others are not raw doubles; bitdoubles with default instead,
2449     // where default is previous point coords.
2450     size_t prev;
2451     for( int i = 1; i < verticesCount; ++i )
2452     {
2453         prev = size_t( i - 1 );
2454         double x = buffer.ReadBITDOUBLEWD( polyline->avertVertices[prev].getX() );
2455         double y = buffer.ReadBITDOUBLEWD( polyline->avertVertices[prev].getY() );
2456         if( buffer.IsEOB() )
2457         {
2458             delete polyline;
2459             return nullptr;
2460         }
2461         vertex.setX( x );
2462         vertex.setY( y );
2463         polyline->avertVertices.push_back( vertex );
2464     }
2465 
2466     for( int i = 0; i < nBulges; ++i )
2467     {
2468         double dfBulgeValue = buffer.ReadBITDOUBLE();
2469         polyline->adfBulges.push_back( dfBulgeValue );
2470         if( buffer.IsEOB() )
2471         {
2472             delete polyline;
2473             return nullptr;
2474         }
2475     }
2476 
2477     for( int i = 0; i < nNumWidths; ++i )
2478     {
2479         double dfStartWidth = buffer.ReadBITDOUBLE();
2480         double dfEndWidth   = buffer.ReadBITDOUBLE();
2481         if( buffer.IsEOB() )
2482         {
2483             delete polyline;
2484             return nullptr;
2485         }
2486         polyline->astWidths.push_back( make_pair( dfStartWidth, dfEndWidth ) );
2487     }
2488 
2489     fillCommonEntityHandleData( polyline, buffer);
2490 
2491     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2492     polyline->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "WPOLYLINE" ) );
2493     return polyline;
2494 }
2495 
getArc(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)2496 CADArcObject * DWGFileR2000::getArc(unsigned int dObjectSize,
2497                                     const CADCommonED& stCommonEntityData,
2498                                     CADBuffer &buffer)
2499 {
2500     CADArcObject * arc = new CADArcObject();
2501 
2502     arc->setSize( dObjectSize );
2503     arc->stCed = stCommonEntityData;
2504 
2505     CADVector vertPosition = buffer.ReadVector();
2506     arc->vertPosition = vertPosition;
2507     arc->dfRadius     = buffer.ReadBITDOUBLE();
2508     arc->dfThickness  = buffer.ReadBIT() ? 0.0f : buffer.ReadBITDOUBLE();
2509 
2510     if( buffer.ReadBIT() )
2511     {
2512         arc->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
2513     }
2514     else
2515     {
2516         CADVector vectExtrusion = buffer.ReadVector();
2517         arc->vectExtrusion = vectExtrusion;
2518     }
2519 
2520     arc->dfStartAngle = buffer.ReadBITDOUBLE();
2521     arc->dfEndAngle   = buffer.ReadBITDOUBLE();
2522 
2523     fillCommonEntityHandleData( arc, buffer);
2524 
2525     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2526     arc->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "ARC" ) );
2527     return arc;
2528 }
2529 
getSpline(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)2530 CADSplineObject * DWGFileR2000::getSpline(unsigned int dObjectSize,
2531                                           const CADCommonED& stCommonEntityData,
2532                                           CADBuffer &buffer)
2533 {
2534     CADSplineObject * spline = new CADSplineObject();
2535     spline->setSize( dObjectSize );
2536     spline->stCed     = stCommonEntityData;
2537     spline->dScenario = buffer.ReadBITLONG();
2538     spline->dDegree   = buffer.ReadBITLONG();
2539 
2540     if( spline->dScenario == 2 )
2541     {
2542         spline->dfFitTol = buffer.ReadBITDOUBLE();
2543         CADVector vectBegTangDir = buffer.ReadVector();
2544         spline->vectBegTangDir = vectBegTangDir;
2545         CADVector vectEndTangDir = buffer.ReadVector();
2546         spline->vectEndTangDir = vectEndTangDir;
2547 
2548         spline->nNumFitPts = buffer.ReadBITLONG();
2549         if(spline->nNumFitPts < 0 || spline->nNumFitPts > 10 * 1024 * 1024)
2550         {
2551             delete spline;
2552             return nullptr;
2553         }
2554         spline->averFitPoints.reserve( static_cast<size_t>(spline->nNumFitPts) );
2555     }
2556     else if( spline->dScenario == 1 )
2557     {
2558         spline->bRational = buffer.ReadBIT();
2559         spline->bClosed   = buffer.ReadBIT();
2560         spline->bPeriodic = buffer.ReadBIT();
2561         spline->dfKnotTol = buffer.ReadBITDOUBLE();
2562         spline->dfCtrlTol = buffer.ReadBITDOUBLE();
2563 
2564         spline->nNumKnots = buffer.ReadBITLONG();
2565         if(spline->nNumKnots < 0 || spline->nNumKnots > 10 * 1024 * 1024)
2566         {
2567             delete spline;
2568             return nullptr;
2569         }
2570         spline->adfKnots.reserve( static_cast<size_t>(spline->nNumKnots) );
2571 
2572         spline->nNumCtrlPts = buffer.ReadBITLONG();
2573         if(spline->nNumCtrlPts < 0 || spline->nNumCtrlPts > 10 * 1024 * 1024)
2574         {
2575             delete spline;
2576             return nullptr;
2577         }
2578         spline->avertCtrlPoints.reserve( static_cast<size_t>(spline->nNumCtrlPts) );
2579         if( spline->bWeight )
2580             spline->adfCtrlPointsWeight.reserve( static_cast<size_t>(spline->nNumCtrlPts) );
2581         spline->bWeight = buffer.ReadBIT();
2582     }
2583 #ifdef _DEBUG
2584     else
2585     {
2586         DebugMsg( "Spline scenario != {1,2} read: error." );
2587     }
2588 #endif
2589     for( long i = 0; i < spline->nNumKnots; ++i )
2590     {
2591         spline->adfKnots.push_back( buffer.ReadBITDOUBLE() );
2592         if( buffer.IsEOB() )
2593         {
2594             delete spline;
2595             return nullptr;
2596         }
2597     }
2598 
2599     for( long i = 0; i < spline->nNumCtrlPts; ++i )
2600     {
2601         CADVector vertex = buffer.ReadVector();
2602         spline->avertCtrlPoints.push_back( vertex );
2603         if( spline->bWeight )
2604             spline->adfCtrlPointsWeight.push_back( buffer.ReadBITDOUBLE() );
2605         if( buffer.IsEOB() )
2606         {
2607             delete spline;
2608             return nullptr;
2609         }
2610     }
2611 
2612     for( long i = 0; i < spline->nNumFitPts; ++i )
2613     {
2614         CADVector vertex = buffer.ReadVector();
2615         if( buffer.IsEOB() )
2616         {
2617             delete spline;
2618             return nullptr;
2619         }
2620         spline->averFitPoints.push_back( vertex );
2621     }
2622 
2623     fillCommonEntityHandleData( spline, buffer);
2624 
2625     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2626     spline->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "SPLINE" ) );
2627     return spline;
2628 }
2629 
getEntity(int dObjectType,unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)2630 CADEntityObject * DWGFileR2000::getEntity(int dObjectType,
2631                                           unsigned int dObjectSize,
2632                                           const CADCommonED& stCommonEntityData,
2633                                           CADBuffer &buffer)
2634 {
2635     CADEntityObject * entity = new CADEntityObject(
2636                     static_cast<CADObject::ObjectType>(dObjectType) );
2637 
2638     entity->setSize( dObjectSize );
2639     entity->stCed = stCommonEntityData;
2640 
2641     buffer.Seek(static_cast<size_t>(
2642                     entity->stCed.nObjectSizeInBits + 16), CADBuffer::BEG);
2643 
2644     fillCommonEntityHandleData( entity, buffer );
2645 
2646     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2647     entity->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "ENTITY" ) );
2648     return entity;
2649 }
2650 
getInsert(int dObjectType,unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)2651 CADInsertObject * DWGFileR2000::getInsert(int dObjectType,
2652                                           unsigned int dObjectSize,
2653                                           const CADCommonED& stCommonEntityData,
2654                                           CADBuffer &buffer)
2655 {
2656     CADInsertObject * insert = new CADInsertObject(
2657                             static_cast<CADObject::ObjectType>(dObjectType) );
2658     insert->setSize( dObjectSize );
2659     insert->stCed = stCommonEntityData;
2660 
2661     insert->vertInsertionPoint = buffer.ReadVector();
2662     unsigned char dataFlags = buffer.Read2B();
2663     double        val41     = 1.0;
2664     double        val42     = 1.0;
2665     double        val43     = 1.0;
2666     if( dataFlags == 0 )
2667     {
2668         val41 = buffer.ReadRAWDOUBLE();
2669         val42 = buffer.ReadBITDOUBLEWD( val41 );
2670         val43 = buffer.ReadBITDOUBLEWD( val41 );
2671     }
2672     else if( dataFlags == 1 )
2673     {
2674         val41 = 1.0;
2675         val42 = buffer.ReadBITDOUBLEWD( val41 );
2676         val43 = buffer.ReadBITDOUBLEWD( val41 );
2677     }
2678     else if( dataFlags == 2 )
2679     {
2680         val41 = buffer.ReadRAWDOUBLE();
2681         val42 = val41;
2682         val43 = val41;
2683     }
2684     insert->vertScales    = CADVector( val41, val42, val43 );
2685     insert->dfRotation    = buffer.ReadBITDOUBLE();
2686     insert->vectExtrusion = buffer.ReadVector();
2687     insert->bHasAttribs   = buffer.ReadBIT();
2688 
2689     fillCommonEntityHandleData( insert, buffer);
2690 
2691     insert->hBlockHeader = buffer.ReadHANDLE();
2692     if( insert->bHasAttribs )
2693     {
2694         insert->hAttribs.push_back( buffer.ReadHANDLE() );
2695         insert->hAttribs.push_back( buffer.ReadHANDLE() );
2696         insert->hSeqend = buffer.ReadHANDLE();
2697     }
2698 
2699     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2700     insert->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "INSERT" ) );
2701 
2702     return insert;
2703 }
2704 
getDictionary(unsigned int dObjectSize,CADBuffer & buffer)2705 CADDictionaryObject * DWGFileR2000::getDictionary(unsigned int dObjectSize,
2706                                                   CADBuffer &buffer)
2707 {
2708     /*
2709      * FIXME: ODA has a lot of mistypes in spec. for this objects,
2710      * it doesn't work for now (error begins in handles stream).
2711      * Nonetheless, dictionary->sItemNames is 100% array,
2712      * not a single obj as pointer by their docs.
2713      */
2714     CADDictionaryObject * dictionary = new CADDictionaryObject();
2715 
2716     if(!readBasicData(dictionary, dObjectSize, buffer))
2717     {
2718         delete dictionary;
2719         return nullptr;
2720     }
2721 
2722     dictionary->nNumItems      = buffer.ReadBITLONG();
2723     if(dictionary->nNumItems < 0)
2724     {
2725         delete dictionary;
2726         return nullptr;
2727     }
2728     dictionary->dCloningFlag   = buffer.ReadBITSHORT();
2729     dictionary->dHardOwnerFlag = buffer.ReadCHAR();
2730 
2731     for( long i = 0; i < dictionary->nNumItems; ++i )
2732     {
2733         dictionary->sItemNames.push_back( buffer.ReadTV() );
2734         if( buffer.IsEOB() )
2735         {
2736             delete dictionary;
2737             return nullptr;
2738         }
2739     }
2740 
2741     dictionary->hParentHandle = buffer.ReadHANDLE();
2742 
2743     for( long i = 0; i < dictionary->nNumReactors; ++i )
2744     {
2745         dictionary->hReactors.push_back( buffer.ReadHANDLE() );
2746         if( buffer.IsEOB() )
2747         {
2748             delete dictionary;
2749             return nullptr;
2750         }
2751     }
2752     dictionary->hXDictionary = buffer.ReadHANDLE();
2753     for( long i = 0; i < dictionary->nNumItems; ++i )
2754     {
2755         dictionary->hItemHandles.push_back( buffer.ReadHANDLE() );
2756         if( buffer.IsEOB() )
2757         {
2758             delete dictionary;
2759             return nullptr;
2760         }
2761     }
2762 
2763     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2764     dictionary->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "DICT" ) );
2765 
2766     return dictionary;
2767 }
2768 
getLayerObject(unsigned int dObjectSize,CADBuffer & buffer)2769 CADLayerObject * DWGFileR2000::getLayerObject(unsigned int dObjectSize,
2770                                               CADBuffer &buffer)
2771 {
2772     CADLayerObject * layer = new CADLayerObject();
2773 
2774     if(!readBasicData(layer, dObjectSize, buffer))
2775     {
2776         delete layer;
2777         return nullptr;
2778     }
2779 
2780     layer->sLayerName   = buffer.ReadTV();
2781     layer->b64Flag      = buffer.ReadBIT() != 0;
2782     layer->dXRefIndex   = buffer.ReadBITSHORT();
2783     layer->bXDep        = buffer.ReadBIT() != 0;
2784 
2785     short dFlags = buffer.ReadBITSHORT();
2786     layer->bFrozen           = (dFlags & 0x01) != 0;
2787     layer->bOn               = (dFlags & 0x02) != 0;
2788     layer->bFrozenInNewVPORT = (dFlags & 0x04) != 0;
2789     layer->bLocked           = (dFlags & 0x08) != 0;
2790     layer->bPlottingFlag     = (dFlags & 0x10) != 0;
2791     layer->dLineWeight       = dFlags & 0x03E0;
2792     layer->dCMColor          = buffer.ReadBITSHORT();
2793     layer->hLayerControl     = buffer.ReadHANDLE();
2794     for( long i = 0; i < layer->nNumReactors; ++i )
2795     {
2796         layer->hReactors.push_back( buffer.ReadHANDLE() );
2797         if( buffer.IsEOB() )
2798         {
2799             delete layer;
2800             return nullptr;
2801         }
2802     }
2803     layer->hXDictionary            = buffer.ReadHANDLE();
2804     layer->hExternalRefBlockHandle = buffer.ReadHANDLE();
2805     layer->hPlotStyle              = buffer.ReadHANDLE();
2806     layer->hLType                  = buffer.ReadHANDLE();
2807 
2808     /*
2809      * FIXME: ODA says that this handle should be null hard pointer. It is not.
2810      * Also, after reading it dObjectSize is != actual read structure's size.
2811      * Not used anyway, so no point to read it for now.
2812      * It also means that CRC cannot be computed correctly.
2813      */
2814 // layer->hUnknownHandle = ReadHANDLE (pabySectionContent, nBitOffsetFromStart);
2815 
2816     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2817     layer->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "LAYER" ) );
2818     return layer;
2819 }
2820 
getLayerControl(unsigned int dObjectSize,CADBuffer & buffer)2821 CADLayerControlObject * DWGFileR2000::getLayerControl(unsigned int dObjectSize,
2822                                                       CADBuffer &buffer)
2823 {
2824     CADLayerControlObject * layerControl = new CADLayerControlObject();
2825 
2826     if(!readBasicData(layerControl, dObjectSize, buffer))
2827     {
2828         delete layerControl;
2829         return nullptr;
2830     }
2831 
2832     layerControl->nNumEntries  = buffer.ReadBITLONG();
2833     if(layerControl->nNumEntries < 0)
2834     {
2835         delete layerControl;
2836         return nullptr;
2837     }
2838     layerControl->hNull        = buffer.ReadHANDLE();
2839     layerControl->hXDictionary = buffer.ReadHANDLE();
2840     for( long i = 0; i < layerControl->nNumEntries; ++i )
2841     {
2842         layerControl->hLayers.push_back( buffer.ReadHANDLE() );
2843         if( buffer.IsEOB() )
2844         {
2845             delete layerControl;
2846             return nullptr;
2847         }
2848     }
2849 
2850     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2851     layerControl->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "LAYERCONTROL" ) );
2852     return layerControl;
2853 }
2854 
getBlockControl(unsigned int dObjectSize,CADBuffer & buffer)2855 CADBlockControlObject * DWGFileR2000::getBlockControl(unsigned int dObjectSize,
2856                                                       CADBuffer &buffer)
2857 {
2858     CADBlockControlObject * blockControl = new CADBlockControlObject();
2859 
2860     if(!readBasicData(blockControl, dObjectSize, buffer))
2861     {
2862         delete blockControl;
2863         return nullptr;
2864     }
2865 
2866     blockControl->nNumEntries  = buffer.ReadBITLONG();
2867     if(blockControl->nNumEntries < 0)
2868     {
2869         delete blockControl;
2870         return nullptr;
2871     }
2872 
2873     blockControl->hNull        = buffer.ReadHANDLE();
2874     blockControl->hXDictionary = buffer.ReadHANDLE();
2875 
2876     for( long i = 0; i < blockControl->nNumEntries + 2; ++i )
2877     {
2878         blockControl->hBlocks.push_back( buffer.ReadHANDLE() );
2879         if( buffer.IsEOB() )
2880         {
2881             delete blockControl;
2882             return nullptr;
2883         }
2884     }
2885 
2886     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2887     blockControl->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "BLOCKCONTROL" ) );
2888     return blockControl;
2889 }
2890 
getBlockHeader(unsigned int dObjectSize,CADBuffer & buffer)2891 CADBlockHeaderObject * DWGFileR2000::getBlockHeader(unsigned int dObjectSize,
2892                                                     CADBuffer &buffer)
2893 {
2894     CADBlockHeaderObject * blockHeader = new CADBlockHeaderObject();
2895 
2896     if(!readBasicData(blockHeader, dObjectSize, buffer))
2897     {
2898         delete blockHeader;
2899         return nullptr;
2900     }
2901 
2902     blockHeader->sEntryName    = buffer.ReadTV();
2903     blockHeader->b64Flag       = buffer.ReadBIT();
2904     blockHeader->dXRefIndex    = buffer.ReadBITSHORT();
2905     blockHeader->bXDep         = buffer.ReadBIT();
2906     blockHeader->bAnonymous    = buffer.ReadBIT();
2907     blockHeader->bHasAtts      = buffer.ReadBIT();
2908     blockHeader->bBlkisXRef    = buffer.ReadBIT();
2909     blockHeader->bXRefOverlaid = buffer.ReadBIT();
2910     blockHeader->bLoadedBit    = buffer.ReadBIT();
2911 
2912     CADVector vertBasePoint = buffer.ReadVector();
2913     blockHeader->vertBasePoint = vertBasePoint;
2914     blockHeader->sXRefPName    = buffer.ReadTV();
2915     unsigned char Tmp;
2916     do
2917     {
2918         Tmp = buffer.ReadCHAR();
2919         blockHeader->adInsertCount.push_back( Tmp );
2920     } while( Tmp != 0 );
2921 
2922     blockHeader->sBlockDescription  = buffer.ReadTV();
2923     blockHeader->nSizeOfPreviewData = buffer.ReadBITLONG();
2924     if(blockHeader->nSizeOfPreviewData < 0)
2925     {
2926         delete blockHeader;
2927         return nullptr;
2928     }
2929     for( long i = 0; i < blockHeader->nSizeOfPreviewData; ++i )
2930     {
2931         blockHeader->abyBinaryPreviewData.push_back( buffer.ReadCHAR() );
2932         if( buffer.IsEOB() )
2933         {
2934             delete blockHeader;
2935             return nullptr;
2936         }
2937     }
2938 
2939     blockHeader->hBlockControl = buffer.ReadHANDLE();
2940     for( long i = 0; i < blockHeader->nNumReactors; ++i )
2941     {
2942         blockHeader->hReactors.push_back( buffer.ReadHANDLE() );
2943         if( buffer.IsEOB() )
2944         {
2945             delete blockHeader;
2946             return nullptr;
2947         }
2948     }
2949     blockHeader->hXDictionary = buffer.ReadHANDLE();
2950     blockHeader->hNull        = buffer.ReadHANDLE();
2951     blockHeader->hBlockEntity = buffer.ReadHANDLE();
2952     if( !blockHeader->bBlkisXRef && !blockHeader->bXRefOverlaid )
2953     {
2954         blockHeader->hEntities.push_back( buffer.ReadHANDLE() ); // first
2955         blockHeader->hEntities.push_back( buffer.ReadHANDLE() ); // last
2956     }
2957 
2958     blockHeader->hEndBlk = buffer.ReadHANDLE();
2959     for( size_t i = 0; i < blockHeader->adInsertCount.size() - 1; ++i )
2960         blockHeader->hInsertHandles.push_back( buffer.ReadHANDLE() );
2961     blockHeader->hLayout = buffer.ReadHANDLE();
2962 
2963     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
2964     blockHeader->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "BLOCKHEADER" ) );
2965     return blockHeader;
2966 }
2967 
getLineTypeControl(unsigned int dObjectSize,CADBuffer & buffer)2968 CADLineTypeControlObject * DWGFileR2000::getLineTypeControl(unsigned int dObjectSize,
2969                                                             CADBuffer &buffer)
2970 {
2971     CADLineTypeControlObject * ltypeControl = new CADLineTypeControlObject();
2972 
2973     if(!readBasicData(ltypeControl, dObjectSize, buffer))
2974     {
2975         delete ltypeControl;
2976         return nullptr;
2977     }
2978 
2979     ltypeControl->nNumEntries  = buffer.ReadBITLONG();
2980     if(ltypeControl->nNumEntries < 0)
2981     {
2982         delete ltypeControl;
2983         return nullptr;
2984     }
2985 
2986     ltypeControl->hNull        = buffer.ReadHANDLE();
2987     ltypeControl->hXDictionary = buffer.ReadHANDLE();
2988 
2989     // hLTypes ends with BYLAYER and BYBLOCK
2990     for( long i = 0; i < ltypeControl->nNumEntries + 2; ++i )
2991     {
2992         ltypeControl->hLTypes.push_back( buffer.ReadHANDLE() );
2993         if( buffer.IsEOB() )
2994         {
2995             delete ltypeControl;
2996             return nullptr;
2997         }
2998     }
2999 
3000     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3001     ltypeControl->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "LINETYPECTRL" ) );
3002     return ltypeControl;
3003 }
3004 
getLineType1(unsigned int dObjectSize,CADBuffer & buffer)3005 CADLineTypeObject * DWGFileR2000::getLineType1(unsigned int dObjectSize, CADBuffer &buffer)
3006 {
3007     CADLineTypeObject * ltype = new CADLineTypeObject();
3008 
3009     if(!readBasicData(ltype, dObjectSize, buffer))
3010     {
3011         delete ltype;
3012         return nullptr;
3013     }
3014 
3015     ltype->sEntryName   = buffer.ReadTV();
3016     ltype->b64Flag      = buffer.ReadBIT();
3017     ltype->dXRefIndex   = buffer.ReadBITSHORT();
3018     ltype->bXDep        = buffer.ReadBIT();
3019     ltype->sDescription = buffer.ReadTV();
3020     ltype->dfPatternLen = buffer.ReadBITDOUBLE();
3021     ltype->dAlignment   = buffer.ReadCHAR();
3022     ltype->nNumDashes   = buffer.ReadCHAR();
3023 
3024     CADDash     dash;
3025     for( size_t i = 0; i < ltype->nNumDashes; ++i )
3026     {
3027         dash.dfLength          = buffer.ReadBITDOUBLE();
3028         dash.dComplexShapecode = buffer.ReadBITSHORT();
3029         dash.dfXOffset         = buffer.ReadRAWDOUBLE();
3030         dash.dfYOffset         = buffer.ReadRAWDOUBLE();
3031         dash.dfScale           = buffer.ReadBITDOUBLE();
3032         dash.dfRotation        = buffer.ReadBITDOUBLE();
3033         dash.dShapeflag        = buffer.ReadBITSHORT(); // TODO: what to do with it?
3034 
3035         ltype->astDashes.push_back( dash );
3036     }
3037 
3038     for( short i = 0; i < 256; ++i )
3039         ltype->abyTextArea.push_back( buffer.ReadCHAR() );
3040 
3041     ltype->hLTControl = buffer.ReadHANDLE();
3042 
3043     for( long i = 0; i < ltype->nNumReactors; ++i )
3044     {
3045         ltype->hReactors.push_back( buffer.ReadHANDLE() );
3046         if( buffer.IsEOB() )
3047         {
3048             delete ltype;
3049             return nullptr;
3050         }
3051     }
3052 
3053     ltype->hXDictionary = buffer.ReadHANDLE();
3054     ltype->hXRefBlock   = buffer.ReadHANDLE();
3055 
3056     // TODO: shapefile for dash/shape (1 each). Does it mean that we have nNumDashes * 2 handles, or what?
3057 
3058     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3059     ltype->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "LINETYPE" ) );
3060     return ltype;
3061 }
3062 
getMLine(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)3063 CADMLineObject * DWGFileR2000::getMLine(unsigned int dObjectSize,
3064                                         const CADCommonED& stCommonEntityData,
3065                                         CADBuffer &buffer)
3066 {
3067     CADMLineObject * mline = new CADMLineObject();
3068 
3069     mline->setSize( dObjectSize );
3070     mline->stCed = stCommonEntityData;
3071 
3072     mline->dfScale = buffer.ReadBITDOUBLE();
3073     mline->dJust   = buffer.ReadCHAR();
3074 
3075     CADVector vertBasePoint = buffer.ReadVector();
3076     mline->vertBasePoint = vertBasePoint;
3077 
3078     CADVector vectExtrusion = buffer.ReadVector();
3079     mline->vectExtrusion = vectExtrusion;
3080     mline->dOpenClosed   = buffer.ReadBITSHORT();
3081     mline->nLinesInStyle = buffer.ReadCHAR();
3082     mline->nNumVertices  = buffer.ReadBITSHORT();
3083     if(mline->nNumVertices < 0)
3084     {
3085         delete mline;
3086         return nullptr;
3087     }
3088 
3089     for( short i = 0; i < mline->nNumVertices; ++i )
3090     {
3091         CADMLineVertex stVertex;
3092 
3093         CADVector vertPosition = buffer.ReadVector();
3094         stVertex.vertPosition = vertPosition;
3095 
3096         CADVector vectDirection = buffer.ReadVector();
3097         stVertex.vectDirection = vectDirection;
3098 
3099         CADVector vectMIterDirection = buffer.ReadVector();
3100         stVertex.vectMIterDirection = vectMIterDirection;
3101         if( buffer.IsEOB() )
3102         {
3103             delete mline;
3104             return nullptr;
3105         }
3106         for( unsigned char j = 0; j < mline->nLinesInStyle; ++j )
3107         {
3108             CADLineStyle   stLStyle;
3109             stLStyle.nNumSegParams = buffer.ReadBITSHORT();
3110             if( stLStyle.nNumSegParams > 0 ) // Or return null here?
3111             {
3112                 for( short k = 0; k < stLStyle.nNumSegParams; ++k )
3113                     stLStyle.adfSegparms.push_back( buffer.ReadBITDOUBLE() );
3114             }
3115             stLStyle.nAreaFillParams = buffer.ReadBITSHORT();
3116             if( stLStyle.nAreaFillParams > 0 )
3117             {
3118                 for( short k = 0; k < stLStyle.nAreaFillParams; ++k )
3119                     stLStyle.adfAreaFillParameters.push_back( buffer.ReadBITDOUBLE() );
3120             }
3121 
3122             stVertex.astLStyles.push_back( stLStyle );
3123             if( buffer.IsEOB() )
3124             {
3125                 delete mline;
3126                 return nullptr;
3127             }
3128         }
3129         mline->avertVertices.push_back( stVertex );
3130     }
3131 
3132     if( mline->stCed.bbEntMode == 0 )
3133         mline->stChed.hOwner = buffer.ReadHANDLE();
3134 
3135     for( long i = 0; i < mline->stCed.nNumReactors; ++i )
3136         mline->stChed.hReactors.push_back( buffer.ReadHANDLE() );
3137 
3138     mline->stChed.hXDictionary = buffer.ReadHANDLE();
3139 
3140     if( !mline->stCed.bNoLinks )
3141     {
3142         mline->stChed.hPrevEntity = buffer.ReadHANDLE();
3143         mline->stChed.hNextEntity = buffer.ReadHANDLE();
3144     }
3145 
3146     mline->stChed.hLayer = buffer.ReadHANDLE();
3147 
3148     if( mline->stCed.bbLTypeFlags == 0x03 )
3149         mline->stChed.hLType = buffer.ReadHANDLE();
3150 
3151     if( mline->stCed.bbPlotStyleFlags == 0x03 )
3152         mline->stChed.hPlotStyle = buffer.ReadHANDLE();
3153 
3154     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3155     mline->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "MLINE" ) );
3156     return mline;
3157 }
3158 
getPolylinePFace(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)3159 CADPolylinePFaceObject * DWGFileR2000::getPolylinePFace(unsigned int dObjectSize,
3160                                                         const CADCommonED& stCommonEntityData,
3161                                                         CADBuffer &buffer)
3162 {
3163     CADPolylinePFaceObject * polyline = new CADPolylinePFaceObject();
3164 
3165     polyline->setSize( dObjectSize );
3166     polyline->stCed = stCommonEntityData;
3167 
3168     polyline->nNumVertices = buffer.ReadBITSHORT();
3169     polyline->nNumFaces    = buffer.ReadBITSHORT();
3170 
3171     fillCommonEntityHandleData( polyline, buffer);
3172 
3173     polyline->hVertices.push_back( buffer.ReadHANDLE() ); // 1st vertex
3174     polyline->hVertices.push_back( buffer.ReadHANDLE() ); // last vertex
3175 
3176     polyline->hSeqend = buffer.ReadHANDLE();
3177 
3178     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3179     polyline->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "POLYLINEPFACE" ) );
3180     return polyline;
3181 }
3182 
getImage(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)3183 CADImageObject * DWGFileR2000::getImage(unsigned int dObjectSize,
3184                                         const CADCommonED& stCommonEntityData,
3185                                         CADBuffer &buffer)
3186 {
3187     CADImageObject * image = new CADImageObject();
3188 
3189     image->setSize( dObjectSize );
3190     image->stCed = stCommonEntityData;
3191 
3192     image->dClassVersion = buffer.ReadBITLONG();
3193 
3194     CADVector vertInsertion = buffer.ReadVector();
3195     image->vertInsertion = vertInsertion;
3196 
3197     CADVector vectUDirection = buffer.ReadVector();
3198     image->vectUDirection = vectUDirection;
3199 
3200     CADVector vectVDirection = buffer.ReadVector();
3201     image->vectVDirection = vectVDirection;
3202 
3203     image->dfSizeX       = buffer.ReadRAWDOUBLE();
3204     image->dfSizeY       = buffer.ReadRAWDOUBLE();
3205     image->dDisplayProps = buffer.ReadBITSHORT();
3206 
3207     image->bClipping         = buffer.ReadBIT();
3208     image->dBrightness       = buffer.ReadCHAR();
3209     image->dContrast         = buffer.ReadCHAR();
3210     image->dFade             = buffer.ReadCHAR();
3211     image->dClipBoundaryType = buffer.ReadBITSHORT();
3212 
3213     if( image->dClipBoundaryType == 1 )
3214     {
3215         CADVector vertPoint1 = buffer.ReadRAWVector();
3216         image->avertClippingPolygonVertices.push_back( vertPoint1 );
3217 
3218         CADVector vertPoint2 = buffer.ReadRAWVector();
3219         image->avertClippingPolygonVertices.push_back( vertPoint2 );
3220     }
3221     else
3222     {
3223         image->nNumberVerticesInClipPolygon = buffer.ReadBITLONG();
3224         if(image->nNumberVerticesInClipPolygon < 0)
3225         {
3226             delete image;
3227             return nullptr;
3228         }
3229 
3230         for( long i = 0; i < image->nNumberVerticesInClipPolygon; ++i )
3231         {
3232             CADVector vertPoint = buffer.ReadRAWVector();
3233             if( buffer.IsEOB() )
3234             {
3235                 delete image;
3236                 return nullptr;
3237             }
3238             image->avertClippingPolygonVertices.push_back( vertPoint );
3239         }
3240     }
3241 
3242     fillCommonEntityHandleData( image, buffer);
3243 
3244     image->hImageDef        = buffer.ReadHANDLE();
3245     image->hImageDefReactor = buffer.ReadHANDLE();
3246 
3247     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3248     image->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "IMAGE" ) );
3249 
3250     return image;
3251 }
3252 
get3DFace(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)3253 CAD3DFaceObject * DWGFileR2000::get3DFace(unsigned int dObjectSize,
3254                                           const CADCommonED& stCommonEntityData,
3255                                           CADBuffer &buffer)
3256 {
3257     CAD3DFaceObject * face = new CAD3DFaceObject();
3258 
3259     face->setSize( dObjectSize );
3260     face->stCed = stCommonEntityData;
3261 
3262     face->bHasNoFlagInd = buffer.ReadBIT();
3263     face->bZZero        = buffer.ReadBIT();
3264 
3265     double x, y, z;
3266 
3267     CADVector vertex = buffer.ReadRAWVector();
3268     if( !face->bZZero )
3269     {
3270         z = buffer.ReadRAWDOUBLE();
3271         vertex.setZ( z );
3272     }
3273     face->avertCorners.push_back( vertex );
3274     for( size_t i = 1; i < 4; ++i )
3275     {
3276         x = buffer.ReadBITDOUBLEWD( face->avertCorners[i - 1].getX() );
3277         y = buffer.ReadBITDOUBLEWD( face->avertCorners[i - 1].getY() );
3278         z = buffer.ReadBITDOUBLEWD( face->avertCorners[i - 1].getZ() );
3279 
3280         CADVector corner( x, y, z );
3281         face->avertCorners.push_back( corner );
3282     }
3283 
3284     if( !face->bHasNoFlagInd )
3285         face->dInvisFlags = buffer.ReadBITSHORT();
3286 
3287     fillCommonEntityHandleData( face, buffer);
3288 
3289     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3290     face->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "3DFACE" ) );
3291     return face;
3292 }
3293 
getVertexMesh(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)3294 CADVertexMeshObject * DWGFileR2000::getVertexMesh(unsigned int dObjectSize,
3295                                                   const CADCommonED& stCommonEntityData,
3296                                                   CADBuffer &buffer)
3297 {
3298     CADVertexMeshObject * vertex = new CADVertexMeshObject();
3299 
3300     vertex->setSize( dObjectSize );
3301     vertex->stCed = stCommonEntityData;
3302 
3303     /*unsigned char Flags = */buffer.ReadCHAR();
3304     CADVector vertPosition = buffer.ReadVector();
3305     vertex->vertPosition = vertPosition;
3306 
3307     fillCommonEntityHandleData( vertex, buffer);
3308 
3309     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3310     vertex->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "VERTEXMESH" ) );
3311     return vertex;
3312 }
3313 
getVertexPFace(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)3314 CADVertexPFaceObject * DWGFileR2000::getVertexPFace(unsigned int dObjectSize,
3315                                                     const CADCommonED& stCommonEntityData,
3316                                                     CADBuffer &buffer)
3317 {
3318     CADVertexPFaceObject * vertex = new CADVertexPFaceObject();
3319 
3320     vertex->setSize( dObjectSize );
3321     vertex->stCed = stCommonEntityData;
3322 
3323     /*unsigned char Flags = */buffer.ReadCHAR();
3324     CADVector vertPosition = buffer.ReadVector();
3325     vertex->vertPosition = vertPosition;
3326 
3327     fillCommonEntityHandleData( vertex, buffer);
3328 
3329     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3330     vertex->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "VERTEXPFACE" ) );
3331     return vertex;
3332 }
3333 
getMText(unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)3334 CADMTextObject * DWGFileR2000::getMText(unsigned int dObjectSize,
3335                                         const CADCommonED& stCommonEntityData,
3336                                         CADBuffer &buffer)
3337 {
3338     CADMTextObject * text = new CADMTextObject();
3339 
3340     text->setSize( dObjectSize );
3341     text->stCed = stCommonEntityData;
3342 
3343     CADVector vertInsertionPoint = buffer.ReadVector();
3344     text->vertInsertionPoint = vertInsertionPoint;
3345 
3346     CADVector vectExtrusion = buffer.ReadVector();
3347     text->vectExtrusion = vectExtrusion;
3348 
3349     CADVector vectXAxisDir = buffer.ReadVector();
3350     text->vectXAxisDir = vectXAxisDir;
3351 
3352     text->dfRectWidth        = buffer.ReadBITDOUBLE();
3353     text->dfTextHeight       = buffer.ReadBITDOUBLE();
3354     text->dAttachment        = buffer.ReadBITSHORT();
3355     text->dDrawingDir        = buffer.ReadBITSHORT();
3356     text->dfExtents          = buffer.ReadBITDOUBLE();
3357     text->dfExtentsWidth     = buffer.ReadBITDOUBLE();
3358     text->sTextValue         = buffer.ReadTV();
3359     text->dLineSpacingStyle  = buffer.ReadBITSHORT();
3360     text->dLineSpacingFactor = buffer.ReadBITDOUBLE();
3361     text->bUnknownBit        = buffer.ReadBIT();
3362 
3363     fillCommonEntityHandleData( text, buffer);
3364 
3365     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3366     text->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "MTEXT" ) );
3367     return text;
3368 }
3369 
getDimension(short dObjectType,unsigned int dObjectSize,const CADCommonED & stCommonEntityData,CADBuffer & buffer)3370 CADDimensionObject * DWGFileR2000::getDimension(short dObjectType,
3371                                                 unsigned int dObjectSize,
3372                                                 const CADCommonED& stCommonEntityData,
3373                                                 CADBuffer &buffer)
3374 {
3375     CADCommonDimensionData stCDD;
3376 
3377     CADVector vectExtrusion = buffer.ReadVector();
3378     stCDD.vectExtrusion = vectExtrusion;
3379 
3380     CADVector vertTextMidPt = buffer.ReadRAWVector();
3381     stCDD.vertTextMidPt = vertTextMidPt;
3382 
3383     stCDD.dfElevation = buffer.ReadBITDOUBLE();
3384     stCDD.dFlags      = buffer.ReadCHAR();
3385 
3386     stCDD.sUserText      = buffer.ReadTV();
3387     stCDD.dfTextRotation = buffer.ReadBITDOUBLE();
3388     stCDD.dfHorizDir     = buffer.ReadBITDOUBLE();
3389 
3390     stCDD.dfInsXScale   = buffer.ReadBITDOUBLE();
3391     stCDD.dfInsYScale   = buffer.ReadBITDOUBLE();
3392     stCDD.dfInsZScale   = buffer.ReadBITDOUBLE();
3393     stCDD.dfInsRotation = buffer.ReadBITDOUBLE();
3394 
3395     stCDD.dAttachmentPoint    = buffer.ReadBITSHORT();
3396     stCDD.dLineSpacingStyle   = buffer.ReadBITSHORT();
3397     stCDD.dfLineSpacingFactor = buffer.ReadBITDOUBLE();
3398     stCDD.dfActualMeasurement = buffer.ReadBITDOUBLE();
3399 
3400     CADVector vert12Pt = buffer.ReadRAWVector();
3401     stCDD.vert12Pt = vert12Pt;
3402 
3403     switch( dObjectType )
3404     {
3405         case CADObject::DIMENSION_ORDINATE:
3406         {
3407             CADDimensionOrdinateObject * dimension = new CADDimensionOrdinateObject();
3408 
3409             dimension->setSize( dObjectSize );
3410             dimension->stCed = stCommonEntityData;
3411             dimension->cdd   = stCDD;
3412 
3413             CADVector vert10pt = buffer.ReadVector();
3414             dimension->vert10pt = vert10pt;
3415 
3416             CADVector vert13pt = buffer.ReadVector();
3417             dimension->vert13pt = vert13pt;
3418 
3419             CADVector vert14pt = buffer.ReadVector();
3420             dimension->vert14pt = vert14pt;
3421 
3422             dimension->Flags2 = buffer.ReadCHAR();
3423 
3424             fillCommonEntityHandleData( dimension, buffer);
3425 
3426             dimension->hDimstyle       = buffer.ReadHANDLE();
3427             dimension->hAnonymousBlock = buffer.ReadHANDLE();
3428 
3429             buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3430             dimension->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "DIM" ) );
3431             return dimension;
3432         }
3433 
3434         case CADObject::DIMENSION_LINEAR:
3435         {
3436             CADDimensionLinearObject * dimension = new CADDimensionLinearObject();
3437 
3438             dimension->setSize( dObjectSize );
3439             dimension->stCed = stCommonEntityData;
3440             dimension->cdd   = stCDD;
3441 
3442             CADVector vert13pt = buffer.ReadVector();
3443             dimension->vert13pt = vert13pt;
3444 
3445             CADVector vert14pt = buffer.ReadVector();
3446             dimension->vert14pt = vert14pt;
3447 
3448             CADVector vert10pt = buffer.ReadVector();
3449             dimension->vert10pt = vert10pt;
3450 
3451             dimension->dfExtLnRot = buffer.ReadBITDOUBLE();
3452             dimension->dfDimRot   = buffer.ReadBITDOUBLE();
3453 
3454             fillCommonEntityHandleData( dimension, buffer);
3455 
3456             dimension->hDimstyle       = buffer.ReadHANDLE();
3457             dimension->hAnonymousBlock = buffer.ReadHANDLE();
3458 
3459             buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3460             dimension->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "DIM" ) );
3461             return dimension;
3462         }
3463 
3464         case CADObject::DIMENSION_ALIGNED:
3465         {
3466             CADDimensionAlignedObject * dimension = new CADDimensionAlignedObject();
3467 
3468             dimension->setSize( dObjectSize );
3469             dimension->stCed = stCommonEntityData;
3470             dimension->cdd   = stCDD;
3471 
3472             CADVector vert13pt = buffer.ReadVector();
3473             dimension->vert13pt = vert13pt;
3474 
3475             CADVector vert14pt = buffer.ReadVector();
3476             dimension->vert14pt = vert14pt;
3477 
3478             CADVector vert10pt = buffer.ReadVector();
3479             dimension->vert10pt = vert10pt;
3480 
3481             dimension->dfExtLnRot = buffer.ReadBITDOUBLE();
3482 
3483             fillCommonEntityHandleData( dimension, buffer);
3484 
3485             dimension->hDimstyle       = buffer.ReadHANDLE();
3486             dimension->hAnonymousBlock = buffer.ReadHANDLE();
3487 
3488             buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3489             dimension->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "DIM" ) );
3490             return dimension;
3491         }
3492 
3493         case CADObject::DIMENSION_ANG_3PT:
3494         {
3495             CADDimensionAngular3PtObject * dimension = new CADDimensionAngular3PtObject();
3496 
3497             dimension->setSize( dObjectSize );
3498             dimension->stCed = stCommonEntityData;
3499             dimension->cdd   = stCDD;
3500 
3501             CADVector vert10pt = buffer.ReadVector();
3502             dimension->vert10pt = vert10pt;
3503 
3504             CADVector vert13pt = buffer.ReadVector();
3505             dimension->vert13pt = vert13pt;
3506 
3507             CADVector vert14pt = buffer.ReadVector();
3508             dimension->vert14pt = vert14pt;
3509 
3510             CADVector vert15pt = buffer.ReadVector();
3511             dimension->vert15pt = vert15pt;
3512 
3513             fillCommonEntityHandleData( dimension, buffer );
3514 
3515             dimension->hDimstyle       = buffer.ReadHANDLE();
3516             dimension->hAnonymousBlock = buffer.ReadHANDLE();
3517 
3518             buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3519             dimension->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "DIM" ) );
3520             return dimension;
3521         }
3522 
3523         case CADObject::DIMENSION_ANG_2LN:
3524         {
3525             CADDimensionAngular2LnObject * dimension = new CADDimensionAngular2LnObject();
3526 
3527             dimension->setSize( dObjectSize );
3528             dimension->stCed = stCommonEntityData;
3529             dimension->cdd   = stCDD;
3530 
3531             CADVector vert16pt = buffer.ReadVector();
3532             dimension->vert16pt = vert16pt;
3533 
3534             CADVector vert13pt = buffer.ReadVector();
3535             dimension->vert13pt = vert13pt;
3536 
3537             CADVector vert14pt = buffer.ReadVector();
3538             dimension->vert14pt = vert14pt;
3539 
3540             CADVector vert15pt = buffer.ReadVector();
3541             dimension->vert15pt = vert15pt;
3542 
3543             CADVector vert10pt = buffer.ReadVector();
3544             dimension->vert10pt = vert10pt;
3545 
3546             fillCommonEntityHandleData( dimension, buffer);
3547 
3548             dimension->hDimstyle       = buffer.ReadHANDLE();
3549             dimension->hAnonymousBlock = buffer.ReadHANDLE();
3550 
3551             buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3552             dimension->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "DIM" ) );
3553             return dimension;
3554         }
3555 
3556         case CADObject::DIMENSION_RADIUS:
3557         {
3558             CADDimensionRadiusObject * dimension = new CADDimensionRadiusObject();
3559 
3560             dimension->setSize( dObjectSize );
3561             dimension->stCed = stCommonEntityData;
3562             dimension->cdd   = stCDD;
3563 
3564             CADVector vert10pt = buffer.ReadVector();
3565             dimension->vert10pt = vert10pt;
3566 
3567             CADVector vert15pt = buffer.ReadVector();
3568             dimension->vert15pt = vert15pt;
3569 
3570             dimension->dfLeaderLen = buffer.ReadBITDOUBLE();
3571 
3572             fillCommonEntityHandleData( dimension, buffer);
3573 
3574             dimension->hDimstyle       = buffer.ReadHANDLE();
3575             dimension->hAnonymousBlock = buffer.ReadHANDLE();
3576 
3577             buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3578             dimension->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "DIM" ) );
3579             return dimension;
3580         }
3581 
3582         case CADObject::DIMENSION_DIAMETER:
3583         {
3584             CADDimensionDiameterObject * dimension = new CADDimensionDiameterObject();
3585 
3586             dimension->setSize( dObjectSize );
3587             dimension->stCed = stCommonEntityData;
3588             dimension->cdd   = stCDD;
3589 
3590             CADVector vert15pt = buffer.ReadVector();
3591             dimension->vert15pt = vert15pt;
3592 
3593             CADVector vert10pt = buffer.ReadVector();
3594             dimension->vert10pt = vert10pt;
3595 
3596             dimension->dfLeaderLen = buffer.ReadBITDOUBLE();
3597 
3598             fillCommonEntityHandleData( dimension, buffer);
3599 
3600             dimension->hDimstyle       = buffer.ReadHANDLE();
3601             dimension->hAnonymousBlock = buffer.ReadHANDLE();
3602 
3603             buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3604             dimension->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "DIM" ) );
3605             return dimension;
3606         }
3607     }
3608     return nullptr;
3609 }
3610 
getImageDef(unsigned int dObjectSize,CADBuffer & buffer)3611 CADImageDefObject * DWGFileR2000::getImageDef(unsigned int dObjectSize,
3612                                               CADBuffer &buffer)
3613 {
3614     CADImageDefObject * imagedef = new CADImageDefObject();
3615 
3616     if(!readBasicData(imagedef, dObjectSize, buffer))
3617     {
3618         delete imagedef;
3619         return nullptr;
3620     }
3621 
3622     imagedef->dClassVersion = buffer.ReadBITLONG();
3623 
3624     imagedef->dfXImageSizeInPx = buffer.ReadRAWDOUBLE();
3625     imagedef->dfYImageSizeInPx = buffer.ReadRAWDOUBLE();
3626 
3627     imagedef->sFilePath = buffer.ReadTV();
3628     imagedef->bIsLoaded = buffer.ReadBIT();
3629 
3630     imagedef->dResUnits = buffer.ReadCHAR();
3631 
3632     imagedef->dfXPixelSize = buffer.ReadRAWDOUBLE();
3633     imagedef->dfYPixelSize = buffer.ReadRAWDOUBLE();
3634 
3635     imagedef->hParentHandle = buffer.ReadHANDLE();
3636 
3637     for( long i = 0; i < imagedef->nNumReactors; ++i )
3638     {
3639         imagedef->hReactors.push_back( buffer.ReadHANDLE() );
3640         if( buffer.IsEOB() )
3641         {
3642             delete imagedef;
3643             return nullptr;
3644         }
3645     }
3646 
3647     imagedef->hXDictionary = buffer.ReadHANDLE();
3648 
3649     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3650     imagedef->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "IMAGEDEF" ) );
3651 
3652     return imagedef;
3653 }
3654 
getImageDefReactor(unsigned int dObjectSize,CADBuffer & buffer)3655 CADImageDefReactorObject * DWGFileR2000::getImageDefReactor(unsigned int dObjectSize, CADBuffer &buffer)
3656 {
3657     CADImageDefReactorObject * imagedefreactor = new CADImageDefReactorObject();
3658 
3659     if(!readBasicData(imagedefreactor, dObjectSize, buffer))
3660     {
3661         delete imagedefreactor;
3662         return nullptr;
3663     }
3664 
3665     imagedefreactor->dClassVersion = buffer.ReadBITLONG();
3666 
3667     imagedefreactor->hParentHandle =buffer.ReadHANDLE();
3668 
3669     for( long i = 0; i < imagedefreactor->nNumReactors; ++i )
3670     {
3671         imagedefreactor->hReactors.push_back( buffer.ReadHANDLE() );
3672         if( buffer.IsEOB() )
3673         {
3674             delete imagedefreactor;
3675             return nullptr;
3676         }
3677     }
3678 
3679     imagedefreactor->hXDictionary = buffer.ReadHANDLE();
3680 
3681     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3682     imagedefreactor->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "IMAGEDEFREFACTOR" ) );
3683 
3684     return imagedefreactor;
3685 }
3686 
getXRecord(unsigned int dObjectSize,CADBuffer & buffer)3687 CADXRecordObject * DWGFileR2000::getXRecord(unsigned int dObjectSize, CADBuffer &buffer)
3688 {
3689     CADXRecordObject * xrecord = new CADXRecordObject();
3690 
3691     if(!readBasicData(xrecord, dObjectSize, buffer))
3692     {
3693         delete xrecord;
3694         return nullptr;
3695     }
3696 
3697     xrecord->nNumDataBytes = buffer.ReadBITLONG();
3698     if(xrecord->nNumDataBytes < 0)
3699     {
3700         delete xrecord;
3701         return nullptr;
3702     }
3703     for( long i = 0; i < xrecord->nNumDataBytes; ++i )
3704     {
3705         xrecord->abyDataBytes.push_back( buffer.ReadCHAR() );
3706         if( buffer.IsEOB() )
3707         {
3708             delete xrecord;
3709             return nullptr;
3710         }
3711     }
3712 
3713     xrecord->dCloningFlag = buffer.ReadBITSHORT();
3714 
3715     short dIndicatorNumber = buffer.ReadRAWSHORT();
3716     if( dIndicatorNumber == 1 )
3717     {
3718         unsigned char nStringSize = buffer.ReadCHAR();
3719         /* char dCodePage   =  */ buffer.ReadCHAR();
3720         for( unsigned char i = 0; i < nStringSize; ++i )
3721         {
3722             buffer.ReadCHAR();
3723         }
3724     }
3725     else if( dIndicatorNumber == 70 )
3726     {
3727         buffer.ReadRAWSHORT();
3728     }
3729     else if( dIndicatorNumber == 10 )
3730     {
3731         buffer.ReadRAWDOUBLE();
3732         buffer.ReadRAWDOUBLE();
3733         buffer.ReadRAWDOUBLE();
3734     }
3735     else if( dIndicatorNumber == 40 )
3736     {
3737         buffer.ReadRAWDOUBLE();
3738     }
3739 
3740     xrecord->hParentHandle = buffer.ReadHANDLE();
3741 
3742     for( long i = 0; i < xrecord->nNumReactors; ++i )
3743     {
3744         xrecord->hReactors.push_back( buffer.ReadHANDLE() );
3745         if( buffer.IsEOB() )
3746         {
3747             delete xrecord;
3748             return nullptr;
3749         }
3750     }
3751 
3752     xrecord->hXDictionary = buffer.ReadHANDLE();
3753 
3754     size_t dObjectSizeBit = (dObjectSize + 4) * 8;
3755     while( buffer.PositionBit() < dObjectSizeBit )
3756     {
3757         xrecord->hObjIdHandles.push_back( buffer.ReadHANDLE() );
3758     }
3759 
3760     buffer.Seek((dObjectSize - 2) * 8, CADBuffer::BEG);
3761     xrecord->setCRC( validateEntityCRC( buffer, dObjectSize - 2, "XRECORD" ) );
3762 
3763     return xrecord;
3764 }
3765 
fillCommonEntityHandleData(CADEntityObject * pEnt,CADBuffer & buffer)3766 void DWGFileR2000::fillCommonEntityHandleData(CADEntityObject * pEnt,
3767                                               CADBuffer& buffer)
3768 {
3769     if( pEnt->stCed.bbEntMode == 0 )
3770         pEnt->stChed.hOwner = buffer.ReadHANDLE();
3771 
3772     // TODO: Need some reasonable nNumReactors limits.
3773     if(pEnt->stCed.nNumReactors < 0 || pEnt->stCed.nNumReactors > 5000)
3774     {
3775         // Something wrong occurred
3776         return;
3777     }
3778     for( long i = 0; i < pEnt->stCed.nNumReactors; ++i )
3779         pEnt->stChed.hReactors.push_back( buffer.ReadHANDLE() );
3780 
3781     pEnt->stChed.hXDictionary = buffer.ReadHANDLE();
3782 
3783     if( !pEnt->stCed.bNoLinks )
3784     {
3785         pEnt->stChed.hPrevEntity = buffer.ReadHANDLE();
3786         pEnt->stChed.hNextEntity = buffer.ReadHANDLE();
3787     }
3788 
3789     pEnt->stChed.hLayer = buffer.ReadHANDLE();
3790 
3791     if( pEnt->stCed.bbLTypeFlags == 0x03 )
3792         pEnt->stChed.hLType = buffer.ReadHANDLE();
3793 
3794     if( pEnt->stCed.bbPlotStyleFlags == 0x03 )
3795         pEnt->stChed.hPlotStyle = buffer.ReadHANDLE();
3796 }
3797 
DWGFileR2000(CADFileIO * poFileIO)3798 DWGFileR2000::DWGFileR2000( CADFileIO * poFileIO ) :
3799     CADFile( poFileIO ),
3800     imageSeeker(0)
3801 {
3802     oHeader.addValue( CADHeader::OPENCADVER, CADVersions::DWG_R2000 );
3803 }
3804 
ReadSectionLocators()3805 int DWGFileR2000::ReadSectionLocators()
3806 {
3807     char  abyBuf[255] = { 0 };
3808     int   dImageSeeker = 0, SLRecordsCount = 0;
3809     short dCodePage = 0;
3810 
3811     pFileIO->Rewind();
3812     memset( abyBuf, 0, DWG_VERSION_STR_SIZE + 1 );
3813     pFileIO->Read( abyBuf, DWG_VERSION_STR_SIZE );
3814     oHeader.addValue( CADHeader::ACADVER, abyBuf );
3815     memset( abyBuf, 0, 8 );
3816     pFileIO->Read( abyBuf, 7 );
3817     oHeader.addValue( CADHeader::ACADMAINTVER, abyBuf );
3818     // TODO: code can be much simplified if CADHandle will be used.
3819     pFileIO->Read( & dImageSeeker, 4 );
3820     FromLSB(dImageSeeker);
3821     // to do so, == and ++ operators should be implemented.
3822     DebugMsg( "Image seeker read: %d\n", dImageSeeker );
3823     imageSeeker = dImageSeeker;
3824 
3825     pFileIO->Seek( 2, CADFileIO::SeekOrigin::CUR ); // 19
3826     pFileIO->Read( & dCodePage, 2 );
3827     FromLSB(dCodePage);
3828     oHeader.addValue( CADHeader::DWGCODEPAGE, dCodePage );
3829 
3830     DebugMsg( "DWG Code page: %d\n", dCodePage );
3831 
3832     pFileIO->Read( & SLRecordsCount, 4 ); // 21
3833     FromLSB(SLRecordsCount);
3834     // Last vertex is reached. read it and break reading.
3835     DebugMsg( "Section locator records count: %d\n", SLRecordsCount );
3836 
3837     for( size_t i = 0; i < static_cast<size_t>(SLRecordsCount); ++i )
3838     {
3839         SectionLocatorRecord readRecord;
3840         if( pFileIO->Read( & readRecord.byRecordNumber, 1 ) != 1 ||
3841             pFileIO->Read( & readRecord.dSeeker, 4 ) != 4 ||
3842             pFileIO->Read( & readRecord.dSize, 4 ) != 4 )
3843         {
3844             return CADErrorCodes::HEADER_SECTION_READ_FAILED;
3845         }
3846         FromLSB(readRecord.dSeeker);
3847         FromLSB(readRecord.dSize);
3848 
3849         sectionLocatorRecords.push_back( readRecord );
3850         DebugMsg( "  Record #%d : %d %d\n", sectionLocatorRecords[i].byRecordNumber, sectionLocatorRecords[i].dSeeker,
3851                   sectionLocatorRecords[i].dSize );
3852     }
3853     if( sectionLocatorRecords.size() < 3 )
3854         return CADErrorCodes::HEADER_SECTION_READ_FAILED;
3855 
3856     return CADErrorCodes::SUCCESS;
3857 }
3858 
GetNOD()3859 CADDictionary DWGFileR2000::GetNOD()
3860 {
3861     CADDictionary stNOD;
3862     unique_ptr<CADObject> pCADDictionaryObject( GetObject( oTables.GetTableHandle(
3863                                   CADTables::NamedObjectsDict ).getAsLong() ) );
3864 
3865     CADDictionaryObject* spoNamedDictObj =
3866             dynamic_cast<CADDictionaryObject*>( pCADDictionaryObject.get() );
3867     if( !spoNamedDictObj )
3868     {
3869         return stNOD;
3870     }
3871 
3872     for( size_t i = 0; i < spoNamedDictObj->sItemNames.size(); ++i )
3873     {
3874         unique_ptr<CADObject> spoDictRecord (
3875                     GetObject( spoNamedDictObj->hItemHandles[i].getAsLong() ) );
3876 
3877         if( spoDictRecord == nullptr )
3878             continue; // Skip unread objects
3879 
3880         if( spoDictRecord->getType() == CADObject::DICTIONARY )
3881         {
3882             // TODO: add implementation of DICTIONARY reading
3883         }
3884         else if( spoDictRecord->getType() == CADObject::XRECORD )
3885         {
3886             CADXRecord * cadxRecord = new CADXRecord();
3887             CADXRecordObject * cadxRecordObject =
3888                 static_cast<CADXRecordObject*>(spoDictRecord.get());
3889 
3890             string xRecordData( cadxRecordObject->abyDataBytes.begin(),
3891                                 cadxRecordObject->abyDataBytes.end() );
3892             cadxRecord->setRecordData( xRecordData );
3893 
3894             shared_ptr<CADDictionaryRecord> cadxRecordPtr(static_cast<CADDictionaryRecord*>(cadxRecord));
3895 
3896             stNOD.addRecord( make_pair( spoNamedDictObj->sItemNames[i], cadxRecordPtr ) );
3897         }
3898     }
3899 
3900     return stNOD;
3901 }
3902 
validateEntityCRC(CADBuffer & buffer,unsigned int dObjectSize,const char * entityName,bool bSwapEndianness)3903 unsigned short DWGFileR2000::validateEntityCRC(CADBuffer& buffer,
3904                                                unsigned int dObjectSize,
3905                                                const char * entityName,
3906                                                bool bSwapEndianness )
3907 {
3908     unsigned short CRC = static_cast<unsigned short>(buffer.ReadRAWSHORT());
3909     if(bSwapEndianness)
3910     {
3911         SwapEndianness(CRC, sizeof (CRC));
3912     }
3913 
3914     buffer.Seek(0, CADBuffer::BEG);
3915     const unsigned short initial = 0xC0C1;
3916     const unsigned short calculated =
3917             CalculateCRC8(initial, static_cast<const char*>(buffer.GetRawBuffer()),
3918                           static_cast<int>(dObjectSize) );
3919     if( CRC != calculated )
3920     {
3921         DebugMsg( "Invalid CRC for %s object\nCRC read:0x%X calculated:0x%X\n",
3922                                                   entityName, CRC, calculated );
3923         return 0; // If CRC equal 0 - this is error
3924     }
3925     return CRC;
3926 }
3927 
readBasicData(CADBaseControlObject * pBaseControlObject,unsigned int dObjectSize,CADBuffer & buffer)3928 bool DWGFileR2000::readBasicData(CADBaseControlObject *pBaseControlObject,
3929                            unsigned int dObjectSize,
3930                            CADBuffer &buffer)
3931 {
3932     pBaseControlObject->setSize( dObjectSize );
3933     pBaseControlObject->nObjectSizeInBits = buffer.ReadRAWLONG();
3934     pBaseControlObject->hObjectHandle = buffer.ReadHANDLE();
3935     short  dEEDSize = 0;
3936     CADEed dwgEed;
3937     while( ( dEEDSize = buffer.ReadBITSHORT() ) != 0 )
3938     {
3939         dwgEed.dLength = dEEDSize;
3940         dwgEed.hApplication = buffer.ReadHANDLE();
3941 
3942         if(dEEDSize > 0)
3943         {
3944             for( short i = 0; i < dEEDSize; ++i )
3945             {
3946                 dwgEed.acData.push_back( buffer.ReadCHAR() );
3947             }
3948         }
3949 
3950         pBaseControlObject->aEED.push_back( dwgEed );
3951     }
3952 
3953     pBaseControlObject->nNumReactors = buffer.ReadBITLONG();
3954     // TODO: Need reasonable nNumReactors limits.
3955     if(pBaseControlObject->nNumReactors < 0 ||
3956        pBaseControlObject->nNumReactors > 5000)
3957     {
3958         return false;
3959     }
3960     return true;
3961 }
3962