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