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