1 /******************************************************************************
2 ** libDXFrw - Library to read/write DXF files (ascii & binary) **
3 ** **
4 ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com **
5 ** **
6 ** This library is free software, licensed under the terms of the GNU **
7 ** General Public License as published by the Free Software Foundation, **
8 ** either version 2 of the License, or (at your option) any later version. **
9 ** You should have received a copy of the GNU General Public License **
10 ** along with this program. If not, see <http://www.gnu.org/licenses/>. **
11 ******************************************************************************/
12
13 #ifndef DRW_BASE_H
14 #define DRW_BASE_H
15
16 #define DRW_VERSION "0.6.3"
17
18 #include <string>
19 #include <list>
20 #include <cmath>
21 #include <QtGlobal>
22 #include <ciso646>
23
24 #ifdef DRW_ASSERTS
25 # define drw_assert(a) assert(a)
26 #else
27 # define drw_assert(a)
28 #endif
29
30 #define UTF8STRING std::string
31 #define DRW_UNUSED(x) (void)x
32
33 #if defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
34 # define DRW_WIN
35 #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
36 # define DRW_WIN
37 #elif defined(__MWERKS__) && defined(__INTEL__)
38 # define DRW_WIN
39 #else
40 # define DRW_POSIX
41 #endif
42
43 #ifndef M_PI
44 #define M_PI 3.141592653589793238462643
45 #endif
46 #ifndef M_PI_2
47 #define M_PI_2 1.57079632679489661923
48 #endif
49 #define M_PIx2 6.283185307179586 // 2*PI
50 #define ARAD 57.29577951308232
51
52 #ifndef __has_cpp_attribute
53 # define __has_cpp_attribute(x) 0
54 #endif
55
56 #if QT_VERSION < QT_VERSION_CHECK(5, 8, 0)
57
58 #ifndef QT_HAS_CPP_ATTRIBUTE
59 #ifdef __has_cpp_attribute
60 # define QT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
61 #else
62 # define QT_HAS_CPP_ATTRIBUTE(x) 0
63 #endif
64 #endif // QT_HAS_CPP_ATTRIBUTE
65
66 #if defined(__cplusplus)
67 #if QT_HAS_CPP_ATTRIBUTE(clang::fallthrough)
68 # define Q_FALLTHROUGH() [[clang::fallthrough]]
69 #elif QT_HAS_CPP_ATTRIBUTE(gnu::fallthrough)
70 # define Q_FALLTHROUGH() [[gnu::fallthrough]]
71 #elif QT_HAS_CPP_ATTRIBUTE(fallthrough)
72 # define Q_FALLTHROUGH() [[fallthrough]]
73 #endif
74 #endif
75 #ifndef Q_FALLTHROUGH
76 # if (defined(Q_CC_GNU) && Q_CC_GNU >= 700) && !defined(Q_CC_INTEL)
77 # define Q_FALLTHROUGH() __attribute__((fallthrough))
78 # else
79 # define Q_FALLTHROUGH() (void)0
80 #endif
81 #endif // defined(__cplusplus)
82 #endif // QT_VERSION < QT_VERSION_CHECK(5, 8, 0)
83
84 typedef signed char dint8; /* 8 bit signed */
85 typedef signed short dint16; /* 16 bit signed */
86 typedef signed int dint32; /* 32 bit signed */
87 typedef long long int dint64; /* 64 bit signed */
88
89 typedef unsigned char duint8; /* 8 bit unsigned */
90 typedef unsigned short duint16; /* 16 bit unsigned */
91 typedef unsigned int duint32; /* 32 bit unsigned */
92 typedef unsigned long long int duint64; /* 64 bit unsigned */
93
94 typedef float dfloat32; /* 32 bit floating point */
95 typedef double ddouble64; /* 64 bit floating point */
96 typedef long double ddouble80; /* 80 bit floating point */
97
98
99 namespace DRW {
100
101 //! Version numbers for the DXF Format.
102 enum Version {
103 UNKNOWNV, /*!< UNKNOWN VERSION. */
104 AC1006, /*!< R10. */
105 AC1009, /*!< R11 & R12. */
106 AC1012, /*!< R13. */
107 AC1014, /*!< R14. */
108 AC1015, /*!< ACAD 2000. */
109 AC1018, /*!< ACAD 2004. */
110 AC1021, /*!< ACAD 2007. */
111 AC1024, /*!< ACAD 2010. */
112 AC1027 /*!< ACAD 2013. */
113 };
114
115 enum error {
116 BAD_NONE, /*!< No error. */
117 BAD_UNKNOWN, /*!< UNKNOWN. */
118 BAD_OPEN, /*!< error opening file. */
119 BAD_VERSION, /*!< unsupported version. */
120 BAD_READ_METADATA, /*!< error reading matadata. */
121 BAD_READ_FILE_HEADER, /*!< error in file header read process. */
122 BAD_READ_HEADER, /*!< error in header vars read process. */
123 BAD_READ_HANDLES, /*!< error in object map read process. */
124 BAD_READ_CLASSES, /*!< error in classes read process. */
125 BAD_READ_TABLES, /*!< error in tables read process. */
126 BAD_READ_BLOCKS, /*!< error in block read process. */
127 BAD_READ_ENTITIES, /*!< error in entities read process. */
128 BAD_READ_OBJECTS /*!< error in objects read process. */
129 };
130
131 enum DBG_LEVEL {
132 NONE,
133 DEBUG
134 };
135
136 //! Special codes for colors
137 enum ColorCodes {
138 black = 250,
139 green = 3,
140 red = 1,
141 brown = 15,
142 yellow = 2,
143 cyan = 4,
144 magenta = 6,
145 gray = 8,
146 blue = 5,
147 l_blue = 163,
148 l_green = 121,
149 l_cyan = 131,
150 l_red = 23,
151 l_magenta = 221,
152 l_gray = 252,
153 white = 7,
154 ColorByLayer = 256,
155 ColorByBlock = 0
156 };
157
158 //! Spaces
159 enum Space {
160 ModelSpace = 0,
161 PaperSpace = 1
162 };
163
164 //! Special kinds of handles
165 enum HandleCodes {
166 NoHandle = 0
167 };
168
169 //! Shadow mode
170 enum ShadowMode {
171 CastAndReceieveShadows = 0,
172 CastShadows = 1,
173 ReceiveShadows = 2,
174 IgnoreShadows = 3
175 };
176
177 //! Special kinds of materials
178 enum MaterialCodes {
179 MaterialByLayer = 0
180 };
181
182 //! Special kinds of plot styles
183 enum PlotStyleCodes {
184 DefaultPlotStyle = 0
185 };
186
187 //! Special kinds of transparencies
188 enum TransparencyCodes {
189 Opaque = 0,
190 Transparent = -1
191 };
192
193 } // namespace DRW
194
195 Q_REQUIRED_RESULT static inline bool DRW_FuzzyComparePossibleNulls(double p1, double p2);
DRW_FuzzyComparePossibleNulls(double p1,double p2)196 static inline bool DRW_FuzzyComparePossibleNulls(double p1, double p2)
197 {
198 if(qFuzzyIsNull(p1))
199 {
200 return qFuzzyIsNull(p2);
201 }
202 else if(qFuzzyIsNull(p2))
203 {
204 return false;
205 }
206 else
207 {
208 return qFuzzyCompare(p1, p2);
209 }
210 }
211
212 //! Class to handle 3D coordinate point
213 /*!
214 * Class to handle 3D coordinate point
215 * @author Rallaz
216 */
217 class DRW_Coord {
218 public:
DRW_Coord()219 DRW_Coord()
220 : x(0),
221 y(0),
222 z(0)
223 {}
DRW_Coord(double ix,double iy,double iz)224 DRW_Coord(double ix, double iy, double iz)
225 : x(ix),
226 y(iy),
227 z(iz)
228 {}
229
DRW_Coord(const DRW_Coord & data)230 DRW_Coord(const DRW_Coord &data)
231 : x(data.x),
232 y(data.y),
233 z(data.z)
234 {}
235
236 DRW_Coord &operator = (const DRW_Coord& data)
237 {
238 if ( &data == this )
239 {
240 return *this;
241 }
242
243 x = data.x;
244 y = data.y;
245 z = data.z;
246 return *this;
247 }
248 /*!< convert to unitary vector */
unitize()249 void unitize(){
250 double dist;
251 dist = sqrt(x*x + y*y + z*z);
252 if (dist > 0.0) {
253 x= x/dist;
254 y= y/dist;
255 z= z/dist;
256 }
257 }
258
259 public:
260 double x;
261 double y;
262 double z;
263 };
264
265
266 //! Class to handle vertex
267 /*!
268 * Class to handle vertex for lwpolyline entity
269 * @author Rallaz
270 */
271 class DRW_Vertex2D {
272 public:
DRW_Vertex2D()273 DRW_Vertex2D()
274 : x(),
275 y(),
276 stawidth(0),
277 endwidth(0),
278 bulge(0)
279 {
280 // eType = DRW::LWPOLYLINE;
281 }
282 DRW_Vertex2D(double sx, double sy, double b = 0.0)
x(sx)283 : x(sx),
284 y(sy),
285 stawidth(0),
286 endwidth(0),
287 bulge(b)
288 {}
289
290 public:
291 double x; /*!< x coordinate, code 10 */
292 double y; /*!< y coordinate, code 20 */
293 double stawidth; /*!< Start width, code 40 */
294 double endwidth; /*!< End width, code 41 */
295 double bulge; /*!< bulge, code 42 */
296 };
297
298
299 //! Class to handle header vars
300 /*!
301 * Class to handle header vars
302 * @author Rallaz
303 */
304 class DRW_Variant {
305 public:
306 enum TYPE {
307 STRING,
308 INTEGER,
309 DOUBLE,
310 COORD,
311 INVALID
312 };
313 //TODO: add INT64 support
DRW_Variant()314 DRW_Variant()
315 : content(),
316 type(INVALID),
317 code(),
318 sdata(),
319 vdata()
320 {}
321
DRW_Variant(int c,dint32 i)322 DRW_Variant(int c, dint32 i)
323 : content(),
324 type(),
325 code(c),
326 sdata(),
327 vdata()
328 {
329 addInt(i);
330 }
331
DRW_Variant(int c,duint32 i)332 DRW_Variant(int c, duint32 i)
333 : content(),
334 type(),
335 code(c),
336 sdata(),
337 vdata()
338 {
339 addInt(static_cast<dint32>(i));//RLZ: verify if work with big numbers
340 }
341
DRW_Variant(int c,double d)342 DRW_Variant(int c, double d)
343 : content(),
344 type(),
345 code(c),
346 sdata(),
347 vdata()
348 {
349 addDouble(d);
350 }
351
DRW_Variant(int c,const UTF8STRING & s)352 DRW_Variant(int c, const UTF8STRING &s)
353 : content(),
354 type(),
355 code(c),
356 sdata(),
357 vdata()
358 {
359 addString(s);
360 }
361
DRW_Variant(int c,const DRW_Coord & crd)362 DRW_Variant(int c, const DRW_Coord &crd)
363 : content(),
364 type(),
365 code(c),
366 sdata(),
367 vdata()
368 {
369 addCoord(crd);
370 }
371
DRW_Variant(const DRW_Variant & d)372 DRW_Variant(const DRW_Variant& d)
373 : content(d.content),
374 type(d.type),
375 code(d.code),
376 sdata(),
377 vdata()
378 {
379 if (d.type == COORD)
380 {
381 vdata = d.vdata;
382 content.v = &vdata;
383 }
384
385 if (d.type == STRING)
386 {
387 sdata = d.sdata;
388 content.s = &sdata;
389 }
390 }
391
392 ~DRW_Variant() = default;
393
addString(const UTF8STRING & s)394 void addString(const UTF8STRING &s) {setType(STRING); sdata = s; content.s = &sdata;}
addInt(int i)395 void addInt(int i) {setType(INTEGER); content.i = i;}
addDouble(double d)396 void addDouble(double d) {setType(DOUBLE); content.d = d;}
addCoord()397 void addCoord() {setType(COORD); vdata.x=0.0; vdata.y=0.0; vdata.z=0.0; content.v = &vdata;}
addCoord(const DRW_Coord & v)398 void addCoord(const DRW_Coord &v) {setType(COORD); vdata = v; content.v = &vdata;}
setType(enum TYPE t)399 void setType(enum TYPE t) { type = t;}
setCoordX(double d)400 void setCoordX(double d) { if (type == COORD) vdata.x = d;}
setCoordY(double d)401 void setCoordY(double d) { if (type == COORD) vdata.y = d;}
setCoordZ(double d)402 void setCoordZ(double d) { if (type == COORD) vdata.z = d;}
403
404 private:
405 typedef union {
406 UTF8STRING *s;
407 dint32 i;
408 double d;
409 DRW_Coord *v;
410 } DRW_VarContent;
411
412 public:
413 DRW_VarContent content;
414 enum TYPE type;
415 int code; /*!< dxf code of this value*/
416
417 private:
418 DRW_Variant &operator=(const DRW_Variant &) Q_DECL_EQ_DELETE;
419 std::string sdata;
420 DRW_Coord vdata;
421 };
422
423 //! Class to convert between line width and integer
424 /*!
425 * Class to convert between line width and integer
426 * verifing valid values, if value is not valid
427 * returns widthDefault.
428 * @author Rallaz
429 */
430 class DRW_LW_Conv{
431 public:
432 enum lineWidth {
433 width00 = 0, /*!< 0.00mm (dxf 0)*/
434 width01 = 1, /*!< 0.05mm (dxf 5)*/
435 width02 = 2, /*!< 0.09mm (dxf 9)*/
436 width03 = 3, /*!< 0.13mm (dxf 13)*/
437 width04 = 4, /*!< 0.15mm (dxf 15)*/
438 width05 = 5, /*!< 0.18mm (dxf 18)*/
439 width06 = 6, /*!< 0.20mm (dxf 20)*/
440 width07 = 7, /*!< 0.25mm (dxf 25)*/
441 width08 = 8, /*!< 0.30mm (dxf 30)*/
442 width09 = 9, /*!< 0.35mm (dxf 35)*/
443 width10 = 10, /*!< 0.40mm (dxf 40)*/
444 width11 = 11, /*!< 0.50mm (dxf 50)*/
445 width12 = 12, /*!< 0.53mm (dxf 53)*/
446 width13 = 13, /*!< 0.60mm (dxf 60)*/
447 width14 = 14, /*!< 0.70mm (dxf 70)*/
448 width15 = 15, /*!< 0.80mm (dxf 80)*/
449 width16 = 16, /*!< 0.90mm (dxf 90)*/
450 width17 = 17, /*!< 1.00mm (dxf 100)*/
451 width18 = 18, /*!< 1.06mm (dxf 106)*/
452 width19 = 19, /*!< 1.20mm (dxf 120)*/
453 width20 = 20, /*!< 1.40mm (dxf 140)*/
454 width21 = 21, /*!< 1.58mm (dxf 158)*/
455 width22 = 22, /*!< 2.00mm (dxf 200)*/
456 width23 = 23, /*!< 2.11mm (dxf 211)*/
457 widthByLayer = 29, /*!< by layer (dxf -1) */
458 widthByBlock = 30, /*!< by block (dxf -2) */
459 widthDefault = 31 /*!< by default (dxf -3) */
460 };
461
lineWidth2dxfInt(enum lineWidth lw)462 static int lineWidth2dxfInt(enum lineWidth lw){
463 switch (lw){
464 case widthByLayer:
465 return -1;
466 case widthByBlock:
467 return -2;
468 case widthDefault:
469 return -3;
470 case width00:
471 return 0;
472 case width01:
473 return 5;
474 case width02:
475 return 9;
476 case width03:
477 return 13;
478 case width04:
479 return 15;
480 case width05:
481 return 18;
482 case width06:
483 return 20;
484 case width07:
485 return 25;
486 case width08:
487 return 30;
488 case width09:
489 return 35;
490 case width10:
491 return 40;
492 case width11:
493 return 50;
494 case width12:
495 return 53;
496 case width13:
497 return 60;
498 case width14:
499 return 70;
500 case width15:
501 return 80;
502 case width16:
503 return 90;
504 case width17:
505 return 100;
506 case width18:
507 return 106;
508 case width19:
509 return 120;
510 case width20:
511 return 140;
512 case width21:
513 return 158;
514 case width22:
515 return 200;
516 case width23:
517 return 211;
518 default:
519 break;
520 }
521 return -3;
522 }
523
dxfInt2lineWidth(int i)524 static enum lineWidth dxfInt2lineWidth(int i){
525 if (i<0) {
526 if (i==-1)
527 return widthByLayer;
528 else if (i==-2)
529 return widthByBlock;
530 else if (i==-3)
531 return widthDefault;
532 } else if (i<3) {
533 return width00;
534 } else if (i<7) {
535 return width01;
536 } else if (i<11) {
537 return width02;
538 } else if (i<14) {
539 return width03;
540 } else if (i<16) {
541 return width04;
542 } else if (i<19) {
543 return width05;
544 } else if (i<22) {
545 return width06;
546 } else if (i<27) {
547 return width07;
548 } else if (i<32) {
549 return width08;
550 } else if (i<37) {
551 return width09;
552 } else if (i<45) {
553 return width10;
554 } else if (i<52) {
555 return width11;
556 } else if (i<57) {
557 return width12;
558 } else if (i<65) {
559 return width13;
560 } else if (i<75) {
561 return width14;
562 } else if (i<85) {
563 return width15;
564 } else if (i<95) {
565 return width16;
566 } else if (i<103) {
567 return width17;
568 } else if (i<112) {
569 return width18;
570 } else if (i<130) {
571 return width19;
572 } else if (i<149) {
573 return width20;
574 } else if (i<180) {
575 return width21;
576 } else if (i<205) {
577 return width22;
578 } else {
579 return width23;
580 }
581 //default by default
582 return widthDefault;
583 }
584 };
585
586 #endif
587
588 // EOF
589