]> Shamusworld >> Repos - architektonas/blob - dxflib/src/dl_dxf.cpp
Refactored CAD tool bars to use predefined actions.
[architektonas] / dxflib / src / dl_dxf.cpp
1 /****************************************************************************
2 ** $Id: dl_dxf.cpp 2398 2005-06-06 18:12:14Z andrew $
3 **
4 ** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
5 **
6 ** This file is part of the dxflib project.
7 **
8 ** This file may be distributed and/or modified under the terms of the
9 ** GNU General Public License version 2 as published by the Free Software
10 ** Foundation and appearing in the file LICENSE.GPL included in the
11 ** packaging of this file.
12 **
13 ** Licensees holding valid dxflib Professional Edition licenses may use 
14 ** this file in accordance with the dxflib Commercial License
15 ** Agreement provided with the Software.
16 **
17 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 **
20 ** See http://www.ribbonsoft.com for further details.
21 **
22 ** Contact info@ribbonsoft.com if any conditions of this licensing are
23 ** not clear to you.
24 **
25 **********************************************************************/
26
27 #include "dl_dxf.h"
28
29 #include <algorithm>
30 #include <string>
31 #include <cstdio>
32 #include <cassert>
33 #include <cmath>
34
35 #include "dl_attributes.h"
36 #include "dl_codes.h"
37 #include "dl_creationinterface.h"
38 #include "dl_writer_ascii.h"
39
40
41 /**
42  * Default constructor.
43  */
44 DL_Dxf::DL_Dxf() {
45     styleHandleStd = 0;
46     version = VER_2000;
47
48     vertices = NULL;
49     maxVertices = 0;
50     vertexIndex = 0;
51
52     knots = NULL;
53     maxKnots = 0;
54     knotIndex = 0;
55
56     controlPoints = NULL;
57     maxControlPoints = 0;
58     controlPointIndex = 0;
59
60     leaderVertices = NULL;
61     maxLeaderVertices = 0;
62     leaderVertexIndex = 0;
63
64     hatchLoops = NULL;
65     maxHatchLoops = 0;
66     hatchLoopIndex = -1;
67     hatchEdges = NULL;
68     maxHatchEdges = NULL;
69     hatchEdgeIndex = NULL;
70     dropEdges = false;
71
72     //bulge = 0.0;
73 }
74
75
76
77 /**
78  * Destructor.
79  */
80 DL_Dxf::~DL_Dxf() {
81     if (vertices!=NULL) {
82         delete[] vertices;
83     }
84     if (knots!=NULL) {
85         delete[] knots;
86     }
87     if (controlPoints!=NULL) {
88         delete[] controlPoints;
89     }
90     if (leaderVertices!=NULL) {
91         delete[] leaderVertices;
92     }
93     if (hatchLoops!=NULL) {
94         delete[] hatchLoops;
95     }
96     if (hatchEdges!=NULL) {
97         for (int i=0; i<maxHatchLoops; ++i) {
98             if (hatchEdges[i]!=NULL) {
99                 delete[] hatchEdges[i];
100             }
101         }
102         delete[] hatchEdges;
103     }
104     if (maxHatchEdges!=NULL) {
105         delete[] maxHatchEdges;
106     }
107     if (hatchEdgeIndex!=NULL) {
108         delete[] hatchEdgeIndex;
109     }
110 }
111
112
113
114 /**
115  * @brief Reads the given file and calls the appropriate functions in
116  * the given creation interface for every entity found in the file.
117  *
118  * @param file Input
119  *              Path and name of file to read
120  * @param creationInterface
121  *              Pointer to the class which takes care of the entities in the file.
122  *
123  * @retval true If \p file could be opened.
124  * @retval false If \p file could not be opened.
125  */
126 bool DL_Dxf::in(const string& file, DL_CreationInterface* creationInterface) {
127     FILE *fp;
128     firstCall = true;
129     currentEntity = DL_UNKNOWN;
130     int errorCounter = 0;
131
132     fp = fopen(file.c_str(), "rt");
133     if (fp) {
134         while (readDxfGroups(fp, creationInterface, &errorCounter)) {}
135         fclose(fp);
136         if (errorCounter>0) {
137             std::cerr << "DXF Filter: There have been " << errorCounter <<
138             " errors. The drawing might be incomplete / incorrect.\n";
139         }
140         return true;
141     }
142
143     return false;
144 }
145
146
147
148 /**
149  * Reads a DXF file from an existing stream.
150  *
151  * @param stream The string stream.
152  * @param creationInterface
153  *              Pointer to the class which takes care of the entities in the file.
154  *
155  * @retval true If \p file could be opened.
156  * @retval false If \p file could not be opened.
157  */
158 #ifndef __GCC2x__
159 bool DL_Dxf::in(std::stringstream& stream,
160                 DL_CreationInterface* creationInterface) {
161
162     int errorCounter = 0;
163
164     if (stream.good()) {
165         firstCall=true;
166         currentEntity = DL_UNKNOWN;
167         while (readDxfGroups(stream, creationInterface, &errorCounter)) {}
168         if (errorCounter>0) {
169             std::cerr << "DXF Filter: There have been " << errorCounter <<
170             " errors. The drawing might be incomplete / incorrect.\n";
171         }
172         return true;
173     }
174     return false;
175 }
176 #endif
177
178
179
180 /**
181  * @brief Reads a group couplet from a DXF file.  Calls another function
182  * to process it.
183  *
184  * A group couplet consists of two lines that represent a single
185  * piece of data.  An integer constant on the first line indicates
186  * the type of data.  The value is on the next line.\n
187  *
188  * This function reads a couplet, determines the type of data, and
189  * passes the value to the the appropriate handler function of
190  * \p creationInterface.\n
191  * 
192  * \p fp is advanced so that the next call to \p readDXFGroups() reads
193  * the next couplet in the file.
194  *
195  * @param fp Handle of input file
196  * @param creationInterface Handle of class which processes entities
197  *              in the file
198  *
199  * @retval true If EOF not reached.
200  * @retval false If EOF reached.
201  */
202 bool DL_Dxf::readDxfGroups(FILE *fp, DL_CreationInterface* creationInterface,
203                            int* errorCounter) {
204
205     bool ok = true;
206     static int line = 1;
207
208     // Read one group of the DXF file and chop the lines:
209     if (DL_Dxf::getChoppedLine(groupCodeTmp, DL_DXF_MAXLINE, fp) &&
210             DL_Dxf::getChoppedLine(groupValue, DL_DXF_MAXLINE, fp) ) {
211
212         groupCode = (unsigned int)stringToInt(groupCodeTmp, &ok);
213
214         if (ok) {
215             //std::cerr << groupCode << "\n";
216             //std::cerr << groupValue << "\n";
217             line+=2;
218             processDXFGroup(creationInterface, groupCode, groupValue);
219         } else {
220             std::cerr << "DXF read error: Line: " << line << "\n";
221             if (errorCounter!=NULL) {
222                 (*errorCounter)++;
223             }
224             // try to fix:
225             std::cerr << "DXF read error: trying to fix..\n";
226             // drop a line to sync:
227             DL_Dxf::getChoppedLine(groupCodeTmp, DL_DXF_MAXLINE, fp);
228         }
229     }
230
231     return !feof(fp);
232 }
233
234
235
236 /**
237  * Same as above but for stringstreams.
238  */
239 #ifndef __GCC2x__
240 bool DL_Dxf::readDxfGroups(std::stringstream& stream,
241                            DL_CreationInterface* creationInterface,
242                            int* errorCounter) {
243
244     bool ok = true;
245     static int line = 1;
246
247     // Read one group of the DXF file and chop the lines:
248     if (DL_Dxf::getChoppedLine(groupCodeTmp, DL_DXF_MAXLINE, stream) &&
249             DL_Dxf::getChoppedLine(groupValue, DL_DXF_MAXLINE, stream) ) {
250
251         groupCode = (unsigned int)stringToInt(groupCodeTmp, &ok);
252
253         if (ok) {
254             //std::cout << groupCode << "\n";
255             //std::cout << groupValue << "\n";
256             line+=2;
257             processDXFGroup(creationInterface, groupCode, groupValue);
258         } else {
259             std::cerr << "DXF read error: Line: " << line << "\n";
260             if (errorCounter!=NULL) {
261                 (*errorCounter)++;
262             }
263             // try to fix:
264             std::cerr << "DXF read error: trying to fix..\n";
265             // drop a line to sync:
266             DL_Dxf::getChoppedLine(groupCodeTmp, DL_DXF_MAXLINE, stream);
267         }
268     }
269     return !stream.eof();
270 }
271 #endif
272
273
274
275 /**
276  * @brief Reads line from file & strips whitespace at start and newline 
277  * at end.
278  *
279  * @param s Output\n
280  *              Pointer to character array that chopped line will be returned in.
281  * @param size Size of \p s.  (Including space for NULL.)
282  * @param fp Input\n
283  *              Handle of input file.
284  *
285  * @retval true if line could be read
286  * @retval false if \p fp is already at end of file
287  *
288  * @todo Change function to use safer FreeBSD strl* functions
289  * @todo Is it a problem if line is blank (i.e., newline only)?
290  *              Then, when function returns, (s==NULL).
291  */
292 bool DL_Dxf::getChoppedLine(char *s, unsigned int size, FILE *fp) {
293     if (!feof(fp)) {
294         // The whole line in the file.  Includes space for NULL.
295         char* wholeLine = new char[size];
296         // Only the useful part of the line
297         char* line;
298
299         line = fgets(wholeLine, size, fp);
300
301         if (line!=NULL && line[0] != '\0') { // Evaluates to fgets() retval
302             // line == wholeLine at this point.
303             // Both guaranteed to be NULL terminated.
304
305             // Strip leading whitespace and trailing CR/LF.
306             stripWhiteSpace(&line);
307
308             strncpy(s, line, size);
309             s[size] = '\0';
310             // s should always be NULL terminated, because:
311             assert(size > strlen(line));
312         }
313
314         delete[] wholeLine; // Done with wholeLine
315
316         return true;
317     } else {
318         s[0] = '\0';
319         return false;
320     }
321 }
322
323
324
325 /**
326  * Same as above but for stringstreams.
327  */
328 #ifndef __GCC2x__
329 bool DL_Dxf::getChoppedLine(char *s, unsigned int size,
330                             std::stringstream& stream) {
331
332     if (!stream.eof()) {
333         // Only the useful part of the line
334         stream.getline(s, size);
335         stripWhiteSpace(&s);
336         assert(size > strlen(s));
337         return true;
338     } else {
339         s[0] = '\0';
340         return false;
341     }
342 }
343 #endif
344
345
346
347 /**
348  * @brief Strips leading whitespace and trailing Carriage Return (CR)
349  * and Line Feed (LF) from NULL terminated string.
350  *
351  * @param s Input and output.
352  *              NULL terminates string.
353  *
354  * @retval true if \p s is non-NULL
355  * @retval false if \p s is NULL
356  */
357 bool DL_Dxf::stripWhiteSpace(char** s) {
358     // last non-NULL char:
359     int lastChar = strlen(*s) - 1;
360     //std::cout << "lastChar: " << lastChar << "\n";
361
362     // Is last character CR or LF?
363     while ( (lastChar >= 0) &&
364             (((*s)[lastChar] == 10) || ((*s)[lastChar] == 13) ||
365              ((*s)[lastChar] == ' ' || ((*s)[lastChar] == '\t'))) ) {
366         (*s)[lastChar] = '\0';
367         lastChar--;
368     }
369
370     // Skip whitespace, excluding \n, at beginning of line
371     while ((*s)[0]==' ' || (*s)[0]=='\t') {
372         ++(*s);
373     }
374
375     return ((*s) ? true : false);
376 }
377
378
379
380 /**
381  * Processes a group (pair of group code and value).
382  *
383  * @param creationInterface Handle to class that creates entities and
384  * other CAD data from DXF group codes
385  *
386  * @param groupCode Constant indicating the data type of the group.
387  * @param groupValue The data value.
388  *
389  * @retval true if done processing current entity and new entity begun
390  * @retval false if not done processing current entity
391 */
392 bool DL_Dxf::processDXFGroup(DL_CreationInterface* creationInterface,
393                              int groupCode, const char *groupValue) {
394
395
396     //std::cout << "DL_Dxf::processDXFGroup: " << groupCode << ": "
397     //<< groupValue << "\n";
398
399     // Init on first call
400     if (firstCall) {
401         for (int i=0; i<DL_DXF_MAXGROUPCODE; ++i) {
402             values[i][0] = '\0';
403         }
404         settingValue[0] = '\0';
405         firstCall=false;
406     }
407
408     // Indicates comment or dxflib version:
409     if (groupCode==999) {
410         //std::cout << "999: " << groupValue << "\n";
411         if (groupValue!=NULL) {
412             if (!strncmp(groupValue, "dxflib", 6)) {
413                 //std::cout << "dxflib version found" << "\n";
414                 libVersion = getLibVersion(&groupValue[7]);
415             }
416         }
417     }
418
419     // Indicates start of new entity or var
420     else if (groupCode==0 || groupCode==9) {
421
422         // If new entity is encountered, the last one must be complete
423         // prepare attributes which can be used for most entities:
424         char name[DL_DXF_MAXLINE+1];
425         if ((values[8])[0]!='\0') {
426             strcpy(name, values[8]);
427         }
428         // defaults to layer '0':
429         else {
430             strcpy(name, "0");
431         }
432
433         int width;
434         // Compatibillity with qcad1:
435         if ((values[39])[0]!='\0' &&
436                 (values[370])[0]=='\0') {
437             width = toInt(values[39], -1);
438         }
439         // since autocad 2002:
440         else if ((values[370])[0]!='\0') {
441             width = toInt(values[370], -1);
442         }
443         // default to BYLAYER:
444         else {
445             width = -1;
446         }
447
448         int color;
449         color = toInt(values[62], 256);
450
451         char linetype[DL_DXF_MAXLINE+1];
452         strcpy(linetype, toString(values[6], "BYLAYER"));
453
454         attrib = DL_Attributes(values[8],          // layer
455                                color,              // color
456                                width,              // width
457                                linetype);          // linetype
458         creationInterface->setAttributes(attrib);
459
460         creationInterface->setExtrusion(toReal(values[210], 0.0),
461                                         toReal(values[220], 0.0),
462                                         toReal(values[230], 1.0),
463                                         toReal(values[30], 0.0));
464
465         // Add the last entity via creationInterface
466         switch (currentEntity) {
467         case DL_SETTING:
468             addSetting(creationInterface);
469             break;
470
471         case DL_LAYER:
472             addLayer(creationInterface);
473             break;
474
475         case DL_BLOCK:
476             addBlock(creationInterface);
477             break;
478
479         case DL_ENDBLK:
480             endBlock(creationInterface);
481             break;
482
483         case DL_ENTITY_POINT:
484             addPoint(creationInterface);
485             break;
486
487         case DL_ENTITY_LINE:
488             addLine(creationInterface);
489             break;
490
491         case DL_ENTITY_POLYLINE:
492             //bulge = toReal(values[42]);
493             // fall through
494         case DL_ENTITY_LWPOLYLINE:
495             addPolyline(creationInterface);
496             break;
497
498         case DL_ENTITY_VERTEX:
499             addVertex(creationInterface);
500             break;
501
502         case DL_ENTITY_SPLINE:
503             addSpline(creationInterface);
504             break;
505
506         case DL_ENTITY_ARC:
507             addArc(creationInterface);
508             break;
509
510         case DL_ENTITY_CIRCLE:
511             addCircle(creationInterface);
512             break;
513
514         case DL_ENTITY_ELLIPSE:
515             addEllipse(creationInterface);
516             break;
517
518         case DL_ENTITY_INSERT:
519             addInsert(creationInterface);
520             break;
521
522         case DL_ENTITY_MTEXT:
523             addMText(creationInterface);
524             break;
525
526         case DL_ENTITY_TEXT:
527             addText(creationInterface);
528             break;
529
530         case DL_ENTITY_ATTRIB:
531             addAttrib(creationInterface);
532             break;
533
534         case DL_ENTITY_DIMENSION: {
535                 int type = (toInt(values[70], 0)&0x07);
536
537                 switch (type) {
538                 case 0:
539                     addDimLinear(creationInterface);
540                     break;
541
542                 case 1:
543                     addDimAligned(creationInterface);
544                     break;
545
546                 case 2:
547                     addDimAngular(creationInterface);
548                     break;
549
550                 case 3:
551                     addDimDiametric(creationInterface);
552                     break;
553
554                 case 4:
555                     addDimRadial(creationInterface);
556                     break;
557
558                 case 5:
559                     addDimAngular3P(creationInterface);
560                     break;
561
562                 default:
563                     break;
564                 }
565             }
566             break;
567
568         case DL_ENTITY_LEADER:
569             addLeader(creationInterface);
570             break;
571
572         case DL_ENTITY_HATCH:
573             addHatch(creationInterface);
574             break;
575
576         case DL_ENTITY_IMAGE:
577             addImage(creationInterface);
578             break;
579
580         case DL_ENTITY_IMAGEDEF:
581             addImageDef(creationInterface);
582             break;
583
584         case DL_ENTITY_TRACE:
585             addTrace(creationInterface);
586             break;
587
588         case DL_ENTITY_SOLID:
589             addSolid(creationInterface);
590             break;
591
592         case DL_ENTITY_SEQEND:
593             endSequence(creationInterface);
594             break;
595
596         default:
597             break;
598         }
599
600
601         // reset all values (they are not persistent and only this
602         //  way we can detect default values for unstored settings)
603         for (int i=0; i<DL_DXF_MAXGROUPCODE; ++i) {
604             values[i][0] = '\0';
605         }
606         settingValue[0] = '\0';
607         settingKey[0] = '\0';
608
609
610         // Last DXF entity or setting has been handled
611         // Now determine what the next entity or setting type is
612
613                 int prevEntity = currentEntity;
614
615         // Read DXF settings:
616         if (groupValue[0]=='$') {
617             currentEntity = DL_SETTING;
618             strncpy(settingKey, groupValue, DL_DXF_MAXLINE);
619             settingKey[DL_DXF_MAXLINE] = '\0';
620         }
621         // Read Layers:
622         else if (!strcmp(groupValue, "LAYER")) {
623             currentEntity = DL_LAYER;
624
625         }
626         // Read Blocks:
627         else if (!strcmp(groupValue, "BLOCK")) {
628             currentEntity = DL_BLOCK;
629         } else if (!strcmp(groupValue, "ENDBLK")) {
630             currentEntity = DL_ENDBLK;
631
632         }
633         // Read entities:
634         else if (!strcmp(groupValue, "POINT")) {
635             currentEntity = DL_ENTITY_POINT;
636         } else if (!strcmp(groupValue, "LINE")) {
637             currentEntity = DL_ENTITY_LINE;
638         } else if (!strcmp(groupValue, "POLYLINE")) {
639             currentEntity = DL_ENTITY_POLYLINE;
640         } else if (!strcmp(groupValue, "LWPOLYLINE")) {
641             currentEntity = DL_ENTITY_LWPOLYLINE;
642         } else if (!strcmp(groupValue, "VERTEX")) {
643             currentEntity = DL_ENTITY_VERTEX;
644         } else if (!strcmp(groupValue, "SPLINE")) {
645             currentEntity = DL_ENTITY_SPLINE;
646         } else if (!strcmp(groupValue, "ARC")) {
647             currentEntity = DL_ENTITY_ARC;
648         } else if (!strcmp(groupValue, "ELLIPSE")) {
649             currentEntity = DL_ENTITY_ELLIPSE;
650         } else if (!strcmp(groupValue, "CIRCLE")) {
651             currentEntity = DL_ENTITY_CIRCLE;
652         } else if (!strcmp(groupValue, "INSERT")) {
653             currentEntity = DL_ENTITY_INSERT;
654         } else if (!strcmp(groupValue, "TEXT")) {
655             currentEntity = DL_ENTITY_TEXT;
656         } else if (!strcmp(groupValue, "MTEXT")) {
657             currentEntity = DL_ENTITY_MTEXT;
658         } else if (!strcmp(groupValue, "ATTRIB")) {
659             currentEntity = DL_ENTITY_ATTRIB;
660         } else if (!strcmp(groupValue, "DIMENSION")) {
661             currentEntity = DL_ENTITY_DIMENSION;
662         } else if (!strcmp(groupValue, "LEADER")) {
663             currentEntity = DL_ENTITY_LEADER;
664         } else if (!strcmp(groupValue, "HATCH")) {
665             currentEntity = DL_ENTITY_HATCH;
666         } else if (!strcmp(groupValue, "IMAGE")) {
667             currentEntity = DL_ENTITY_IMAGE;
668         } else if (!strcmp(groupValue, "IMAGEDEF")) {
669             currentEntity = DL_ENTITY_IMAGEDEF;
670         } else if (!strcmp(groupValue, "TRACE")) {
671            currentEntity = DL_ENTITY_TRACE;
672         } else if (!strcmp(groupValue, "SOLID")) {
673            currentEntity = DL_ENTITY_SOLID;
674         } else if (!strcmp(groupValue, "SEQEND")) {
675             currentEntity = DL_ENTITY_SEQEND;
676         } else {
677             currentEntity = DL_UNKNOWN;
678         }
679
680                 // end of old style POLYLINE entity
681                 if (prevEntity==DL_ENTITY_VERTEX && currentEntity!=DL_ENTITY_VERTEX) {
682                         endEntity(creationInterface);
683                 }
684
685         return true;
686
687     } else {
688         // Group code does not indicate start of new entity or setting,
689         // so this group must be continuation of data for the current
690         // one.
691         if (groupCode<DL_DXF_MAXGROUPCODE) {
692
693             bool handled = false;
694
695             switch (currentEntity) {
696             case DL_ENTITY_MTEXT:
697                 handled = handleMTextData(creationInterface);
698                 break;
699
700             case DL_ENTITY_LWPOLYLINE:
701                 handled = handleLWPolylineData(creationInterface);
702                 break;
703
704             case DL_ENTITY_SPLINE:
705                 handled = handleSplineData(creationInterface);
706                 break;
707
708             case DL_ENTITY_LEADER:
709                 handled = handleLeaderData(creationInterface);
710                 break;
711
712             case DL_ENTITY_HATCH:
713                 handled = handleHatchData(creationInterface);
714                 break;
715
716             default:
717                 break;
718             }
719
720             if (!handled) {
721                 // Normal group / value pair:
722                 strncpy(values[groupCode], groupValue, DL_DXF_MAXLINE);
723                 values[groupCode][DL_DXF_MAXLINE] = '\0';
724             }
725         }
726
727         return false;
728     }
729     return false;
730 }
731
732
733
734 /**
735  * Adds a variable from the DXF file.
736  */
737 void DL_Dxf::addSetting(DL_CreationInterface* creationInterface) {
738     int c = -1;
739     for (int i=0; i<=380; ++i) {
740         if (values[i][0]!='\0') {
741             c = i;
742             break;
743         }
744     }
745
746     // string
747     if (c>=0 && c<=9) {
748         creationInterface->setVariableString(settingKey,
749                                              values[c], c);
750     }
751     // vector
752     else if (c>=10 && c<=39) {
753         if (c==10) {
754             creationInterface->setVariableVector(
755                 settingKey,
756                 toReal(values[c]),
757                 toReal(values[c+10]),
758                 toReal(values[c+20]),
759                 c);
760         }
761     }
762     // double
763     else if (c>=40 && c<=59) {
764         creationInterface->setVariableDouble(settingKey,
765                                              toReal(values[c]),
766                                              c);
767     }
768     // int
769     else if (c>=60 && c<=99) {
770         creationInterface->setVariableInt(settingKey,
771                                           toInt(values[c]),
772                                           c);
773     }
774     // misc
775     else if (c>=0) {
776         creationInterface->setVariableString(settingKey,
777                                              values[c],
778                                              c);
779     }
780 }
781
782
783
784 /**
785  * Adds a layer that was read from the file via the creation interface.
786  */
787 void DL_Dxf::addLayer(DL_CreationInterface* creationInterface) {
788     // correct some impossible attributes for layers:
789     attrib = creationInterface->getAttributes();
790     if (attrib.getColor()==256 || attrib.getColor()==0) {
791         attrib.setColor(7);
792     }
793     if (attrib.getWidth()<0) {
794         attrib.setWidth(1);
795     }
796     if (!strcasecmp(attrib.getLineType().c_str(), "BYLAYER") ||
797             !strcasecmp(attrib.getLineType().c_str(), "BYBLOCK")) {
798         attrib.setLineType("CONTINUOUS");
799     }
800
801     // add layer
802     creationInterface->addLayer(DL_LayerData(values[2],
803                                 toInt(values[70])));
804 }
805
806
807
808 /**
809  * Adds a block that was read from the file via the creation interface.
810  */
811 void DL_Dxf::addBlock(DL_CreationInterface* creationInterface) {
812     DL_BlockData d(
813         // Name:
814         values[2],
815         // flags:
816         toInt(values[70]),
817         // base point:
818         toReal(values[10]),
819         toReal(values[20]),
820         toReal(values[30]));
821
822     creationInterface->addBlock(d);
823 }
824
825
826
827 /**
828  * Ends a block that was read from the file via the creation interface.
829  */
830 void DL_Dxf::endBlock(DL_CreationInterface* creationInterface) {
831     creationInterface->endBlock();
832 }
833
834
835
836 /**
837  * Adds a point entity that was read from the file via the creation interface.
838  */
839 void DL_Dxf::addPoint(DL_CreationInterface* creationInterface) {
840     DL_PointData d(toReal(values[10]),
841                    toReal(values[20]),
842                    toReal(values[30]));
843     creationInterface->addPoint(d);
844 }
845
846
847
848 /**
849  * Adds a line entity that was read from the file via the creation interface.
850  */
851 void DL_Dxf::addLine(DL_CreationInterface* creationInterface) {
852     DL_LineData d(toReal(values[10]),
853                   toReal(values[20]),
854                   toReal(values[30]),
855                   toReal(values[11]),
856                   toReal(values[21]),
857                   toReal(values[31]));
858
859     creationInterface->addLine(d);
860 }
861
862
863
864 /**
865  * Adds a polyline entity that was read from the file via the creation interface.
866  */
867 void DL_Dxf::addPolyline(DL_CreationInterface* creationInterface) {
868     DL_PolylineData pd(maxVertices, toInt(values[71], 0), toInt(values[72], 0), toInt(values[70], 0));
869     creationInterface->addPolyline(pd);
870
871     if (currentEntity==DL_ENTITY_LWPOLYLINE) {
872         for (int i=0; i<maxVertices; i++) {
873             DL_VertexData d(vertices[i*4],
874                             vertices[i*4+1],
875                             vertices[i*4+2],
876                             vertices[i*4+3]);
877
878             creationInterface->addVertex(d);
879         }
880                 creationInterface->endEntity();
881     }
882 }
883
884
885
886 /**
887  * Adds a polyline vertex entity that was read from the file 
888  * via the creation interface.
889  */
890 void DL_Dxf::addVertex(DL_CreationInterface* creationInterface) {
891     DL_VertexData d(toReal(values[10]),
892                     toReal(values[20]),
893                     toReal(values[30]),
894                     //bulge);
895                     toReal(values[42]));
896
897     //bulge = toReal(values[42]);
898
899     creationInterface->addVertex(d);
900 }
901
902
903
904 /**
905  * Adds a spline entity that was read from the file via the creation interface.
906  */
907 void DL_Dxf::addSpline(DL_CreationInterface* creationInterface) {
908     DL_SplineData sd(toInt(values[71], 3), toInt(values[72], 0),
909                      toInt(values[73], 0), toInt(values[70], 4));
910     creationInterface->addSpline(sd);
911
912     for (int i=0; i<maxControlPoints; i++) {
913         DL_ControlPointData d(controlPoints[i*3],
914                               controlPoints[i*3+1],
915                               controlPoints[i*3+2]);
916
917         creationInterface->addControlPoint(d);
918     }
919 }
920
921
922
923 /**
924  * Adds a knot to the previously added spline. 
925  */
926 /*
927 void DL_Dxf::addKnot(DL_CreationInterface* creationInterface) {
928    std::cout << "DL_Dxf::addKnot\n";
929 }
930 */
931
932
933
934 /**
935  * Adds a control point to the previously added spline. 
936  */
937 /*
938 void DL_Dxf::addControlPoint(DL_CreationInterface* creationInterface) {
939     std::cout << "DL_Dxf::addControlPoint\n";
940 }
941 */
942
943
944
945 /**
946  * Adds an arc entity that was read from the file via the creation interface.
947  */
948 void DL_Dxf::addArc(DL_CreationInterface* creationInterface) {
949     DL_ArcData d(toReal(values[10]),
950                  toReal(values[20]),
951                  toReal(values[30]),
952                  toReal(values[40]),
953                  toReal(values[50]),
954                  toReal(values[51]));
955
956     creationInterface->addArc(d);
957 }
958
959
960
961 /**
962  * Adds a circle entity that was read from the file via the creation interface.
963  */
964 void DL_Dxf::addCircle(DL_CreationInterface* creationInterface) {
965     DL_CircleData d(toReal(values[10]),
966                     toReal(values[20]),
967                     toReal(values[30]),
968                     toReal(values[40]));
969
970     creationInterface->addCircle(d);
971 }
972
973
974
975 /**
976  * Adds an ellipse entity that was read from the file via the creation interface.
977  */
978 void DL_Dxf::addEllipse(DL_CreationInterface* creationInterface) {
979     DL_EllipseData d(toReal(values[10]),
980                      toReal(values[20]),
981                      toReal(values[30]),
982                      toReal(values[11]),
983                      toReal(values[21]),
984                      toReal(values[31]),
985                      toReal(values[40], 1.0),
986                      toReal(values[41], 0.0),
987                      toReal(values[42], 2*M_PI));
988
989     creationInterface->addEllipse(d);
990 }
991
992
993
994 /**
995  * Adds an insert entity that was read from the file via the creation interface.
996  */
997 void DL_Dxf::addInsert(DL_CreationInterface* creationInterface) {
998     DL_InsertData d(values[2],
999                     // insertion point
1000                     toReal(values[10], 0.0),
1001                     toReal(values[20], 0.0),
1002                     toReal(values[30], 0.0),
1003                     // scale:
1004                     toReal(values[41], 1.0),
1005                     toReal(values[42], 1.0),
1006                     toReal(values[43], 1.0),
1007                     // angle:
1008                     toReal(values[50], 0.0),
1009                     // cols / rows:
1010                     toInt(values[70], 1),
1011                     toInt(values[71], 1),
1012                     // spacing:
1013                     toReal(values[44], 0.0),
1014                     toReal(values[45], 0.0));
1015
1016     creationInterface->addInsert(d);
1017 }
1018
1019
1020 /**
1021  * Adds a trace entity (4 edge closed polyline) that was read from the file via the creation interface.
1022  *
1023  * @author AHM
1024  */
1025 void DL_Dxf::addTrace(DL_CreationInterface* creationInterface) {
1026     DL_TraceData td;
1027     
1028     for (int k = 0; k < 4; k++) {
1029        td.x[k] = toReal(values[10 + k]);
1030        td.y[k] = toReal(values[20 + k]);
1031        td.z[k] = toReal(values[30 + k]);
1032     }
1033     creationInterface->addTrace(td);
1034 }
1035
1036 /**
1037  * Adds a solid entity (filled trace) that was read from the file via the creation interface.
1038  * 
1039  * @author AHM
1040  */
1041 void DL_Dxf::addSolid(DL_CreationInterface* creationInterface) {
1042     DL_SolidData sd;
1043     
1044     for (int k = 0; k < 4; k++) {
1045        sd.x[k] = toReal(values[10 + k]);
1046        sd.y[k] = toReal(values[20 + k]);
1047        sd.z[k] = toReal(values[30 + k]);
1048     }
1049     creationInterface->addSolid(sd);
1050 }
1051
1052
1053 /**
1054  * Adds an MText entity that was read from the file via the creation interface.
1055  */
1056 void DL_Dxf::addMText(DL_CreationInterface* creationInterface) {
1057     double angle = 0.0;
1058
1059     if (values[50][0]!='\0') {
1060         if (libVersion<=0x02000200) {
1061             // wrong but compatible with dxflib <=2.0.2.0:
1062             angle = toReal(values[50], 0.0);
1063         } else {
1064             angle = (toReal(values[50], 0.0)*2*M_PI)/360.0;
1065         }
1066     } else if (values[11][0]!='\0' && values[21][0]!='\0') {
1067         double x = toReal(values[11], 0.0);
1068         double y = toReal(values[21], 0.0);
1069
1070         if (fabs(x)<1.0e-6) {
1071             if (y>0.0) {
1072                 angle = M_PI/2.0;
1073             } else {
1074                 angle = M_PI/2.0*3.0;
1075             }
1076         } else {
1077             angle = atan(y/x);
1078         }
1079     }
1080
1081     DL_MTextData d(
1082         // insertion point
1083         toReal(values[10], 0.0),
1084         toReal(values[20], 0.0),
1085         toReal(values[30], 0.0),
1086         // height
1087         toReal(values[40], 2.5),
1088         // width
1089         toReal(values[41], 100.0),
1090         // attachment point
1091         toInt(values[71], 1),
1092         // drawing direction
1093         toInt(values[72], 1),
1094         // line spacing style
1095         toInt(values[73], 1),
1096         // line spacing factor
1097         toReal(values[44], 1.0),
1098         // text
1099         values[1],
1100         // style
1101         values[7],
1102         // angle
1103         angle);
1104     creationInterface->addMText(d);
1105 }
1106
1107
1108
1109 /**
1110  * Handles additional MText data.
1111  */
1112 bool DL_Dxf::handleMTextData(DL_CreationInterface* creationInterface) {
1113     // Special handling of text chunks for MTEXT entities:
1114     if (groupCode==3) {
1115         creationInterface->addMTextChunk(groupValue);
1116         return true;
1117     }
1118
1119     return false;
1120 }
1121
1122
1123
1124 /**
1125  * Handles additional polyline data.
1126  */
1127 bool DL_Dxf::handleLWPolylineData(DL_CreationInterface* /*creationInterface*/) {
1128     // Allocate LWPolyline vertices (group code 90):
1129     if (groupCode==90) {
1130         maxVertices = toInt(groupValue);
1131         if (maxVertices>0) {
1132             if (vertices!=NULL) {
1133                 delete[] vertices;
1134             }
1135             vertices = new double[4*maxVertices];
1136             for (int i=0; i<maxVertices; ++i) {
1137                 vertices[i*4] = 0.0;
1138                 vertices[i*4+1] = 0.0;
1139                 vertices[i*4+2] = 0.0;
1140                 vertices[i*4+3] = 0.0;
1141             }
1142         }
1143         vertexIndex=-1;
1144         return true;
1145     }
1146
1147     // Compute LWPolylines vertices (group codes 10/20/30/42):
1148     else if (groupCode==10 || groupCode==20 ||
1149              groupCode==30 || groupCode==42) {
1150
1151         if (vertexIndex<maxVertices-1 && groupCode==10) {
1152             vertexIndex++;
1153         }
1154
1155         if (groupCode<=30) {
1156             if (vertexIndex>=0 && vertexIndex<maxVertices) {
1157                 vertices[4*vertexIndex + (groupCode/10-1)]
1158                 = toReal(groupValue);
1159             }
1160         } else if (groupCode==42 && vertexIndex<maxVertices) {
1161             vertices[4*vertexIndex + 3] = toReal(groupValue);
1162         }
1163         return true;
1164     }
1165     return false;
1166 }
1167
1168
1169
1170 /**
1171  * Handles additional spline data.
1172  */
1173 bool DL_Dxf::handleSplineData(DL_CreationInterface* /*creationInterface*/) {
1174     // Allocate Spline knots (group code 72):
1175     if (groupCode==72) {
1176         maxKnots = toInt(groupValue);
1177         if (maxKnots>0) {
1178             if (knots!=NULL) {
1179                 delete[] knots;
1180             }
1181             knots = new double[maxKnots];
1182             for (int i=0; i<maxKnots; ++i) {
1183                 knots[i] = 0.0;
1184             }
1185         }
1186         knotIndex=-1;
1187         return true;
1188     }
1189
1190     // Allocate Spline control points (group code 73):
1191     else if (groupCode==73) {
1192         maxControlPoints = toInt(groupValue);
1193         if (maxControlPoints>0) {
1194             if (controlPoints!=NULL) {
1195                 delete[] controlPoints;
1196             }
1197             controlPoints = new double[3*maxControlPoints];
1198             for (int i=0; i<maxControlPoints; ++i) {
1199                 controlPoints[i*3] = 0.0;
1200                 controlPoints[i*3+1] = 0.0;
1201                 controlPoints[i*3+2] = 0.0;
1202             }
1203         }
1204         controlPointIndex=-1;
1205         return true;
1206     }
1207
1208     // Compute spline knot vertices (group code 40):
1209     else if (groupCode==40) {
1210         if (knotIndex<maxKnots-1) {
1211             knotIndex++;
1212             knots[knotIndex] = toReal(groupValue);
1213         }
1214         return true;
1215     }
1216
1217     // Compute spline control points (group codes 10/20/30):
1218     else if (groupCode==10 || groupCode==20 ||
1219              groupCode==30) {
1220
1221         if (controlPointIndex<maxControlPoints-1 && groupCode==10) {
1222             controlPointIndex++;
1223         }
1224
1225         if (controlPointIndex>=0 && controlPointIndex<maxControlPoints) {
1226             controlPoints[3*controlPointIndex + (groupCode/10-1)]
1227             = toReal(groupValue);
1228         }
1229         return true;
1230     }
1231     return false;
1232 }
1233
1234
1235
1236 /**
1237  * Handles additional leader data.
1238  */
1239 bool DL_Dxf::handleLeaderData(DL_CreationInterface* /*creationInterface*/) {
1240     // Allocate Leader vertices (group code 76):
1241     if (groupCode==76) {
1242         maxLeaderVertices = toInt(groupValue);
1243         if (maxLeaderVertices>0) {
1244             if (leaderVertices!=NULL) {
1245                 delete[] leaderVertices;
1246             }
1247             leaderVertices = new double[3*maxLeaderVertices];
1248             for (int i=0; i<maxLeaderVertices; ++i) {
1249                 leaderVertices[i*3] = 0.0;
1250                 leaderVertices[i*3+1] = 0.0;
1251                 leaderVertices[i*3+2] = 0.0;
1252             }
1253         }
1254         leaderVertexIndex=-1;
1255         return true;
1256     }
1257
1258     // Compute Leader vertices (group codes 10/20/30):
1259     else if (groupCode==10 || groupCode==20 || groupCode==30) {
1260
1261         if (leaderVertexIndex<maxLeaderVertices-1 && groupCode==10) {
1262             leaderVertexIndex++;
1263         }
1264
1265         if (groupCode<=30) {
1266             if (leaderVertexIndex>=0 &&
1267                     leaderVertexIndex<maxLeaderVertices) {
1268                 leaderVertices[3*leaderVertexIndex + (groupCode/10-1)]
1269                 = toReal(groupValue);
1270             }
1271         }
1272         return true;
1273     }
1274
1275     return false;
1276 }
1277
1278
1279
1280 /**
1281  * Handles additional hatch data.
1282  */
1283 bool DL_Dxf::handleHatchData(DL_CreationInterface* /*creationInterface*/) {
1284
1285     static int firstPolylineStatus = 0;
1286
1287     // Allocate hatch loops (group code 91):
1288     if (groupCode==91 && toInt(groupValue)>0) {
1289
1290         //std::cout << "allocating " << toInt(groupValue) << " loops\n";
1291
1292         if (hatchLoops!=NULL) {
1293             delete[] hatchLoops;
1294             hatchLoops = NULL;
1295         }
1296         if (maxHatchEdges!=NULL) {
1297             delete[] maxHatchEdges;
1298             maxHatchEdges = NULL;
1299         }
1300         if (hatchEdgeIndex!=NULL) {
1301             delete[] hatchEdgeIndex;
1302             hatchEdgeIndex = NULL;
1303         }
1304         if (hatchEdges!=NULL) {
1305             for (int i=0; i<maxHatchLoops; ++i) {
1306                 delete[] hatchEdges[i];
1307             }
1308             delete[] hatchEdges;
1309             hatchEdges = NULL;
1310         }
1311         maxHatchLoops = toInt(groupValue);
1312
1313         //std::cout << "maxHatchLoops: " << maxHatchLoops << "\n";
1314
1315         if (maxHatchLoops>0) {
1316             hatchLoops = new DL_HatchLoopData[maxHatchLoops];
1317             maxHatchEdges = new int[maxHatchLoops];
1318             hatchEdgeIndex = new int[maxHatchLoops];
1319             hatchEdges = new DL_HatchEdgeData*[maxHatchLoops];
1320             //std::cout << "new hatchEdges[" << maxHatchLoops << "]\n";
1321             for (int i=0; i<maxHatchLoops; ++i) {
1322                 hatchEdges[i] = NULL;
1323                 //std::cout << "hatchEdges[" << i << "] = NULL\n";
1324                 maxHatchEdges[i] = 0;
1325             }
1326             hatchLoopIndex = -1;
1327             dropEdges = false;
1328         }
1329         //std::cout << "done\n";
1330         return true;
1331     }
1332
1333     // Allocate hatch edges, group code 93
1334     if (groupCode==93 && toInt(groupValue)>0) {
1335         if (hatchLoopIndex<maxHatchLoops-1 && hatchLoops!=NULL &&
1336                 maxHatchEdges!=NULL && hatchEdgeIndex!=NULL &&
1337                 hatchEdges!=NULL) {
1338
1339             //std::cout << "  allocating " << toInt(groupValue) << " edges\n";
1340             dropEdges = false;
1341
1342             hatchLoopIndex++;
1343             hatchLoops[hatchLoopIndex]
1344             = DL_HatchLoopData(toInt(groupValue));
1345
1346             maxHatchEdges[hatchLoopIndex] = toInt(groupValue);
1347             hatchEdgeIndex[hatchLoopIndex] = -1;
1348             hatchEdges[hatchLoopIndex]
1349             = new DL_HatchEdgeData[toInt(groupValue)];
1350
1351             //std::cout << "hatchEdges[" << hatchLoopIndex << "] = new "
1352             //  << toInt(groupValue) << "\n";
1353             firstPolylineStatus = 0;
1354         } else {
1355             //std::cout << "dropping " << toInt(groupValue) << " edges\n";
1356             dropEdges = true;
1357         }
1358         //std::cout << "done\n";
1359         return true;
1360     }
1361
1362     // Init hatch edge for non-polyline boundary (group code 72)
1363     if (hatchEdges!=NULL &&
1364             hatchEdgeIndex!=NULL &&
1365             maxHatchEdges!=NULL &&
1366             hatchLoopIndex>=0 &&
1367             hatchLoopIndex<maxHatchLoops &&
1368             hatchEdgeIndex[hatchLoopIndex] <
1369             maxHatchEdges[hatchLoopIndex] &&
1370             (atoi(values[92])&2)==0 &&   // not a polyline
1371             groupCode==72 &&
1372             !dropEdges) {
1373
1374         //std::cout << "Init hatch edge for non-polyline boundary\n";
1375         //std::cout << "hatchLoopIndex: " << hatchLoopIndex << "\n";
1376         //std::cout << "maxHatchLoops: " << maxHatchLoops << "\n";
1377
1378         hatchEdgeIndex[hatchLoopIndex]++;
1379
1380         //std::cout << "  init edge: type: "
1381         //<< toInt(groupValue)
1382         //<< " index: " << hatchEdgeIndex[hatchLoopIndex] << "\n";
1383
1384         hatchEdges[hatchLoopIndex][hatchEdgeIndex[hatchLoopIndex]]
1385         .type = toInt(groupValue);
1386         hatchEdges[hatchLoopIndex][hatchEdgeIndex[hatchLoopIndex]]
1387         .defined = false;
1388
1389         //std::cout << "done\n";
1390         return true;
1391     }
1392
1393     // Handle hatch edges for non-polyline boundaries
1394     //   (group codes 10, 20, 11, 21, 40, 50, 51, 73)
1395     if (!dropEdges &&
1396             hatchEdges!=NULL &&
1397             hatchEdgeIndex!=NULL &&
1398             hatchLoopIndex>=0 &&
1399             hatchLoopIndex<maxHatchLoops &&
1400             hatchEdges[hatchLoopIndex]!=NULL &&
1401             hatchEdgeIndex[hatchLoopIndex]>=0 &&
1402             hatchEdgeIndex[hatchLoopIndex] <
1403             maxHatchEdges[hatchLoopIndex] &&
1404             ((atoi(values[92])&2)==0) &&        // not a polyline
1405             (groupCode==10 || groupCode==20 ||
1406              groupCode==11 || groupCode==21 ||
1407              groupCode==40 || groupCode==50 ||
1408              groupCode==51 || groupCode==73)) {
1409
1410         //std::cout << "Handle hatch edge for non-polyline boundary\n";
1411         //std::cout << "  found edge data: " << groupCode << "\n";
1412         //std::cout << "     value: " << toReal(groupValue) << "\n";
1413
1414         // can crash:
1415         //std::cout << "     defined: "
1416         //   << (int)hatchEdges[hatchLoopIndex]
1417         //   [hatchEdgeIndex[hatchLoopIndex]].defined << "\n";
1418
1419         //std::cout << "92 flag: '" << values[92] << "'\n";
1420         //std::cout << "92 flag (int): '" << atoi(values[92]) << "'\n";
1421
1422         if (hatchEdges[hatchLoopIndex]
1423                 [hatchEdgeIndex[hatchLoopIndex]].defined==false) {
1424             if (hatchEdges[hatchLoopIndex]
1425                     [hatchEdgeIndex[hatchLoopIndex]].type==1) {
1426                 switch (groupCode) {
1427                 case 10:
1428                     hatchEdges[hatchLoopIndex]
1429                     [hatchEdgeIndex[hatchLoopIndex]].x1
1430                     = toReal(groupValue);
1431                     break;
1432                 case 20:
1433                     hatchEdges[hatchLoopIndex]
1434                     [hatchEdgeIndex[hatchLoopIndex]].y1
1435                     = toReal(groupValue);
1436                     break;
1437                 case 11:
1438                     hatchEdges[hatchLoopIndex]
1439                     [hatchEdgeIndex[hatchLoopIndex]].x2
1440                     = toReal(groupValue);
1441                     break;
1442                 case 21:
1443                     hatchEdges[hatchLoopIndex]
1444                     [hatchEdgeIndex[hatchLoopIndex]].y2
1445                     = toReal(groupValue);
1446                     hatchEdges[hatchLoopIndex]
1447                     [hatchEdgeIndex[hatchLoopIndex]].defined = true;
1448                     break;
1449                 default:
1450                     break;
1451                 }
1452             }
1453
1454             if (hatchEdges[hatchLoopIndex]
1455                     [hatchEdgeIndex[hatchLoopIndex]].type==2) {
1456                 switch (groupCode) {
1457                 case 10:
1458                     hatchEdges[hatchLoopIndex]
1459                     [hatchEdgeIndex[hatchLoopIndex]].cx
1460                     = toReal(groupValue);
1461                     break;
1462                 case 20:
1463                     hatchEdges[hatchLoopIndex]
1464                     [hatchEdgeIndex[hatchLoopIndex]].cy
1465                     = toReal(groupValue);
1466                     break;
1467                 case 40:
1468                     hatchEdges[hatchLoopIndex]
1469                     [hatchEdgeIndex[hatchLoopIndex]].radius
1470                     = toReal(groupValue);
1471                     break;
1472                 case 50:
1473                     hatchEdges[hatchLoopIndex]
1474                     [hatchEdgeIndex[hatchLoopIndex]].angle1
1475                     = toReal(groupValue)/360.0*2*M_PI;
1476                     break;
1477                 case 51:
1478                     hatchEdges[hatchLoopIndex]
1479                     [hatchEdgeIndex[hatchLoopIndex]].angle2
1480                     = toReal(groupValue)/360.0*2*M_PI;
1481                     break;
1482                 case 73:
1483                     hatchEdges[hatchLoopIndex]
1484                     [hatchEdgeIndex[hatchLoopIndex]].ccw
1485                     = (bool)toInt(groupValue);
1486                     hatchEdges[hatchLoopIndex]
1487                     [hatchEdgeIndex[hatchLoopIndex]].defined = true;
1488                     break;
1489                 default:
1490                     break;
1491                 }
1492             }
1493         }
1494         return true;
1495     }
1496
1497     /*
1498     // 2003/12/31: polyline hatches can be extremely slow and are rarely used
1499     //
1500        // Handle hatch edges for polyline boundaries
1501        //  (group codes 10, 20, 42)
1502        if (!dropEdges &&
1503                hatchEdges!=NULL &&
1504                hatchEdgeIndex!=NULL &&
1505                hatchLoopIndex>=0 &&
1506                hatchLoopIndex<maxHatchLoops &&
1507                hatchEdges[hatchLoopIndex]!=NULL &&
1508                //hatchEdgeIndex[hatchLoopIndex]>=0 &&
1509                hatchEdgeIndex[hatchLoopIndex] <
1510                maxHatchEdges[hatchLoopIndex] &&
1511                ((atoi(values[92])&2)==2)) {        // a polyline
1512
1513            if (groupCode==10 || groupCode==20 ||
1514                    groupCode==42) {
1515
1516                std::cout << "  found polyline edge data: " << groupCode << "\n";
1517                std::cout << "     value: " << toReal(groupValue) << "\n";
1518
1519                static double lastX = 0.0;
1520                static double lastY = 0.0;
1521                static double lastB = 0.0;
1522
1523                if (firstPolylineStatus<2) {
1524                    switch (groupCode) {
1525                    case 10:
1526                        firstPolylineStatus++;
1527                        if (firstPolylineStatus==1) {
1528                            lastX = toReal(groupValue);
1529                            std::cout << "     firstX: " << lastX << "\n";
1530                        }
1531                        break;
1532
1533                    case 20:
1534                        lastY = toReal(groupValue);
1535                        std::cout << "     firstY: " << lastY << "\n";
1536                        break;
1537
1538                    case 42:
1539                        lastB = toReal(groupValue);
1540                        break;
1541
1542                    default:
1543                        break;
1544                    }
1545
1546                    if (firstPolylineStatus!=2) {
1547                        return true;
1548                    }
1549                }
1550
1551
1552                switch (groupCode) {
1553                case 10:
1554                    hatchEdgeIndex[hatchLoopIndex]++;
1555                    hatchEdges[hatchLoopIndex]
1556                    [hatchEdgeIndex[hatchLoopIndex]].type = 1;
1557                    hatchEdges[hatchLoopIndex]
1558                    [hatchEdgeIndex[hatchLoopIndex]].x1
1559                    = lastX;
1560                    hatchEdges[hatchLoopIndex]
1561                    [hatchEdgeIndex[hatchLoopIndex]].x2
1562                    = lastX = toReal(groupValue);
1563                    std::cout << "     X: " << lastX << "\n";
1564                    break;
1565                case 20:
1566                    hatchEdges[hatchLoopIndex]
1567                    [hatchEdgeIndex[hatchLoopIndex]].y1
1568                    = lastY;
1569                    hatchEdges[hatchLoopIndex]
1570                    [hatchEdgeIndex[hatchLoopIndex]].y2
1571                    = lastY = toReal(groupValue);
1572                    std::cout << "     Y: " << lastY << "\n";
1573                    break;
1574                    / *
1575                                case 42: {
1576                         // convert to arc:
1577                         double x1 = hatchEdges[hatchLoopIndex]
1578                                 [hatchEdgeIndex[hatchLoopIndex]].x1;
1579                         double y1 = hatchEdges[hatchLoopIndex]
1580                                 [hatchEdgeIndex[hatchLoopIndex]].y1;
1581                         double x2 = hatchEdges[hatchLoopIndex]
1582                                 [hatchEdgeIndex[hatchLoopIndex]].x2;
1583                         double y2 = hatchEdges[hatchLoopIndex]
1584                                 [hatchEdgeIndex[hatchLoopIndex]].y2;
1585
1586                         double bulge = toReal(groupValue);
1587
1588                         bool reversed = (bulge<0.0);
1589                         double alpha = atan(bulge)*4.0;
1590                         double radius;
1591                              double cx;
1592                              double cy;
1593                         double a1;
1594                         double a2;
1595                              double mx = (x2+x1)/2.0;
1596                              double my = (y2+y1)/2.0;
1597                         double dist = sqrt(pow(x2-x1,2) + pow(y2-y1,2)) / 2.0;
1598
1599                         // alpha can't be 0.0 at this point
1600                              radius = fabs(dist / sin(alpha/2.0));
1601
1602                              double wu = fabs(pow(radius, 2.0) - pow(dist, 2.0));
1603                              double h = sqrt(wu);
1604                         double angle = acos((x2-x1) / dist);
1605
1606                              if (bulge>0.0) {
1607                                         angle+=M_PI/2.0;
1608                              } else {
1609                                  angle-=M_PI/2.0;
1610                              }
1611
1612                              if (fabs(alpha)>M_PI) {
1613                                  h*=-1.0;
1614                              }
1615
1616                         cx = mx + cos(angle) * h;
1617                         cy = my + sin(angle) * h;
1618
1619                         a1 = hatchEdges[hatchLoopIndex]
1620                                         [hatchEdgeIndex[hatchLoopIndex]].type = 2;
1621                                    hatchEdges[hatchLoopIndex]
1622                                         [hatchEdgeIndex[hatchLoopIndex]].ccw = (toReal(groupValue)>0.0);
1623                                    hatchEdges[hatchLoopIndex]
1624                                         [hatchEdgeIndex[hatchLoopIndex]].cx = cx;
1625                                    hatchEdges[hatchLoopIndex]
1626                                         [hatchEdgeIndex[hatchLoopIndex]].cy = cy;
1627                                    hatchEdges[hatchLoopIndex]
1628                                         [hatchEdgeIndex[hatchLoopIndex]].radius = radius;
1629                                    } break;
1630                         * /
1631
1632                default:
1633                    break;
1634                }
1635            } else {
1636                // end polyline boundary
1637                dropEdges = true;
1638            }
1639
1640            return true;
1641        }
1642     */
1643
1644     return false;
1645 }
1646
1647
1648
1649
1650 /**
1651  * Adds an text entity that was read from the file via the creation interface.
1652  */
1653 void DL_Dxf::addText(DL_CreationInterface* creationInterface) {
1654     DL_TextData d(
1655         // insertion point
1656         toReal(values[10], 0.0),
1657         toReal(values[20], 0.0),
1658         toReal(values[30], 0.0),
1659         // alignment point
1660         toReal(values[11], 0.0),
1661         toReal(values[21], 0.0),
1662         toReal(values[31], 0.0),
1663         // height
1664         toReal(values[40], 2.5),
1665         // x scale
1666         toReal(values[41], 1.0),
1667         // generation flags
1668         toInt(values[71], 0),
1669         // h just
1670         toInt(values[72], 0),
1671         // v just
1672         toInt(values[73], 0),
1673         // text
1674         values[1],
1675         // style
1676         values[7],
1677         // angle
1678         (toReal(values[50], 0.0)*2*M_PI)/360.0);
1679
1680     creationInterface->addText(d);
1681 }
1682
1683
1684
1685 /**
1686  * Adds an attrib entity that was read from the file via the creation interface.
1687  * @todo add attrib instead of normal text
1688  */
1689 void DL_Dxf::addAttrib(DL_CreationInterface* creationInterface) {
1690     DL_TextData d(
1691         // insertion point
1692         toReal(values[10], 0.0),
1693         toReal(values[20], 0.0),
1694         toReal(values[30], 0.0),
1695         // alignment point
1696         toReal(values[11], 0.0),
1697         toReal(values[21], 0.0),
1698         toReal(values[31], 0.0),
1699         // height
1700         toReal(values[40], 2.5),
1701         // x scale
1702         toReal(values[41], 1.0),
1703         // generation flags
1704         toInt(values[71], 0),
1705         // h just
1706         toInt(values[72], 0),
1707         // v just
1708         toInt(values[74], 0),
1709         // text
1710         values[1],
1711         // style
1712         values[7],
1713         // angle
1714         (toReal(values[50], 0.0)*2*M_PI)/360.0);
1715
1716     creationInterface->addText(d);
1717 }
1718
1719
1720
1721 /**
1722  * @return dimension data from current values.
1723  */
1724 DL_DimensionData DL_Dxf::getDimData() {
1725     // generic dimension data:
1726     return DL_DimensionData(
1727                // def point
1728                toReal(values[10], 0.0),
1729                toReal(values[20], 0.0),
1730                toReal(values[30], 0.0),
1731                // text middle point
1732                toReal(values[11], 0.0),
1733                toReal(values[21], 0.0),
1734                toReal(values[31], 0.0),
1735                // type
1736                toInt(values[70], 0),
1737                // attachment point
1738                toInt(values[71], 5),
1739                // line sp. style
1740                toInt(values[72], 1),
1741                // line sp. factor
1742                toReal(values[41], 1.0),
1743                // text
1744                values[1],
1745                // style
1746                values[3],
1747                // angle
1748                toReal(values[53], 0.0));
1749 }
1750
1751
1752
1753 /**
1754  * Adds a linear dimension entity that was read from the file via the creation interface.
1755  */
1756 void DL_Dxf::addDimLinear(DL_CreationInterface* creationInterface) {
1757     DL_DimensionData d = getDimData();
1758
1759     // horizontal / vertical / rotated dimension:
1760     DL_DimLinearData dl(
1761         // definition point 1
1762         toReal(values[13], 0.0),
1763         toReal(values[23], 0.0),
1764         toReal(values[33], 0.0),
1765         // definition point 2
1766         toReal(values[14], 0.0),
1767         toReal(values[24], 0.0),
1768         toReal(values[34], 0.0),
1769         // angle
1770         toReal(values[50], 0.0),
1771         // oblique
1772         toReal(values[52], 0.0));
1773     creationInterface->addDimLinear(d, dl);
1774 }
1775
1776
1777
1778 /**
1779  * Adds an aligned dimension entity that was read from the file via the creation interface.
1780  */
1781 void DL_Dxf::addDimAligned(DL_CreationInterface* creationInterface) {
1782     DL_DimensionData d = getDimData();
1783
1784     // aligned dimension:
1785     DL_DimAlignedData da(
1786         // extension point 1
1787         toReal(values[13], 0.0),
1788         toReal(values[23], 0.0),
1789         toReal(values[33], 0.0),
1790         // extension point 2
1791         toReal(values[14], 0.0),
1792         toReal(values[24], 0.0),
1793         toReal(values[34], 0.0));
1794     creationInterface->addDimAlign(d, da);
1795 }
1796
1797
1798
1799 /**
1800  * Adds a radial dimension entity that was read from the file via the creation interface.
1801  */
1802 void DL_Dxf::addDimRadial(DL_CreationInterface* creationInterface) {
1803     DL_DimensionData d = getDimData();
1804
1805     DL_DimRadialData dr(
1806         // definition point
1807         toReal(values[15], 0.0),
1808         toReal(values[25], 0.0),
1809         toReal(values[35], 0.0),
1810         // leader length:
1811         toReal(values[40], 0.0));
1812     creationInterface->addDimRadial(d, dr);
1813 }
1814
1815
1816
1817 /**
1818  * Adds a diametric dimension entity that was read from the file via the creation interface.
1819  */
1820 void DL_Dxf::addDimDiametric(DL_CreationInterface* creationInterface) {
1821     DL_DimensionData d = getDimData();
1822
1823     // diametric dimension:
1824     DL_DimDiametricData dr(
1825         // definition point
1826         toReal(values[15], 0.0),
1827         toReal(values[25], 0.0),
1828         toReal(values[35], 0.0),
1829         // leader length:
1830         toReal(values[40], 0.0));
1831     creationInterface->addDimDiametric(d, dr);
1832 }
1833
1834
1835
1836 /**
1837  * Adds an angular dimension entity that was read from the file via the creation interface.
1838  */
1839 void DL_Dxf::addDimAngular(DL_CreationInterface* creationInterface) {
1840     DL_DimensionData d = getDimData();
1841
1842     // angular dimension:
1843     DL_DimAngularData da(
1844         // definition point 1
1845         toReal(values[13], 0.0),
1846         toReal(values[23], 0.0),
1847         toReal(values[33], 0.0),
1848         // definition point 2
1849         toReal(values[14], 0.0),
1850         toReal(values[24], 0.0),
1851         toReal(values[34], 0.0),
1852         // definition point 3
1853         toReal(values[15], 0.0),
1854         toReal(values[25], 0.0),
1855         toReal(values[35], 0.0),
1856         // definition point 4
1857         toReal(values[16], 0.0),
1858         toReal(values[26], 0.0),
1859         toReal(values[36], 0.0));
1860     creationInterface->addDimAngular(d, da);
1861 }
1862
1863
1864 /**
1865  * Adds an angular dimension entity that was read from the file via the creation interface.
1866  */
1867 void DL_Dxf::addDimAngular3P(DL_CreationInterface* creationInterface) {
1868     DL_DimensionData d = getDimData();
1869
1870     // angular dimension (3P):
1871     DL_DimAngular3PData da(
1872         // definition point 1
1873         toReal(values[13], 0.0),
1874         toReal(values[23], 0.0),
1875         toReal(values[33], 0.0),
1876         // definition point 2
1877         toReal(values[14], 0.0),
1878         toReal(values[24], 0.0),
1879         toReal(values[34], 0.0),
1880         // definition point 3
1881         toReal(values[15], 0.0),
1882         toReal(values[25], 0.0),
1883         toReal(values[35], 0.0));
1884     creationInterface->addDimAngular3P(d, da);
1885 }
1886
1887
1888
1889 /**
1890  * Adds a leader entity that was read from the file via the creation interface.
1891  */
1892 void DL_Dxf::addLeader(DL_CreationInterface* creationInterface) {
1893     // leader (arrow)
1894     DL_LeaderData le(
1895         // arrow head flag
1896         toInt(values[71], 1),
1897         // leader path type
1898         toInt(values[72], 0),
1899         // Leader creation flag
1900         toInt(values[73], 3),
1901         // Hookline direction flag
1902         toInt(values[74], 1),
1903         // Hookline flag
1904         toInt(values[75], 0),
1905         // Text annotation height
1906         toReal(values[40], 1.0),
1907         // Text annotation width
1908         toReal(values[41], 1.0),
1909         // Number of vertices in leader
1910         toInt(values[76], 0)
1911     );
1912     creationInterface->addLeader(le);
1913
1914     for (int i=0; i<maxLeaderVertices; i++) {
1915         DL_LeaderVertexData d(leaderVertices[i*3],
1916                               leaderVertices[i*3+1],
1917                               leaderVertices[i*3+2]);
1918
1919         creationInterface->addLeaderVertex(d);
1920     }
1921 }
1922
1923
1924
1925 /**
1926  * Adds a hatch entity that was read from the file via the creation interface.
1927  */
1928 void DL_Dxf::addHatch(DL_CreationInterface* creationInterface) {
1929     DL_HatchData hd(toInt(values[91], 1),
1930                     toInt(values[70], 0),
1931                     toReal(values[41], 1.0),
1932                     toReal(values[52], 0.0),
1933                     values[2]);
1934     creationInterface->addHatch(hd);
1935
1936     for (int l=0; l<maxHatchLoops; l++) {
1937         DL_HatchLoopData ld(maxHatchEdges[l]);
1938         creationInterface->addHatchLoop(ld);
1939         for (int b=0; b<maxHatchEdges[l]; b++) {
1940             creationInterface->addHatchEdge(hatchEdges[l][b]);
1941         }
1942     }
1943     creationInterface->endEntity();
1944     currentEntity = DL_UNKNOWN;
1945 }
1946
1947
1948
1949 /**
1950  * Adds an image entity that was read from the file via the creation interface.
1951  */
1952 void DL_Dxf::addImage(DL_CreationInterface* creationInterface) {
1953     DL_ImageData id(// pass ref insead of name we don't have yet
1954         values[340],
1955         // ins point:
1956         toReal(values[10], 0.0),
1957         toReal(values[20], 0.0),
1958         toReal(values[30], 0.0),
1959         // u vector:
1960         toReal(values[11], 1.0),
1961         toReal(values[21], 0.0),
1962         toReal(values[31], 0.0),
1963         // v vector:
1964         toReal(values[12], 0.0),
1965         toReal(values[22], 1.0),
1966         toReal(values[32], 0.0),
1967         // image size (pixel):
1968         toInt(values[13], 1),
1969         toInt(values[23], 1),
1970         // brightness, contrast, fade
1971         toInt(values[281], 50),
1972         toInt(values[282], 50),
1973         toInt(values[283], 0));
1974
1975     creationInterface->addImage(id);
1976     creationInterface->endEntity();
1977     currentEntity = DL_UNKNOWN;
1978 }
1979
1980
1981
1982 /**
1983  * Adds an image definition that was read from the file via the creation interface.
1984  */
1985 void DL_Dxf::addImageDef(DL_CreationInterface* creationInterface) {
1986     DL_ImageDefData id(// handle
1987         values[5],
1988         values[1]);
1989
1990     creationInterface->linkImage(id);
1991     creationInterface->endEntity();
1992     currentEntity = DL_UNKNOWN;
1993 }
1994
1995
1996
1997 /**
1998  * Ends some special entities like hatches or old style polylines.
1999  */
2000 void DL_Dxf::endEntity(DL_CreationInterface* creationInterface) {
2001         creationInterface->endEntity();
2002 }
2003
2004
2005 /**
2006  * Ends a sequence and notifies the creation interface.
2007  */
2008 void DL_Dxf::endSequence(DL_CreationInterface* creationInterface) {
2009     creationInterface->endSequence();
2010 }
2011
2012
2013 /**
2014  * Converts the given string into an int.
2015  * ok is set to false if there was an error.
2016  */
2017 int DL_Dxf::stringToInt(const char* s, bool* ok) {
2018     if (ok!=NULL) {
2019         // check string:
2020         *ok = true;
2021         int i=0;
2022         bool dot = false;
2023         do {
2024             if (s[i]=='\0') {
2025                 break;
2026             } else if (s[i]=='.') {
2027                 if (dot==true) {
2028                     //std::cerr << "two dots\n";
2029                     *ok = false;
2030                 } else {
2031                     dot = true;
2032                 }
2033             } else if (s[i]<'0' || s[i]>'9') {
2034                 //std::cerr << "NaN: '" << s[i] << "'\n";
2035                 *ok = false;
2036             }
2037             i++;
2038         } while(s[i]!='\0' && *ok==true);
2039     }
2040
2041     return atoi(s);
2042 }
2043
2044
2045 /**
2046  * @brief Opens the given file for writing and returns a pointer
2047  * to the dxf writer. This pointer needs to be passed on to other
2048  * writing functions.
2049  *
2050  * @param file Full path of the file to open.
2051  *
2052  * @return Pointer to an ascii dxf writer object.
2053  */
2054 DL_WriterA* DL_Dxf::out(const char* file, DL_Codes::version version) {
2055     char* f = new char[strlen(file)+1];
2056     strcpy(f, file);
2057     this->version = version;
2058
2059     DL_WriterA* dw = new DL_WriterA(f, version);
2060     if (dw->openFailed()) {
2061         delete dw;
2062         return NULL;
2063     } else {
2064         return dw;
2065     }
2066 }
2067
2068
2069
2070 /**
2071  * @brief Writes a DXF header to the file currently opened 
2072  * by the given DXF writer object.
2073  */
2074 void DL_Dxf::writeHeader(DL_WriterA& dw) {
2075     dw.comment("dxflib " DL_VERSION);
2076     dw.sectionHeader();
2077
2078     dw.dxfString(9, "$ACADVER");
2079     switch (version) {
2080     case DL_Codes::AC1009:
2081         dw.dxfString(1, "AC1009");
2082         break;
2083     case DL_Codes::AC1012:
2084         dw.dxfString(1, "AC1012");
2085         break;
2086     case DL_Codes::AC1014:
2087         dw.dxfString(1, "AC1014");
2088         break;
2089     case DL_Codes::AC1015:
2090         dw.dxfString(1, "AC1015");
2091         break;
2092     }
2093
2094     // Newer version require that (otherwise a*cad crashes..)
2095     if (version==VER_2000) {
2096         dw.dxfString(9, "$HANDSEED");
2097         dw.dxfHex(5, 0xFFFF);
2098     }
2099
2100     //dw.sectionEnd();
2101 }
2102
2103
2104
2105
2106 /**
2107  * Writes a point entity to the file.
2108  *
2109  * @param dw DXF writer
2110  * @param data Entity data from the file
2111  * @param attrib Attributes
2112  */
2113 void DL_Dxf::writePoint(DL_WriterA& dw,
2114                         const DL_PointData& data,
2115                         const DL_Attributes& attrib) {
2116     dw.entity("POINT");
2117     if (version==VER_2000) {
2118         dw.dxfString(100, "AcDbEntity");
2119         dw.dxfString(100, "AcDbPoint");
2120     }
2121     dw.entityAttributes(attrib);
2122     dw.coord(POINT_COORD_CODE, data.x, data.y);
2123 }
2124
2125
2126
2127 /**
2128  * Writes a line entity to the file.
2129  *
2130  * @param dw DXF writer
2131  * @param data Entity data from the file
2132  * @param attrib Attributes
2133  */
2134 void DL_Dxf::writeLine(DL_WriterA& dw,
2135                        const DL_LineData& data,
2136                        const DL_Attributes& attrib) {
2137     dw.entity("LINE");
2138     if (version==VER_2000) {
2139         dw.dxfString(100, "AcDbEntity");
2140         dw.dxfString(100, "AcDbLine");
2141     }
2142     dw.entityAttributes(attrib);
2143     dw.coord(LINE_START_CODE, data.x1, data.y1);
2144     dw.coord(LINE_END_CODE, data.x2, data.y2);
2145 }
2146
2147
2148
2149 /**
2150  * Writes a polyline entity to the file.
2151  *
2152  * @param dw DXF writer
2153  * @param data Entity data from the file
2154  * @param attrib Attributes
2155  * @see writeVertex
2156  */
2157 void DL_Dxf::writePolyline(DL_WriterA& dw,
2158                            const DL_PolylineData& data,
2159                            const DL_Attributes& attrib) {
2160     if (version==VER_2000) {
2161         dw.entity("LWPOLYLINE");
2162         dw.entityAttributes(attrib);
2163         dw.dxfString(100, "AcDbEntity");
2164         dw.dxfString(100, "AcDbPolyline");
2165         dw.dxfInt(90, (int)data.number);
2166         dw.dxfInt(70, data.flags);
2167     } else {
2168         dw.entity("POLYLINE");
2169         dw.entityAttributes(attrib);
2170                 polylineLayer = attrib.getLayer();
2171         dw.dxfInt(66, 1);
2172         dw.dxfInt(70, data.flags);
2173         dw.coord(VERTEX_COORD_CODE, 0.0, 0.0);
2174     }
2175 }
2176
2177
2178
2179 /**
2180  * Writes a single vertex of a polyline to the file.
2181  *
2182  * @param dw DXF writer
2183  * @param data Entity data from the file
2184  * @param attrib Attributes
2185  */
2186 void DL_Dxf::writeVertex(DL_WriterA& dw,
2187                          const DL_VertexData& data) {
2188
2189
2190     if (version==VER_2000) {
2191         dw.dxfReal(10, data.x);
2192         dw.dxfReal(20, data.y);
2193         if (fabs(data.bulge)>1.0e-10) {
2194             dw.dxfReal(42, data.bulge);
2195         }
2196     } else {
2197         dw.entity("VERTEX");
2198         //dw.entityAttributes(attrib);
2199         dw.dxfString(8, polylineLayer);
2200         dw.coord(VERTEX_COORD_CODE, data.x, data.y);
2201         if (fabs(data.bulge)>1.0e-10) {
2202             dw.dxfReal(42, data.bulge);
2203         }
2204     }
2205 }
2206
2207     
2208         
2209 /**
2210  * Writes the polyline end. Only needed for DXF R12.
2211  */
2212 void DL_Dxf::writePolylineEnd(DL_WriterA& dw) {
2213     if (version==VER_2000) {
2214     } else {
2215         dw.entity("SEQEND");
2216     }
2217 }
2218
2219
2220 /**
2221  * Writes a spline entity to the file.
2222  *
2223  * @param dw DXF writer
2224  * @param data Entity data from the file
2225  * @param attrib Attributes
2226  * @see writeControlPoint
2227  */
2228 void DL_Dxf::writeSpline(DL_WriterA& dw,
2229                          const DL_SplineData& data,
2230                          const DL_Attributes& attrib) {
2231
2232     dw.entity("SPLINE");
2233     dw.entityAttributes(attrib);
2234     if (version==VER_2000) {
2235         dw.dxfString(100, "AcDbEntity");
2236         dw.dxfString(100, "AcDbSpline");
2237     }
2238     dw.dxfInt(70, data.flags);
2239     dw.dxfInt(71, data.degree);
2240     dw.dxfInt(72, data.nKnots);            // number of knots
2241     dw.dxfInt(73, data.nControl);          // number of control points
2242     dw.dxfInt(74, 0);                      // number of fit points
2243 }
2244
2245
2246
2247 /**
2248  * Writes a single control point of a spline to the file.
2249  *
2250  * @param dw DXF writer
2251  * @param data Entity data from the file
2252  * @param attrib Attributes
2253  */
2254 void DL_Dxf::writeControlPoint(DL_WriterA& dw,
2255                                const DL_ControlPointData& data) {
2256
2257     dw.dxfReal(10, data.x);
2258     dw.dxfReal(20, data.y);
2259     dw.dxfReal(30, data.z);
2260 }
2261
2262
2263
2264 /**
2265  * Writes a single knot of a spline to the file.
2266  *
2267  * @param dw DXF writer
2268  * @param data Entity data from the file
2269  * @param attrib Attributes
2270  */
2271 void DL_Dxf::writeKnot(DL_WriterA& dw,
2272                        const DL_KnotData& data) {
2273
2274     dw.dxfReal(40, data.k);
2275 }
2276
2277
2278
2279 /**
2280  * Writes a circle entity to the file.
2281  *
2282  * @param dw DXF writer
2283  * @param data Entity data from the file
2284  * @param attrib Attributes
2285  */
2286 void DL_Dxf::writeCircle(DL_WriterA& dw,
2287                          const DL_CircleData& data,
2288                          const DL_Attributes& attrib) {
2289     dw.entity("CIRCLE");
2290     if (version==VER_2000) {
2291         dw.dxfString(100, "AcDbEntity");
2292         dw.dxfString(100, "AcDbCircle");
2293     }
2294     dw.entityAttributes(attrib);
2295     dw.coord(10, data.cx, data.cy);
2296     dw.dxfReal(40, data.radius);
2297 }
2298
2299
2300
2301 /**
2302  * Writes an arc entity to the file.
2303  *
2304  * @param dw DXF writer
2305  * @param data Entity data from the file
2306  * @param attrib Attributes
2307  */
2308 void DL_Dxf::writeArc(DL_WriterA& dw,
2309                       const DL_ArcData& data,
2310                       const DL_Attributes& attrib) {
2311     dw.entity("ARC");
2312     if (version==VER_2000) {
2313         dw.dxfString(100, "AcDbEntity");
2314     }
2315     dw.entityAttributes(attrib);
2316     if (version==VER_2000) {
2317         dw.dxfString(100, "AcDbCircle");
2318     }
2319     dw.coord(10, data.cx, data.cy);
2320     dw.dxfReal(40, data.radius);
2321     if (version==VER_2000) {
2322         dw.dxfString(100, "AcDbArc");
2323     }
2324     dw.dxfReal(50, data.angle1);
2325     dw.dxfReal(51, data.angle2);
2326 }
2327
2328
2329
2330 /**
2331  * Writes an ellipse entity to the file.
2332  *
2333  * @param dw DXF writer
2334  * @param data Entity data from the file
2335  * @param attrib Attributes
2336  */
2337 void DL_Dxf::writeEllipse(DL_WriterA& dw,
2338                           const DL_EllipseData& data,
2339                           const DL_Attributes& attrib) {
2340
2341     if (version>VER_R12) {
2342         dw.entity("ELLIPSE");
2343         if (version==VER_2000) {
2344             dw.dxfString(100, "AcDbEntity");
2345             dw.dxfString(100, "AcDbEllipse");
2346         }
2347         dw.entityAttributes(attrib);
2348         dw.coord(10, data.cx, data.cy);
2349         dw.coord(11, data.mx, data.my);
2350         dw.dxfReal(40, data.ratio);
2351         dw.dxfReal(41, data.angle1);
2352         dw.dxfReal(42, data.angle2);
2353     }
2354 }
2355
2356
2357
2358 /**
2359  * Writes an insert to the file.
2360  *
2361  * @param dw DXF writer
2362  * @param data Entity data from the file
2363  * @param attrib Attributes
2364  */
2365 void DL_Dxf::writeInsert(DL_WriterA& dw,
2366                          const DL_InsertData& data,
2367                          const DL_Attributes& attrib) {
2368
2369     if (data.name.empty()) {
2370         std::cerr << "DL_Dxf::writeInsert: "
2371         << "Block name must not be empty\n";
2372         return;
2373     }
2374
2375     dw.entity("INSERT");
2376     if (version==VER_2000) {
2377         dw.dxfString(100, "AcDbEntity");
2378         dw.dxfString(100, "AcDbBlockReference");
2379     }
2380     dw.entityAttributes(attrib);
2381     dw.dxfString(2, data.name);
2382     dw.dxfReal(10, data.ipx);
2383     dw.dxfReal(20, data.ipy);
2384     dw.dxfReal(30, 0.0);
2385     if (data.sx!=1.0 || data.sy!=1.0) {
2386         dw.dxfReal(41, data.sx);
2387         dw.dxfReal(42, data.sy);
2388         dw.dxfReal(43, 1.0);
2389     }
2390     if (data.angle!=0.0) {
2391         dw.dxfReal(50, data.angle);
2392     }
2393     if (data.cols!=1 || data.rows!=1) {
2394         dw.dxfInt(70, data.cols);
2395         dw.dxfInt(71, data.rows);
2396     }
2397     if (data.colSp!=0.0 || data.rowSp!=0.0) {
2398         dw.dxfReal(44, data.colSp);
2399         dw.dxfReal(45, data.rowSp);
2400     }
2401
2402 }
2403
2404
2405
2406 /**
2407  * Writes a multi text entity to the file.
2408  *
2409  * @param dw DXF writer
2410  * @param data Entity data from the file
2411  * @param attrib Attributes
2412  */
2413 void DL_Dxf::writeMText(DL_WriterA& dw,
2414                         const DL_MTextData& data,
2415                         const DL_Attributes& attrib) {
2416
2417     dw.entity("MTEXT");
2418     if (version==VER_2000) {
2419         dw.dxfString(100, "AcDbEntity");
2420         dw.dxfString(100, "AcDbMText");
2421     }
2422     dw.entityAttributes(attrib);
2423     dw.dxfReal(10, data.ipx);
2424     dw.dxfReal(20, data.ipy);
2425     dw.dxfReal(30, 0.0);
2426     dw.dxfReal(40, data.height);
2427     dw.dxfReal(41, data.width);
2428
2429     dw.dxfInt(71, data.attachmentPoint);
2430     dw.dxfInt(72, data.drawingDirection);
2431
2432     // Creare text chunks of 250 characters each:
2433     int length = data.text.length();
2434     char chunk[251];
2435     int i;
2436     for (i=250; i<length; i+=250) {
2437         strncpy(chunk, &data.text.c_str()[i-250], 250);
2438         chunk[250]='\0';
2439         dw.dxfString(3, chunk);
2440     }
2441     strncpy(chunk, &data.text.c_str()[i-250], 250);
2442     chunk[250]='\0';
2443     dw.dxfString(1, chunk);
2444
2445     dw.dxfString(7, data.style);
2446
2447     // since dxflib 2.0.2.1: degrees not rad (error in autodesk dxf doc)
2448     dw.dxfReal(50, data.angle/(2.0*M_PI)*360.0);
2449
2450     dw.dxfInt(73, data.lineSpacingStyle);
2451     dw.dxfReal(44, data.lineSpacingFactor);
2452 }
2453
2454
2455
2456 /**
2457  * Writes a text entity to the file.
2458  *
2459  * @param dw DXF writer
2460  * @param data Entity data from the file
2461  * @param attrib Attributes
2462  */
2463 void DL_Dxf::writeText(DL_WriterA& dw,
2464                        const DL_TextData& data,
2465                        const DL_Attributes& attrib) {
2466
2467     dw.entity("TEXT");
2468     if (version==VER_2000) {
2469         dw.dxfString(100, "AcDbEntity");
2470         dw.dxfString(100, "AcDbText");
2471     }
2472     dw.entityAttributes(attrib);
2473     dw.dxfReal(10, data.ipx);
2474     dw.dxfReal(20, data.ipy);
2475     dw.dxfReal(30, 0.0);
2476     dw.dxfReal(40, data.height);
2477     dw.dxfString(1, data.text);
2478     dw.dxfReal(50, data.angle/(2*M_PI)*360.0);
2479     dw.dxfReal(41, data.xScaleFactor);
2480     dw.dxfString(7, data.style);
2481
2482     dw.dxfInt(71, data.textGenerationFlags);
2483     dw.dxfInt(72, data.hJustification);
2484
2485     dw.dxfReal(11, data.apx);
2486     dw.dxfReal(21, data.apy);
2487     dw.dxfReal(31, 0.0);
2488
2489     dw.dxfInt(73, data.vJustification);
2490 }
2491
2492
2493 /**
2494  * Writes an aligned dimension entity to the file.
2495  *
2496  * @param dw DXF writer
2497  * @param data Generic dimension data for from the file
2498  * @param data Specific aligned dimension data from the file
2499  * @param attrib Attributes
2500  */
2501 void DL_Dxf::writeDimAligned(DL_WriterA& dw,
2502                              const DL_DimensionData& data,
2503                              const DL_DimAlignedData& edata,
2504                              const DL_Attributes& attrib) {
2505
2506     dw.entity("DIMENSION");
2507
2508     if (version==VER_2000) {
2509         dw.dxfString(100, "AcDbEntity");
2510     }
2511     dw.entityAttributes(attrib);
2512     if (version==VER_2000) {
2513         dw.dxfString(100, "AcDbDimension");
2514     }
2515
2516     dw.dxfReal(10, data.dpx);
2517     dw.dxfReal(20, data.dpy);
2518     dw.dxfReal(30, 0.0);
2519
2520     dw.dxfReal(11, data.mpx);
2521     dw.dxfReal(21, data.mpy);
2522     dw.dxfReal(31, 0.0);
2523
2524     dw.dxfInt(70, 1);
2525     if (version>VER_R12) {
2526         dw.dxfInt(71, data.attachmentPoint);
2527         dw.dxfInt(72, data.lineSpacingStyle); // opt
2528         dw.dxfReal(41, data.lineSpacingFactor); // opt
2529     }
2530
2531     dw.dxfReal(42, data.angle);
2532
2533     dw.dxfString(1, data.text);   // opt
2534     //dw.dxfString(3, data.style);
2535     dw.dxfString(3, "Standard");
2536
2537     if (version==VER_2000) {
2538         dw.dxfString(100, "AcDbAlignedDimension");
2539     }
2540
2541     dw.dxfReal(13, edata.epx1);
2542     dw.dxfReal(23, edata.epy1);
2543     dw.dxfReal(33, 0.0);
2544
2545     dw.dxfReal(14, edata.epx2);
2546     dw.dxfReal(24, edata.epy2);
2547     dw.dxfReal(34, 0.0);
2548 }
2549
2550
2551
2552 /**
2553  * Writes a linear dimension entity to the file.
2554  *
2555  * @param dw DXF writer
2556  * @param data Generic dimension data for from the file
2557  * @param data Specific linear dimension data from the file
2558  * @param attrib Attributes
2559  */
2560 void DL_Dxf::writeDimLinear(DL_WriterA& dw,
2561                             const DL_DimensionData& data,
2562                             const DL_DimLinearData& edata,
2563                             const DL_Attributes& attrib) {
2564
2565     dw.entity("DIMENSION");
2566
2567     if (version==VER_2000) {
2568         dw.dxfString(100, "AcDbEntity");
2569     }
2570     dw.entityAttributes(attrib);
2571     if (version==VER_2000) {
2572         dw.dxfString(100, "AcDbDimension");
2573     }
2574
2575     dw.dxfReal(10, data.dpx);
2576     dw.dxfReal(20, data.dpy);
2577     dw.dxfReal(30, 0.0);
2578
2579     dw.dxfReal(11, data.mpx);
2580     dw.dxfReal(21, data.mpy);
2581     dw.dxfReal(31, 0.0);
2582
2583     dw.dxfInt(70, 0);
2584     if (version>VER_R12) {
2585         dw.dxfInt(71, data.attachmentPoint);
2586         dw.dxfInt(72, data.lineSpacingStyle); // opt
2587         dw.dxfReal(41, data.lineSpacingFactor); // opt
2588     }
2589
2590     dw.dxfReal(42, data.angle);
2591
2592     dw.dxfString(1, data.text);   // opt
2593     //dw.dxfString(3, data.style);
2594     dw.dxfString(3, "Standard");
2595
2596     if (version==VER_2000) {
2597         dw.dxfString(100, "AcDbAlignedDimension");
2598     }
2599
2600     dw.dxfReal(13, edata.dpx1);
2601     dw.dxfReal(23, edata.dpy1);
2602     dw.dxfReal(33, 0.0);
2603
2604     dw.dxfReal(14, edata.dpx2);
2605     dw.dxfReal(24, edata.dpy2);
2606     dw.dxfReal(34, 0.0);
2607
2608     dw.dxfReal(50, edata.angle/(2.0*M_PI)*360.0);
2609
2610     if (version==VER_2000) {
2611         dw.dxfString(100, "AcDbRotatedDimension");
2612         /*
2613         dw.dxfString(1001, "ACAD");
2614         dw.dxfString(1000, "DSTYLE");
2615         dw.dxfString(1002, "{");
2616         dw.dxfInt(1070, 340);
2617         dw.dxfInt(1005, 11);
2618         dw.dxfString(1002, "}");
2619         */
2620     }
2621 }
2622
2623
2624
2625 /**
2626  * Writes a radial dimension entity to the file.
2627  *
2628  * @param dw DXF writer
2629  * @param data Generic dimension data for from the file
2630  * @param data Specific radial dimension data from the file
2631  * @param attrib Attributes
2632  */
2633 void DL_Dxf::writeDimRadial(DL_WriterA& dw,
2634                             const DL_DimensionData& data,
2635                             const DL_DimRadialData& edata,
2636                             const DL_Attributes& attrib) {
2637
2638     dw.entity("DIMENSION");
2639
2640     if (version==VER_2000) {
2641         dw.dxfString(100, "AcDbEntity");
2642     }
2643     dw.entityAttributes(attrib);
2644     if (version==VER_2000) {
2645         dw.dxfString(100, "AcDbDimension");
2646     }
2647
2648     dw.dxfReal(10, data.dpx);
2649     dw.dxfReal(20, data.dpy);
2650     dw.dxfReal(30, 0.0);
2651
2652     dw.dxfReal(11, data.mpx);
2653     dw.dxfReal(21, data.mpy);
2654     dw.dxfReal(31, 0.0);
2655
2656     dw.dxfInt(70, 4);
2657     if (version>VER_R12) {
2658         dw.dxfInt(71, data.attachmentPoint);
2659         dw.dxfInt(72, data.lineSpacingStyle); // opt
2660         dw.dxfReal(41, data.lineSpacingFactor); // opt
2661     }
2662
2663     dw.dxfReal(42, data.angle);
2664
2665     dw.dxfString(1, data.text);   // opt
2666     //dw.dxfString(3, data.style);
2667     dw.dxfString(3, "Standard");
2668
2669     if (version==VER_2000) {
2670         dw.dxfString(100, "AcDbRadialDimension");
2671     }
2672
2673     dw.dxfReal(15, edata.dpx);
2674     dw.dxfReal(25, edata.dpy);
2675     dw.dxfReal(35, 0.0);
2676
2677     dw.dxfReal(40, edata.leader);
2678 }
2679
2680
2681
2682 /**
2683  * Writes a diametric dimension entity to the file.
2684  *
2685  * @param dw DXF writer
2686  * @param data Generic dimension data for from the file
2687  * @param data Specific diametric dimension data from the file
2688  * @param attrib Attributes
2689  */
2690 void DL_Dxf::writeDimDiametric(DL_WriterA& dw,
2691                                const DL_DimensionData& data,
2692                                const DL_DimDiametricData& edata,
2693                                const DL_Attributes& attrib) {
2694
2695     dw.entity("DIMENSION");
2696
2697     if (version==VER_2000) {
2698         dw.dxfString(100, "AcDbEntity");
2699     }
2700     dw.entityAttributes(attrib);
2701     if (version==VER_2000) {
2702         dw.dxfString(100, "AcDbDimension");
2703     }
2704
2705     dw.dxfReal(10, data.dpx);
2706     dw.dxfReal(20, data.dpy);
2707     dw.dxfReal(30, 0.0);
2708
2709     dw.dxfReal(11, data.mpx);
2710     dw.dxfReal(21, data.mpy);
2711     dw.dxfReal(31, 0.0);
2712
2713     dw.dxfInt(70, 3);
2714     if (version>VER_R12) {
2715         dw.dxfInt(71, data.attachmentPoint);
2716         dw.dxfInt(72, data.lineSpacingStyle); // opt
2717         dw.dxfReal(41, data.lineSpacingFactor); // opt
2718     }
2719
2720     dw.dxfReal(42, data.angle);
2721
2722     dw.dxfString(1, data.text);   // opt
2723     //dw.dxfString(3, data.style);
2724     dw.dxfString(3, "Standard");
2725
2726     if (version==VER_2000) {
2727         dw.dxfString(100, "AcDbDiametricDimension");
2728     }
2729
2730     dw.dxfReal(15, edata.dpx);
2731     dw.dxfReal(25, edata.dpy);
2732     dw.dxfReal(35, 0.0);
2733
2734     dw.dxfReal(40, edata.leader);
2735 }
2736
2737
2738
2739 /**
2740  * Writes an angular dimension entity to the file.
2741  *
2742  * @param dw DXF writer
2743  * @param data Generic dimension data for from the file
2744  * @param data Specific angular dimension data from the file
2745  * @param attrib Attributes
2746  */
2747 void DL_Dxf::writeDimAngular(DL_WriterA& dw,
2748                              const DL_DimensionData& data,
2749                              const DL_DimAngularData& edata,
2750                              const DL_Attributes& attrib) {
2751
2752     dw.entity("DIMENSION");
2753
2754     if (version==VER_2000) {
2755         dw.dxfString(100, "AcDbEntity");
2756     }
2757     dw.entityAttributes(attrib);
2758     if (version==VER_2000) {
2759         dw.dxfString(100, "AcDbDimension");
2760     }
2761
2762     dw.dxfReal(10, data.dpx);
2763     dw.dxfReal(20, data.dpy);
2764     dw.dxfReal(30, 0.0);
2765
2766     dw.dxfReal(11, data.mpx);
2767     dw.dxfReal(21, data.mpy);
2768     dw.dxfReal(31, 0.0);
2769
2770     dw.dxfInt(70, 2);
2771     if (version>VER_R12) {
2772         dw.dxfInt(71, data.attachmentPoint);
2773         dw.dxfInt(72, data.lineSpacingStyle); // opt
2774         dw.dxfReal(41, data.lineSpacingFactor); // opt
2775     }
2776
2777     dw.dxfReal(42, data.angle);
2778
2779     dw.dxfString(1, data.text);   // opt
2780     //dw.dxfString(3, data.style);
2781     dw.dxfString(3, "Standard");
2782
2783     if (version==VER_2000) {
2784         dw.dxfString(100, "AcDb2LineAngularDimension");
2785     }
2786
2787     dw.dxfReal(13, edata.dpx1);
2788     dw.dxfReal(23, edata.dpy1);
2789     dw.dxfReal(33, 0.0);
2790
2791     dw.dxfReal(14, edata.dpx2);
2792     dw.dxfReal(24, edata.dpy2);
2793     dw.dxfReal(34, 0.0);
2794
2795     dw.dxfReal(15, edata.dpx3);
2796     dw.dxfReal(25, edata.dpy3);
2797     dw.dxfReal(35, 0.0);
2798
2799     dw.dxfReal(16, edata.dpx4);
2800     dw.dxfReal(26, edata.dpy4);
2801     dw.dxfReal(36, 0.0);
2802 }
2803
2804
2805
2806 /**
2807  * Writes an angular dimension entity (3 points version) to the file.
2808  *
2809  * @param dw DXF writer
2810  * @param data Generic dimension data for from the file
2811  * @param data Specific angular dimension data from the file
2812  * @param attrib Attributes
2813  */
2814 void DL_Dxf::writeDimAngular3P(DL_WriterA& dw,
2815                                const DL_DimensionData& data,
2816                                const DL_DimAngular3PData& edata,
2817                                const DL_Attributes& attrib) {
2818
2819     dw.entity("DIMENSION");
2820
2821     if (version==VER_2000) {
2822         dw.dxfString(100, "AcDbEntity");
2823     }
2824     dw.entityAttributes(attrib);
2825     if (version==VER_2000) {
2826         dw.dxfString(100, "AcDbDimension");
2827     }
2828
2829     dw.dxfReal(10, data.dpx);
2830     dw.dxfReal(20, data.dpy);
2831     dw.dxfReal(30, 0.0);
2832
2833     dw.dxfReal(11, data.mpx);
2834     dw.dxfReal(21, data.mpy);
2835     dw.dxfReal(31, 0.0);
2836
2837     dw.dxfInt(70, 5);
2838     if (version>VER_R12) {
2839         dw.dxfInt(71, data.attachmentPoint);
2840         dw.dxfInt(72, data.lineSpacingStyle); // opt
2841         dw.dxfReal(41, data.lineSpacingFactor); // opt
2842     }
2843
2844     dw.dxfReal(42, data.angle);
2845
2846     dw.dxfString(1, data.text);   // opt
2847     //dw.dxfString(3, data.style);
2848     dw.dxfString(3, "Standard");
2849
2850     if (version==VER_2000) {
2851         dw.dxfString(100, "AcDb3PointAngularDimension");
2852     }
2853
2854     dw.dxfReal(13, edata.dpx1);
2855     dw.dxfReal(23, edata.dpy1);
2856     dw.dxfReal(33, 0.0);
2857
2858     dw.dxfReal(14, edata.dpx2);
2859     dw.dxfReal(24, edata.dpy2);
2860     dw.dxfReal(34, 0.0);
2861
2862     dw.dxfReal(15, edata.dpx3);
2863     dw.dxfReal(25, edata.dpy3);
2864     dw.dxfReal(35, 0.0);
2865 }
2866
2867
2868
2869 /**
2870  * Writes a leader entity to the file.
2871  *
2872  * @param dw DXF writer
2873  * @param data Entity data from the file
2874  * @param attrib Attributes
2875  * @see writeVertex
2876  */
2877 void DL_Dxf::writeLeader(DL_WriterA& dw,
2878                          const DL_LeaderData& data,
2879                          const DL_Attributes& attrib) {
2880     if (version>VER_R12) {
2881         dw.entity("LEADER");
2882         dw.entityAttributes(attrib);
2883         if (version==VER_2000) {
2884             dw.dxfString(100, "AcDbEntity");
2885             dw.dxfString(100, "AcDbLeader");
2886         }
2887         dw.dxfString(3, "Standard");
2888         dw.dxfInt(71, data.arrowHeadFlag);
2889         dw.dxfInt(72, data.leaderPathType);
2890         dw.dxfInt(73, data.leaderCreationFlag);
2891         dw.dxfInt(74, data.hooklineDirectionFlag);
2892         dw.dxfInt(75, data.hooklineFlag);
2893         dw.dxfReal(40, data.textAnnotationHeight);
2894         dw.dxfReal(41, data.textAnnotationWidth);
2895         dw.dxfInt(76, data.number);
2896     }
2897 }
2898
2899
2900
2901 /**
2902  * Writes a single vertex of a leader to the file.
2903  *
2904  * @param dw DXF writer
2905  * @param data Entity data
2906  */
2907 void DL_Dxf::writeLeaderVertex(DL_WriterA& dw,
2908                                const DL_LeaderVertexData& data) {
2909     if (version>VER_R12) {
2910         dw.dxfReal(10, data.x);
2911         dw.dxfReal(20, data.y);
2912     }
2913 }
2914
2915
2916
2917 /**
2918  * Writes the beginning of a hatch entity to the file.
2919  * This must be followed by one or more writeHatchLoop()
2920  * calls and a writeHatch2() call.
2921  *
2922  * @param dw DXF writer
2923  * @param data Entity data.
2924  * @param attrib Attributes
2925  */
2926 void DL_Dxf::writeHatch1(DL_WriterA& dw,
2927                          const DL_HatchData& data,
2928                          const DL_Attributes& attrib) {
2929
2930     dw.entity("HATCH");
2931     dw.entityAttributes(attrib);
2932     if (version==VER_2000) {
2933         dw.dxfString(100, "AcDbEntity");
2934         dw.dxfString(100, "AcDbHatch");
2935     }
2936     dw.dxfReal(10, 0.0);             // elevation
2937     dw.dxfReal(20, 0.0);
2938     dw.dxfReal(30, 0.0);
2939     dw.dxfReal(210, 0.0);             // extrusion dir.
2940     dw.dxfReal(220, 0.0);
2941     dw.dxfReal(230, 1.0);
2942     if (data.solid==false) {
2943         dw.dxfString(2, data.pattern);
2944     } else {
2945         dw.dxfString(2, "SOLID");
2946     }
2947     dw.dxfInt(70, (int)data.solid);
2948     dw.dxfInt(71, 0);                // associative
2949     dw.dxfInt(91, data.numLoops);
2950 }
2951
2952
2953
2954 /**
2955  * Writes the end of a hatch entity to the file.
2956  *
2957  * @param dw DXF writer
2958  * @param data Entity data.
2959  * @param attrib Attributes
2960  */
2961 void DL_Dxf::writeHatch2(DL_WriterA& dw,
2962                          const DL_HatchData& data,
2963                          const DL_Attributes& /*attrib*/) {
2964
2965     dw.dxfInt(75, 0);                // odd parity
2966     dw.dxfInt(76, 1);                // pattern type
2967     if (data.solid==false) {
2968         dw.dxfReal(52, data.angle);
2969         dw.dxfReal(41, data.scale);
2970         dw.dxfInt(77, 0);            // not double
2971         //dw.dxfInt(78, 0);
2972         dw.dxfInt(78, 1);
2973         dw.dxfReal(53, 45.0);
2974         dw.dxfReal(43, 0.0);
2975         dw.dxfReal(44, 0.0);
2976         dw.dxfReal(45, -0.0883883476483184);
2977         dw.dxfReal(46, 0.0883883476483185);
2978         dw.dxfInt(79, 0);
2979     }
2980     dw.dxfInt(98, 0);
2981 }
2982
2983
2984
2985 /**
2986  * Writes the beginning of a hatch loop to the file. This
2987  * must happen after writing the beginning of a hatch entity.
2988  *
2989  * @param dw DXF writer
2990  * @param data Entity data.
2991  * @param attrib Attributes
2992  */
2993 void DL_Dxf::writeHatchLoop1(DL_WriterA& dw,
2994                              const DL_HatchLoopData& data) {
2995
2996     dw.dxfInt(92, 1);
2997     dw.dxfInt(93, data.numEdges);
2998     //dw.dxfInt(97, 0);
2999 }
3000
3001
3002
3003 /**
3004  * Writes the end of a hatch loop to the file.
3005  *
3006  * @param dw DXF writer
3007  * @param data Entity data.
3008  * @param attrib Attributes
3009  */
3010 void DL_Dxf::writeHatchLoop2(DL_WriterA& dw,
3011                              const DL_HatchLoopData& /*data*/) {
3012
3013     dw.dxfInt(97, 0);
3014 }
3015
3016
3017 /**
3018  * Writes the beginning of a hatch entity to the file.
3019  *
3020  * @param dw DXF writer
3021  * @param data Entity data.
3022  * @param attrib Attributes
3023  */
3024 void DL_Dxf::writeHatchEdge(DL_WriterA& dw,
3025                             const DL_HatchEdgeData& data) {
3026
3027     dw.dxfInt(72, data.type);
3028
3029     switch (data.type) {
3030     case 1:
3031         dw.dxfReal(10, data.x1);
3032         dw.dxfReal(20, data.y1);
3033         dw.dxfReal(11, data.x2);
3034         dw.dxfReal(21, data.y2);
3035         break;
3036     case 2:
3037         dw.dxfReal(10, data.cx);
3038         dw.dxfReal(20, data.cy);
3039         dw.dxfReal(40, data.radius);
3040         dw.dxfReal(50, data.angle1/(2*M_PI)*360.0);
3041         dw.dxfReal(51, data.angle2/(2*M_PI)*360.0);
3042         dw.dxfInt(73, (int)(data.ccw));
3043         break;
3044     default:
3045         break;
3046     }
3047 }
3048
3049
3050
3051 /**
3052  * Writes an image entity.
3053  *
3054  * @return IMAGEDEF handle. Needed for the IMAGEDEF counterpart.
3055  */
3056 int DL_Dxf::writeImage(DL_WriterA& dw,
3057                        const DL_ImageData& data,
3058                        const DL_Attributes& attrib) {
3059
3060     /*if (data.file.empty()) {
3061         std::cerr << "DL_Dxf::writeImage: "
3062         << "Image file must not be empty\n";
3063         return;
3064 }*/
3065
3066     dw.entity("IMAGE");
3067
3068     dw.entityAttributes(attrib);
3069     if (version==VER_2000) {
3070         dw.dxfString(100, "AcDbEntity");
3071         dw.dxfString(100, "AcDbRasterImage");
3072         dw.dxfInt(90, 0);
3073     }
3074     // insertion point
3075     dw.dxfReal(10, data.ipx);
3076     dw.dxfReal(20, data.ipy);
3077     dw.dxfReal(30, 0.0);
3078
3079     // vector along bottom side (1 pixel long)
3080     dw.dxfReal(11, data.ux);
3081     dw.dxfReal(21, data.uy);
3082     dw.dxfReal(31, 0.0);
3083
3084     // vector along left side (1 pixel long)
3085     dw.dxfReal(12, data.vx);
3086     dw.dxfReal(22, data.vy);
3087     dw.dxfReal(32, 0.0);
3088
3089     // image size in pixel
3090     dw.dxfReal(13, data.width);
3091     dw.dxfReal(23, data.height);
3092
3093     // handle of IMAGEDEF object
3094     int handle = dw.incHandle();
3095     dw.dxfHex(340, handle);
3096
3097     // flags
3098     dw.dxfInt(70, 15);
3099
3100     // clipping:
3101     dw.dxfInt(280, 0);
3102
3103     // brightness, contrast, fade
3104     dw.dxfInt(281, data.brightness);
3105     dw.dxfInt(282, data.contrast);
3106     dw.dxfInt(283, data.fade);
3107
3108     return handle;
3109 }
3110
3111
3112
3113 /**
3114  * Writes an image definiition entity.
3115  */
3116 void DL_Dxf::writeImageDef(DL_WriterA& dw,
3117                            int handle,
3118                            const DL_ImageData& data) {
3119
3120     /*if (data.file.empty()) {
3121         std::cerr << "DL_Dxf::writeImage: "
3122         << "Image file must not be empty\n";
3123         return;
3124 }*/
3125
3126     dw.dxfString(0, "IMAGEDEF");
3127     if (version==VER_2000) {
3128         dw.dxfHex(5, handle);
3129         }
3130
3131     if (version==VER_2000) {
3132         dw.dxfString(100, "AcDbRasterImageDef");
3133         dw.dxfInt(90, 0);
3134     }
3135     // file name:
3136     dw.dxfString(1, data.ref);
3137
3138     // image size in pixel
3139     dw.dxfReal(10, data.width);
3140     dw.dxfReal(20, data.height);
3141
3142     dw.dxfReal(11, 1.0);
3143     dw.dxfReal(21, 1.0);
3144
3145     // loaded:
3146     dw.dxfInt(280, 1);
3147     // units:
3148     dw.dxfInt(281, 0);
3149 }
3150
3151
3152 /**
3153  * Writes a layer to the file. Layers are stored in the 
3154  * tables section of a DXF file.
3155  *
3156  * @param dw DXF writer
3157  * @param data Entity data from the file
3158  * @param attrib Attributes
3159  */
3160 void DL_Dxf::writeLayer(DL_WriterA& dw,
3161                         const DL_LayerData& data,
3162                         const DL_Attributes& attrib) {
3163
3164     if (data.name.empty()) {
3165         std::cerr << "DL_Dxf::writeLayer: "
3166         << "Layer name must not be empty\n";
3167         return;
3168     }
3169
3170     int color = attrib.getColor();
3171     if (color<=0 || color>=256) {
3172         std::cerr << "Layer color cannot be " << color << ". Changed to 7.\n";
3173         color = 7;
3174     }
3175
3176     if (data.name == "0") {
3177         dw.tableLayerEntry(0x10);
3178     } else {
3179         dw.tableLayerEntry();
3180     }
3181
3182     dw.dxfString(2, data.name);
3183     dw.dxfInt(70, data.flags);
3184     dw.dxfInt(62, color);
3185
3186     dw.dxfString(6, (attrib.getLineType().length()==0 ?
3187                      string("CONTINUOUS") : attrib.getLineType()));
3188
3189     if (version>=VER_2000) {
3190         // layer defpoints cannot be plotted
3191         std::string lstr = data.name;
3192         std::transform(lstr.begin(), lstr.end(), lstr.begin(), tolower);
3193         if (lstr=="defpoints") {
3194             dw.dxfInt(290, 0);
3195         }
3196     }
3197     if (version>=VER_2000 && attrib.getWidth()!=-1) {
3198         dw.dxfInt(370, attrib.getWidth());
3199     }
3200     if (version>=VER_2000) {
3201         dw.dxfHex(390, 0xF);
3202     }
3203 }
3204
3205
3206
3207 /**
3208  * Writes a line type to the file. Line types are stored in the 
3209  * tables section of a DXF file.
3210  */
3211 void DL_Dxf::writeLineType(DL_WriterA& dw,
3212                            const DL_LineTypeData& data) {
3213     //const char* description,
3214     //int elements,
3215     //double patternLength) {
3216
3217     if (data.name.empty()) {
3218         std::cerr << "DL_Dxf::writeLineType: "
3219         << "Line type name must not be empty\n";
3220         return;
3221     }
3222
3223         // ignore BYLAYER, BYBLOCK for R12
3224         if (version<VER_2000) {
3225                 if (!strcasecmp(data.name.c_str(), "BYBLOCK") ||
3226                     !strcasecmp(data.name.c_str(), "BYLAYER")) {
3227                         return;
3228                 }
3229         }
3230
3231         // write id (not for R12)
3232     if (!strcasecmp(data.name.c_str(), "BYBLOCK")) {
3233         dw.tableLineTypeEntry(0x14);
3234     } else if (!strcasecmp(data.name.c_str(), "BYLAYER")) {
3235         dw.tableLineTypeEntry(0x15);
3236     } else if (!strcasecmp(data.name.c_str(), "CONTINUOUS")) {
3237         dw.tableLineTypeEntry(0x16);
3238     } else {
3239         dw.tableLineTypeEntry();
3240     }
3241
3242     dw.dxfString(2, data.name);
3243         //if (version>=VER_2000) {
3244         dw.dxfInt(70, data.flags);
3245         //}
3246
3247     if (!strcasecmp(data.name.c_str(), "BYBLOCK")) {
3248         dw.dxfString(3, "");
3249         dw.dxfInt(72, 65);
3250         dw.dxfInt(73, 0);
3251         dw.dxfReal(40, 0.0);
3252     } else if (!strcasecmp(data.name.c_str(), "BYLAYER")) {
3253         dw.dxfString(3, "");
3254         dw.dxfInt(72, 65);
3255         dw.dxfInt(73, 0);
3256         dw.dxfReal(40, 0.0);
3257     } else if (!strcasecmp(data.name.c_str(), "CONTINUOUS")) {
3258         dw.dxfString(3, "Solid line");
3259         dw.dxfInt(72, 65);
3260         dw.dxfInt(73, 0);
3261         dw.dxfReal(40, 0.0);
3262     } else if (!strcasecmp(data.name.c_str(), "ACAD_ISO02W100")) {
3263         dw.dxfString(3, "ISO Dashed __ __ __ __ __ __ __ __ __ __ _");
3264         dw.dxfInt(72, 65);
3265         dw.dxfInt(73, 2);
3266         dw.dxfReal(40, 15.0);
3267         dw.dxfReal(49, 12.0);
3268         if (version>=VER_R13)
3269             dw.dxfInt(74, 0);
3270         dw.dxfReal(49, -3.0);
3271         if (version>=VER_R13)
3272             dw.dxfInt(74, 0);
3273     } else if (!strcasecmp(data.name.c_str(), "ACAD_ISO03W100")) {
3274         dw.dxfString(3, "ISO Dashed with Distance __    __    __    _");
3275         dw.dxfInt(72, 65);
3276         dw.dxfInt(73, 2);
3277         dw.dxfReal(40, 30.0);
3278         dw.dxfReal(49, 12.0);
3279         if (version>=VER_R13)
3280             dw.dxfInt(74, 0);
3281         dw.dxfReal(49, -18.0);
3282         if (version>=VER_R13)
3283             dw.dxfInt(74, 0);
3284     } else if (!strcasecmp(data.name.c_str(), "ACAD_ISO04W100")) {
3285         dw.dxfString(3, "ISO Long Dashed Dotted ____ . ____ . __");
3286         dw.dxfInt(72, 65);
3287         dw.dxfInt(73, 4);
3288         dw.dxfReal(40, 30.0);
3289         dw.dxfReal(49, 24.0);
3290         if (version>=VER_R13)
3291             dw.dxfInt(74, 0);
3292         dw.dxfReal(49, -3.0);
3293         if (version>=VER_R13)
3294             dw.dxfInt(74, 0);
3295         dw.dxfReal(49, 0.0);
3296         if (version>=VER_R13)
3297             dw.dxfInt(74, 0);
3298         dw.dxfReal(49, -3.0);
3299         if (version>=VER_R13)
3300             dw.dxfInt(74, 0);
3301     } else if (!strcasecmp(data.name.c_str(), "ACAD_ISO05W100")) {
3302         dw.dxfString(3, "ISO Long Dashed Double Dotted ____ .. __");
3303         dw.dxfInt(72, 65);
3304         dw.dxfInt(73, 6);
3305         dw.dxfReal(40, 33.0);
3306         dw.dxfReal(49, 24.0);
3307         if (version>=VER_R13)
3308             dw.dxfInt(74, 0);
3309         dw.dxfReal(49, -3.0);
3310         if (version>=VER_R13)
3311             dw.dxfInt(74, 0);
3312         dw.dxfReal(49, 0.0);
3313         if (version>=VER_R13)
3314             dw.dxfInt(74, 0);
3315         dw.dxfReal(49, -3.0);
3316         if (version>=VER_R13)
3317             dw.dxfInt(74, 0);
3318         dw.dxfReal(49, 0.0);
3319         if (version>=VER_R13)
3320             dw.dxfInt(74, 0);
3321         dw.dxfReal(49, -3.0);
3322         if (version>=VER_R13)
3323             dw.dxfInt(74, 0);
3324     } else if (!strcasecmp(data.name.c_str(), "BORDER")) {
3325         dw.dxfString(3, "Border __ __ . __ __ . __ __ . __ __ . __ __ .");
3326         dw.dxfInt(72, 65);
3327         dw.dxfInt(73, 6);
3328         dw.dxfReal(40, 44.45);
3329         dw.dxfReal(49, 12.7);
3330         if (version>=VER_R13)
3331             dw.dxfInt(74, 0);
3332         dw.dxfReal(49, -6.35);
3333         if (version>=VER_R13)
3334             dw.dxfInt(74, 0);
3335         dw.dxfReal(49, 12.7);
3336         if (version>=VER_R13)
3337             dw.dxfInt(74, 0);
3338         dw.dxfReal(49, -6.35);
3339         if (version>=VER_R13)
3340             dw.dxfInt(74, 0);
3341         dw.dxfReal(49, 0.0);
3342         if (version>=VER_R13)
3343             dw.dxfInt(74, 0);
3344         dw.dxfReal(49, -6.35);
3345         if (version>=VER_R13)
3346             dw.dxfInt(74, 0);
3347     } else if (!strcasecmp(data.name.c_str(), "BORDER2")) {
3348         dw.dxfString(3, "Border (.5x) __.__.__.__.__.__.__.__.__.__.__.");
3349         dw.dxfInt(72, 65);
3350         dw.dxfInt(73, 6);
3351         dw.dxfReal(40, 22.225);
3352         dw.dxfReal(49, 6.35);
3353         if (version>=VER_R13)
3354             dw.dxfInt(74, 0);
3355         dw.dxfReal(49, -3.175);
3356         if (version>=VER_R13)
3357             dw.dxfInt(74, 0);
3358         dw.dxfReal(49, 6.35);
3359         if (version>=VER_R13)
3360             dw.dxfInt(74, 0);
3361         dw.dxfReal(49, -3.175);
3362         if (version>=VER_R13)
3363             dw.dxfInt(74, 0);
3364         dw.dxfReal(49, 0.0);
3365         if (version>=VER_R13)
3366             dw.dxfInt(74, 0);
3367         dw.dxfReal(49, -3.175);
3368         if (version>=VER_R13)
3369             dw.dxfInt(74, 0);
3370     } else if (!strcasecmp(data.name.c_str(), "BORDERX2")) {
3371         dw.dxfString(3, "Border (2x) ____  ____  .  ____  ____  .  ___");
3372         dw.dxfInt(72, 65);
3373         dw.dxfInt(73, 6);
3374         dw.dxfReal(40, 88.9);
3375         dw.dxfReal(49, 25.4);
3376         if (version>=VER_R13)
3377             dw.dxfInt(74, 0);
3378         dw.dxfReal(49, -12.7);
3379         if (version>=VER_R13)
3380             dw.dxfInt(74, 0);
3381         dw.dxfReal(49, 25.4);
3382         if (version>=VER_R13)
3383             dw.dxfInt(74, 0);
3384         dw.dxfReal(49, -12.7);
3385         if (version>=VER_R13)
3386             dw.dxfInt(74, 0);
3387         dw.dxfReal(49, 0.0);
3388         if (version>=VER_R13)
3389             dw.dxfInt(74, 0);
3390         dw.dxfReal(49, -12.7);
3391         if (version>=VER_R13)
3392             dw.dxfInt(74, 0);
3393     } else if (!strcasecmp(data.name.c_str(), "CENTER")) {
3394         dw.dxfString(3, "Center ____ _ ____ _ ____ _ ____ _ ____ _ ____");
3395         dw.dxfInt(72, 65);
3396         dw.dxfInt(73, 4);
3397         dw.dxfReal(40, 50.8);
3398         dw.dxfReal(49, 31.75);
3399         if (version>=VER_R13)
3400             dw.dxfInt(74, 0);
3401         dw.dxfReal(49, -6.35);
3402         if (version>=VER_R13)
3403             dw.dxfInt(74, 0);
3404         dw.dxfReal(49, 6.35);
3405         if (version>=VER_R13)
3406             dw.dxfInt(74, 0);
3407         dw.dxfReal(49, -6.35);
3408         if (version>=VER_R13)
3409             dw.dxfInt(74, 0);
3410     } else if (!strcasecmp(data.name.c_str(), "CENTER2")) {
3411         dw.dxfString(3, "Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___");
3412         dw.dxfInt(72, 65);
3413         dw.dxfInt(73, 4);
3414         dw.dxfReal(40, 28.575);
3415         dw.dxfReal(49, 19.05);
3416         if (version>=VER_R13)
3417             dw.dxfInt(74, 0);
3418         dw.dxfReal(49, -3.175);
3419         if (version>=VER_R13)
3420             dw.dxfInt(74, 0);
3421         dw.dxfReal(49, 3.175);
3422         if (version>=VER_R13)
3423             dw.dxfInt(74, 0);
3424         dw.dxfReal(49, -3.175);
3425         if (version>=VER_R13)
3426             dw.dxfInt(74, 0);
3427     } else if (!strcasecmp(data.name.c_str(), "CENTERX2")) {
3428         dw.dxfString(3, "Center (2x) ________  __  ________  __  _____");
3429         dw.dxfInt(72, 65);
3430         dw.dxfInt(73, 4);
3431         dw.dxfReal(40, 101.6);
3432         dw.dxfReal(49, 63.5);
3433         if (version>=VER_R13)
3434             dw.dxfInt(74, 0);
3435         dw.dxfReal(49, -12.7);
3436         if (version>=VER_R13)
3437             dw.dxfInt(74, 0);
3438         dw.dxfReal(49, 12.7);
3439         if (version>=VER_R13)
3440             dw.dxfInt(74, 0);
3441         dw.dxfReal(49, -12.7);
3442         if (version>=VER_R13)
3443             dw.dxfInt(74, 0);
3444     } else if (!strcasecmp(data.name.c_str(), "DASHDOT")) {
3445         dw.dxfString(3, "Dash dot __ . __ . __ . __ . __ . __ . __ . __");
3446         dw.dxfInt(72, 65);
3447         dw.dxfInt(73, 4);
3448         dw.dxfReal(40, 25.4);
3449         dw.dxfReal(49, 12.7);
3450         if (version>=VER_R13)
3451             dw.dxfInt(74, 0);
3452         dw.dxfReal(49, -6.35);
3453         if (version>=VER_R13)
3454             dw.dxfInt(74, 0);
3455         dw.dxfReal(49, 0.0);
3456         if (version>=VER_R13)
3457             dw.dxfInt(74, 0);
3458         dw.dxfReal(49, -6.35);
3459         if (version>=VER_R13)
3460             dw.dxfInt(74, 0);
3461     } else if (!strcasecmp(data.name.c_str(), "DASHDOT2")) {
3462         dw.dxfString(3, "Dash dot (.5x) _._._._._._._._._._._._._._._.");
3463         dw.dxfInt(72, 65);
3464         dw.dxfInt(73, 4);
3465         dw.dxfReal(40, 12.7);
3466         dw.dxfReal(49, 6.35);
3467         if (version>=VER_R13)
3468             dw.dxfInt(74, 0);
3469         dw.dxfReal(49, -3.175);
3470         if (version>=VER_R13)
3471             dw.dxfInt(74, 0);
3472         dw.dxfReal(49, 0.0);
3473         if (version>=VER_R13)
3474             dw.dxfInt(74, 0);
3475         dw.dxfReal(49, -3.175);
3476         if (version>=VER_R13)
3477             dw.dxfInt(74, 0);
3478     } else if (!strcasecmp(data.name.c_str(), "DASHDOTX2")) {
3479         dw.dxfString(3, "Dash dot (2x) ____  .  ____  .  ____  .  ___");
3480         dw.dxfInt(72, 65);
3481         dw.dxfInt(73, 4);
3482         dw.dxfReal(40, 50.8);
3483         dw.dxfReal(49, 25.4);
3484         if (version>=VER_R13)
3485             dw.dxfInt(74, 0);
3486         dw.dxfReal(49, -12.7);
3487         if (version>=VER_R13)
3488             dw.dxfInt(74, 0);
3489         dw.dxfReal(49, 0.0);
3490         if (version>=VER_R13)
3491             dw.dxfInt(74, 0);
3492         dw.dxfReal(49, -12.7);
3493         if (version>=VER_R13)
3494             dw.dxfInt(74, 0);
3495     } else if (!strcasecmp(data.name.c_str(), "DASHED")) {
3496         dw.dxfString(3, "Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _");
3497         dw.dxfInt(72, 65);
3498         dw.dxfInt(73, 2);
3499         dw.dxfReal(40, 19.05);
3500         dw.dxfReal(49, 12.7);
3501         if (version>=VER_R13)
3502             dw.dxfInt(74, 0);
3503         dw.dxfReal(49, -6.35);
3504         if (version>=VER_R13)
3505             dw.dxfInt(74, 0);
3506     } else if (!strcasecmp(data.name.c_str(), "DASHED2")) {
3507         dw.dxfString(3, "Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _");
3508         dw.dxfInt(72, 65);
3509         dw.dxfInt(73, 2);
3510         dw.dxfReal(40, 9.525);
3511         dw.dxfReal(49, 6.35);
3512         if (version>=VER_R13)
3513             dw.dxfInt(74, 0);
3514         dw.dxfReal(49, -3.175);
3515         if (version>=VER_R13)
3516             dw.dxfInt(74, 0);
3517     } else if (!strcasecmp(data.name.c_str(), "DASHEDX2")) {
3518         dw.dxfString(3, "Dashed (2x) ____  ____  ____  ____  ____  ___");
3519         dw.dxfInt(72, 65);
3520         dw.dxfInt(73, 2);
3521         dw.dxfReal(40, 38.1);
3522         dw.dxfReal(49, 25.4);
3523         if (version>=VER_R13)
3524             dw.dxfInt(74, 0);
3525         dw.dxfReal(49, -12.7);
3526         if (version>=VER_R13)
3527             dw.dxfInt(74, 0);
3528     } else if (!strcasecmp(data.name.c_str(), "DIVIDE")) {
3529         dw.dxfString(3, "Divide ____ . . ____ . . ____ . . ____ . . ____");
3530         dw.dxfInt(72, 65);
3531         dw.dxfInt(73, 6);
3532         dw.dxfReal(40, 31.75);
3533         dw.dxfReal(49, 12.7);
3534         if (version>=VER_R13)
3535             dw.dxfInt(74, 0);
3536         dw.dxfReal(49, -6.35);
3537         if (version>=VER_R13)
3538             dw.dxfInt(74, 0);
3539         dw.dxfReal(49, 0.0);
3540         if (version>=VER_R13)
3541             dw.dxfInt(74, 0);
3542         dw.dxfReal(49, -6.35);
3543         if (version>=VER_R13)
3544             dw.dxfInt(74, 0);
3545         dw.dxfReal(49, 0.0);
3546         if (version>=VER_R13)
3547             dw.dxfInt(74, 0);
3548         dw.dxfReal(49, -6.35);
3549         if (version>=VER_R13)
3550             dw.dxfInt(74, 0);
3551     } else if (!strcasecmp(data.name.c_str(), "DIVIDE2")) {
3552         dw.dxfString(3, "Divide (.5x) __..__..__..__..__..__..__..__.._");
3553         dw.dxfInt(72, 65);
3554         dw.dxfInt(73, 6);
3555         dw.dxfReal(40, 15.875);
3556         dw.dxfReal(49, 6.35);
3557         if (version>=VER_R13)
3558             dw.dxfInt(74, 0);
3559         dw.dxfReal(49, -3.175);
3560         if (version>=VER_R13)
3561             dw.dxfInt(74, 0);
3562         dw.dxfReal(49, 0.0);
3563         if (version>=VER_R13)
3564             dw.dxfInt(74, 0);
3565         dw.dxfReal(49, -3.175);
3566         if (version>=VER_R13)
3567             dw.dxfInt(74, 0);
3568         dw.dxfReal(49, 0.0);
3569         if (version>=VER_R13)
3570             dw.dxfInt(74, 0);
3571         dw.dxfReal(49, -3.175);
3572         if (version>=VER_R13)
3573             dw.dxfInt(74, 0);
3574     } else if (!strcasecmp(data.name.c_str(), "DIVIDEX2")) {
3575         dw.dxfString(3, "Divide (2x) ________  .  .  ________  .  .  _");
3576         dw.dxfInt(72, 65);
3577         dw.dxfInt(73, 6);
3578         dw.dxfReal(40, 63.5);
3579         dw.dxfReal(49, 25.4);
3580         if (version>=VER_R13)
3581             dw.dxfInt(74, 0);
3582         dw.dxfReal(49, -12.7);
3583         if (version>=VER_R13)
3584             dw.dxfInt(74, 0);
3585         dw.dxfReal(49, 0.0);
3586         if (version>=VER_R13)
3587             dw.dxfInt(74, 0);
3588         dw.dxfReal(49, -12.7);
3589         if (version>=VER_R13)
3590             dw.dxfInt(74, 0);
3591         dw.dxfReal(49, 0.0);
3592         if (version>=VER_R13)
3593             dw.dxfInt(74, 0);
3594         dw.dxfReal(49, -12.7);
3595         if (version>=VER_R13)
3596             dw.dxfInt(74, 0);
3597     } else if (!strcasecmp(data.name.c_str(), "DOT")) {
3598         dw.dxfString(3, "Dot . . . . . . . . . . . . . . . . . . . . . .");
3599         dw.dxfInt(72, 65);
3600         dw.dxfInt(73, 2);
3601         dw.dxfReal(40, 6.35);
3602         dw.dxfReal(49, 0.0);
3603         if (version>=VER_R13)
3604             dw.dxfInt(74, 0);
3605         dw.dxfReal(49, -6.35);
3606         if (version>=VER_R13)
3607             dw.dxfInt(74, 0);
3608     } else if (!strcasecmp(data.name.c_str(), "DOT2")) {
3609         dw.dxfString(3, "Dot (.5x) .....................................");
3610         dw.dxfInt(72, 65);
3611         dw.dxfInt(73, 2);
3612         dw.dxfReal(40, 3.175);
3613         dw.dxfReal(49, 0.0);
3614         if (version>=VER_R13)
3615             dw.dxfInt(74, 0);
3616         dw.dxfReal(49, -3.175);
3617         if (version>=VER_R13)
3618             dw.dxfInt(74, 0);
3619     } else if (!strcasecmp(data.name.c_str(), "DOTX2")) {
3620         dw.dxfString(3, "Dot (2x) .  .  .  .  .  .  .  .  .  .  .  .  .");
3621         dw.dxfInt(72, 65);
3622         dw.dxfInt(73, 2);
3623         dw.dxfReal(40, 12.7);
3624         dw.dxfReal(49, 0.0);
3625         if (version>=VER_R13)
3626             dw.dxfInt(74, 0);
3627         dw.dxfReal(49, -12.7);
3628         if (version>=VER_R13)
3629             dw.dxfInt(74, 0);
3630     } else {
3631         std::cerr << "dxflib warning: DL_Dxf::writeLineType: Unknown Line Type\n";
3632     }
3633 }
3634
3635
3636
3637 /**
3638  * Writes the APPID section to the DXF file.
3639  *
3640  * @param name Application name
3641  */
3642 void DL_Dxf::writeAppid(DL_WriterA& dw, const string& name) {
3643     if (name.empty()) {
3644         std::cerr << "DL_Dxf::writeAppid: "
3645         << "Application  name must not be empty\n";
3646         return;
3647     }
3648
3649     if (!strcasecmp(name.c_str(), "ACAD")) {
3650         dw.tableAppidEntry(0x12);
3651     } else {
3652         dw.tableAppidEntry();
3653     }
3654     dw.dxfString(2, name);
3655     dw.dxfInt(70, 0);
3656 }
3657
3658
3659
3660 /**
3661  * Writes a block's definition (no entities) to the DXF file.
3662  */
3663 void DL_Dxf::writeBlock(DL_WriterA& dw, const DL_BlockData& data) {
3664     if (data.name.empty()) {
3665         std::cerr << "DL_Dxf::writeBlock: "
3666         << "Block name must not be empty\n";
3667         return;
3668     }
3669
3670     //bool paperSpace = !strcasecmp(name, "*paper_space");
3671     //!strcasecmp(name, "*paper_space0");
3672
3673     if (!strcasecmp(data.name.c_str(), "*paper_space")) {
3674         dw.sectionBlockEntry(0x1C);
3675     } else if (!strcasecmp(data.name.c_str(), "*model_space")) {
3676         dw.sectionBlockEntry(0x20);
3677     } else if (!strcasecmp(data.name.c_str(), "*paper_space0")) {
3678         dw.sectionBlockEntry(0x24);
3679     } else {
3680         dw.sectionBlockEntry();
3681     }
3682     dw.dxfString(2, data.name);
3683     dw.dxfInt(70, 0);
3684     dw.coord(10, data.bpx, data.bpy);
3685     dw.dxfString(3, data.name);
3686     dw.dxfString(1, "");
3687 }
3688
3689
3690
3691 /**
3692  * Writes a block end.
3693  *
3694  * @param name Block name
3695  */
3696 void DL_Dxf::writeEndBlock(DL_WriterA& dw, const string& name) {
3697     if (!strcasecmp(name.c_str(), "*paper_space")) {
3698         dw.sectionBlockEntryEnd(0x1D);
3699     } else if (!strcasecmp(name.c_str(), "*model_space")) {
3700         dw.sectionBlockEntryEnd(0x21);
3701     } else if (!strcasecmp(name.c_str(), "*paper_space0")) {
3702         dw.sectionBlockEntryEnd(0x25);
3703     } else {
3704         dw.sectionBlockEntryEnd();
3705     }
3706 }
3707
3708
3709
3710 /**
3711  * Writes a viewport section. This section is needed in VER_R13.
3712  * Note that this method currently only writes a faked VPORT section
3713  * to make the file readable by Aut*cad.
3714  */
3715 void DL_Dxf::writeVPort(DL_WriterA& dw) {
3716     dw.dxfString(0, "TABLE");
3717     dw.dxfString(2, "VPORT");
3718     if (version==VER_2000) {
3719         dw.dxfHex(5, 0x8);
3720     }
3721     //dw.dxfHex(330, 0);
3722     if (version==VER_2000) {
3723         dw.dxfString(100, "AcDbSymbolTable");
3724     }
3725     dw.dxfInt(70, 1);
3726     dw.dxfString(0, "VPORT");
3727     //dw.dxfHex(5, 0x2F);
3728     if (version==VER_2000) {
3729         dw.handle();
3730     }
3731     //dw.dxfHex(330, 8);
3732     if (version==VER_2000) {
3733         dw.dxfString(100, "AcDbSymbolTableRecord");
3734         dw.dxfString(100, "AcDbViewportTableRecord");
3735     }
3736     dw.dxfString(  2, "*Active");
3737     dw.dxfInt( 70, 0);
3738     dw.dxfReal( 10, 0.0);
3739     dw.dxfReal( 20, 0.0);
3740     dw.dxfReal( 11, 1.0);
3741     dw.dxfReal( 21, 1.0);
3742     dw.dxfReal( 12, 286.3055555555555);
3743     dw.dxfReal( 22, 148.5);
3744     dw.dxfReal( 13, 0.0);
3745     dw.dxfReal( 23, 0.0);
3746     dw.dxfReal( 14, 10.0);
3747     dw.dxfReal( 24, 10.0);
3748     dw.dxfReal( 15, 10.0);
3749     dw.dxfReal( 25, 10.0);
3750     dw.dxfReal( 16, 0.0);
3751     dw.dxfReal( 26, 0.0);
3752     dw.dxfReal( 36, 1.0);
3753     dw.dxfReal( 17, 0.0);
3754     dw.dxfReal( 27, 0.0);
3755     dw.dxfReal( 37, 0.0);
3756     dw.dxfReal( 40, 297.0);
3757     dw.dxfReal( 41, 1.92798353909465);
3758     dw.dxfReal( 42, 50.0);
3759     dw.dxfReal( 43, 0.0);
3760     dw.dxfReal( 44, 0.0);
3761     dw.dxfReal( 50, 0.0);
3762     dw.dxfReal( 51, 0.0);
3763     dw.dxfInt( 71, 0);
3764     dw.dxfInt( 72, 100);
3765     dw.dxfInt( 73, 1);
3766     dw.dxfInt( 74, 3);
3767     dw.dxfInt( 75, 1);
3768     dw.dxfInt( 76, 1);
3769     dw.dxfInt( 77, 0);
3770     dw.dxfInt( 78, 0);
3771
3772     if (version==VER_2000) {
3773         dw.dxfInt(281, 0);
3774         dw.dxfInt( 65, 1);
3775         dw.dxfReal(110, 0.0);
3776         dw.dxfReal(120, 0.0);
3777         dw.dxfReal(130, 0.0);
3778         dw.dxfReal(111, 1.0);
3779         dw.dxfReal(121, 0.0);
3780         dw.dxfReal(131, 0.0);
3781         dw.dxfReal(112, 0.0);
3782         dw.dxfReal(122, 1.0);
3783         dw.dxfReal(132, 0.0);
3784         dw.dxfInt( 79, 0);
3785         dw.dxfReal(146, 0.0);
3786     }
3787     dw.dxfString(  0, "ENDTAB");
3788 }
3789
3790
3791
3792 /**
3793  * Writes a style section. This section is needed in VER_R13.
3794  * Note that this method currently only writes a faked STYLE section
3795  * to make the file readable by Aut*cad.
3796  */
3797 void DL_Dxf::writeStyle(DL_WriterA& dw) {
3798     dw.dxfString(  0, "TABLE");
3799     dw.dxfString(  2, "STYLE");
3800     if (version==VER_2000) {
3801         dw.dxfHex(5, 3);
3802         }
3803     //dw.dxfHex(330, 0);
3804     if (version==VER_2000) {
3805         dw.dxfString(100, "AcDbSymbolTable");
3806     }
3807     dw.dxfInt( 70, 1);
3808     dw.dxfString(  0, "STYLE");
3809     if (version==VER_2000) {
3810         dw.dxfHex(5, 0x11);
3811         }
3812     //styleHandleStd = dw.handle();
3813     //dw.dxfHex(330, 3);
3814     if (version==VER_2000) {
3815         dw.dxfString(100, "AcDbSymbolTableRecord");
3816         dw.dxfString(100, "AcDbTextStyleTableRecord");
3817     }
3818     dw.dxfString(  2, "Standard");
3819     dw.dxfInt( 70, 0);
3820     dw.dxfReal( 40, 0.0);
3821     dw.dxfReal( 41, 0.75);
3822     dw.dxfReal( 50, 0.0);
3823     dw.dxfInt( 71, 0);
3824     dw.dxfReal( 42, 2.5);
3825     dw.dxfString(  3, "txt");
3826     dw.dxfString(  4, "");
3827     dw.dxfString(  0, "ENDTAB");
3828 }
3829
3830
3831
3832 /**
3833  * Writes a view section. This section is needed in VER_R13.
3834  * Note that this method currently only writes a faked VIEW section
3835  * to make the file readable by Aut*cad.
3836  */
3837 void DL_Dxf::writeView(DL_WriterA& dw) {
3838     dw.dxfString(  0, "TABLE");
3839     dw.dxfString(  2, "VIEW");
3840     if (version==VER_2000) {
3841         dw.dxfHex(5, 6);
3842         }
3843     //dw.dxfHex(330, 0);
3844     if (version==VER_2000) {
3845         dw.dxfString(100, "AcDbSymbolTable");
3846     }
3847     dw.dxfInt( 70, 0);
3848     dw.dxfString(  0, "ENDTAB");
3849 }
3850
3851
3852
3853 /**
3854  * Writes a ucs section. This section is needed in VER_R13.
3855  * Note that this method currently only writes a faked UCS section
3856  * to make the file readable by Aut*cad.
3857  */
3858 void DL_Dxf::writeUcs(DL_WriterA& dw) {
3859     dw.dxfString(  0, "TABLE");
3860     dw.dxfString(  2, "UCS");
3861     if (version==VER_2000) {
3862         dw.dxfHex(5, 7);
3863         }
3864     //dw.dxfHex(330, 0);
3865     if (version==VER_2000) {
3866         dw.dxfString(100, "AcDbSymbolTable");
3867     }
3868     dw.dxfInt( 70, 0);
3869     dw.dxfString(  0, "ENDTAB");
3870 }
3871
3872
3873
3874 /**
3875  * Writes a dimstyle section. This section is needed in VER_R13.
3876  * Note that this method currently only writes a faked DIMSTYLE section
3877  * to make the file readable by Aut*cad.
3878  */
3879 void DL_Dxf::writeDimStyle(DL_WriterA& dw, 
3880                                         double dimasz, double dimexe, double dimexo,
3881                        double dimgap, double dimtxt) {
3882
3883     dw.dxfString(  0, "TABLE");
3884     dw.dxfString(  2, "DIMSTYLE");
3885     if (version==VER_2000) {
3886         dw.dxfHex(5, 0xA);
3887         dw.dxfString(100, "AcDbSymbolTable");
3888     }
3889     dw.dxfInt( 70, 1);
3890     if (version==VER_2000) {
3891         dw.dxfString(100, "AcDbDimStyleTable");
3892         dw.dxfInt( 71, 0);
3893     }
3894
3895
3896     dw.dxfString(  0, "DIMSTYLE");
3897     if (version==VER_2000) {
3898         dw.dxfHex(105, 0x27);
3899     }
3900     //dw.handle(105);
3901     //dw.dxfHex(330, 0xA);
3902     if (version==VER_2000) {
3903         dw.dxfString(100, "AcDbSymbolTableRecord");
3904         dw.dxfString(100, "AcDbDimStyleTableRecord");
3905     }
3906     dw.dxfString(  2, "Standard");
3907     if (version==VER_R12) {
3908         dw.dxfString(  3, "");
3909         dw.dxfString(  4, "");
3910         dw.dxfString(  5, "");
3911         dw.dxfString(  6, "");
3912         dw.dxfString(  7, "");
3913         dw.dxfReal( 40, 1.0);
3914     }
3915
3916     dw.dxfReal( 41, dimasz);
3917     dw.dxfReal( 42, dimexo);
3918     dw.dxfReal( 43, 3.75);
3919     dw.dxfReal( 44, dimexe);
3920     if (version==VER_R12) {
3921         dw.dxfReal( 45, 0.0);
3922         dw.dxfReal( 46, 0.0);
3923         dw.dxfReal( 47, 0.0);
3924         dw.dxfReal( 48, 0.0);
3925     }
3926     dw.dxfInt( 70, 0);
3927     if (version==VER_R12) {
3928         dw.dxfInt( 71, 0);
3929         dw.dxfInt( 72, 0);
3930     }
3931     dw.dxfInt( 73, 0);
3932     dw.dxfInt( 74, 0);
3933     if (version==VER_R12) {
3934         dw.dxfInt( 75, 0);
3935         dw.dxfInt( 76, 0);
3936     }
3937     dw.dxfInt( 77, 1);
3938     dw.dxfInt( 78, 8);
3939     dw.dxfReal(140, dimtxt);
3940     dw.dxfReal(141, 2.5);
3941     if (version==VER_R12) {
3942         dw.dxfReal(142, 0.0);
3943     }
3944     dw.dxfReal(143, 0.03937007874016);
3945     if (version==VER_R12) {
3946         dw.dxfReal(144, 1.0);
3947         dw.dxfReal(145, 0.0);
3948         dw.dxfReal(146, 1.0);
3949     }
3950     dw.dxfReal(147, dimgap);
3951     if (version==VER_R12) {
3952         dw.dxfInt(170, 0);
3953     }
3954     dw.dxfInt(171, 3);
3955     dw.dxfInt(172, 1);
3956     if (version==VER_R12) {
3957         dw.dxfInt(173, 0);
3958         dw.dxfInt(174, 0);
3959         dw.dxfInt(175, 0);
3960         dw.dxfInt(176, 0);
3961         dw.dxfInt(177, 0);
3962         dw.dxfInt(178, 0);
3963     }
3964     if (version==VER_2000) {
3965         dw.dxfInt(271, 2);
3966         dw.dxfInt(272, 2);
3967         dw.dxfInt(274, 3);
3968         dw.dxfInt(278, 44);
3969         dw.dxfInt(283, 0);
3970         dw.dxfInt(284, 8);
3971         //dw.dxfHex(340, styleHandleStd);
3972         dw.dxfHex(340, 0x11);
3973     }
3974     // * /
3975     dw.dxfString(  0, "ENDTAB");
3976 }
3977
3978
3979
3980 /**
3981  * Writes a blockrecord section. This section is needed in VER_R13.
3982  * Note that this method currently only writes a faked BLOCKRECORD section
3983  * to make the file readable by Aut*cad.
3984  */
3985 void DL_Dxf::writeBlockRecord(DL_WriterA& dw) {
3986     dw.dxfString(  0, "TABLE");
3987     dw.dxfString(  2, "BLOCK_RECORD");
3988     if (version==VER_2000) {
3989         dw.dxfHex(5, 1);
3990         }
3991     //dw.dxfHex(330, 0);
3992     if (version==VER_2000) {
3993         dw.dxfString(100, "AcDbSymbolTable");
3994     }
3995     dw.dxfInt( 70, 1);
3996
3997     dw.dxfString(  0, "BLOCK_RECORD");
3998     if (version==VER_2000) {
3999         dw.dxfHex(5, 0x1F);
4000         }
4001     //int msh = dw.handle();
4002     //dw.setModelSpaceHandle(msh);
4003     //dw.dxfHex(330, 1);
4004     if (version==VER_2000) {
4005         dw.dxfString(100, "AcDbSymbolTableRecord");
4006         dw.dxfString(100, "AcDbBlockTableRecord");
4007     }
4008     dw.dxfString(  2, "*Model_Space");
4009     dw.dxfHex(340, 0x22);
4010
4011     dw.dxfString(  0, "BLOCK_RECORD");
4012     if (version==VER_2000) {
4013         dw.dxfHex(5, 0x1B);
4014         }
4015     //int psh = dw.handle();
4016     //dw.setPaperSpaceHandle(psh);
4017     //dw.dxfHex(330, 1);
4018     if (version==VER_2000) {
4019         dw.dxfString(100, "AcDbSymbolTableRecord");
4020         dw.dxfString(100, "AcDbBlockTableRecord");
4021     }
4022     dw.dxfString(  2, "*Paper_Space");
4023     dw.dxfHex(340, 0x1E);
4024
4025     dw.dxfString(  0, "BLOCK_RECORD");
4026     if (version==VER_2000) {
4027         dw.dxfHex(5, 0x23);
4028         }
4029     //int ps0h = dw.handle();
4030     //dw.setPaperSpace0Handle(ps0h);
4031     //dw.dxfHex(330, 1);
4032     if (version==VER_2000) {
4033         dw.dxfString(100, "AcDbSymbolTableRecord");
4034         dw.dxfString(100, "AcDbBlockTableRecord");
4035     }
4036     dw.dxfString(  2, "*Paper_Space0");
4037     dw.dxfHex(340, 0x26);
4038
4039     //dw.dxfString(  0, "ENDTAB");
4040 }
4041
4042
4043
4044 /**
4045  * Writes a single block record with the given name.
4046  */
4047 void DL_Dxf::writeBlockRecord(DL_WriterA& dw, const string& name) {
4048     dw.dxfString(  0, "BLOCK_RECORD");
4049     if (version==VER_2000) {
4050         dw.handle();
4051         }
4052     //dw->dxfHex(330, 1);
4053     if (version==VER_2000) {
4054         dw.dxfString(100, "AcDbSymbolTableRecord");
4055         dw.dxfString(100, "AcDbBlockTableRecord");
4056     }
4057     dw.dxfString(  2, name);
4058     dw.dxfHex(340, 0);
4059 }
4060
4061
4062
4063 /**
4064  * Writes a objects section. This section is needed in VER_R13.
4065  * Note that this method currently only writes a faked OBJECTS section
4066  * to make the file readable by Aut*cad.
4067  */
4068 void DL_Dxf::writeObjects(DL_WriterA& dw) {
4069     //int dicId, dicId2, dicId3, dicId4, dicId5;
4070     //int dicId5;
4071
4072     dw.dxfString(  0, "SECTION");
4073     dw.dxfString(  2, "OBJECTS");
4074     dw.dxfString(  0, "DICTIONARY");
4075     dw.dxfHex(5, 0xC);                            // C
4076     //dw.dxfHex(330, 0);
4077     dw.dxfString(100, "AcDbDictionary");
4078     dw.dxfInt(280, 0);
4079     dw.dxfInt(281, 1);
4080     dw.dxfString(  3, "ACAD_GROUP");
4081     //dw.dxfHex(350, dw.getNextHandle());          // D
4082     dw.dxfHex(350, 0xD);          // D
4083     dw.dxfString(  3, "ACAD_LAYOUT");
4084     dw.dxfHex(350, 0x1A);
4085     //dw.dxfHex(350, dw.getNextHandle()+0);        // 1A
4086     dw.dxfString(  3, "ACAD_MLINESTYLE");
4087     dw.dxfHex(350, 0x17);
4088     //dw.dxfHex(350, dw.getNextHandle()+1);        // 17
4089     dw.dxfString(  3, "ACAD_PLOTSETTINGS");
4090     dw.dxfHex(350, 0x19);
4091     //dw.dxfHex(350, dw.getNextHandle()+2);        // 19
4092     dw.dxfString(  3, "ACAD_PLOTSTYLENAME");
4093     dw.dxfHex(350, 0xE);
4094     //dw.dxfHex(350, dw.getNextHandle()+3);        // E
4095     dw.dxfString(  3, "AcDbVariableDictionary");
4096     dw.dxfHex(350, dw.getNextHandle());        // 2C
4097     dw.dxfString(  0, "DICTIONARY");
4098     dw.dxfHex(5, 0xD);
4099     //dw.handle();                                    // D
4100     //dw.dxfHex(330, 0xC);
4101     dw.dxfString(100, "AcDbDictionary");
4102     dw.dxfInt(280, 0);
4103     dw.dxfInt(281, 1);
4104     dw.dxfString(  0, "ACDBDICTIONARYWDFLT");
4105     dw.dxfHex(5, 0xE);
4106     //dicId4 = dw.handle();                           // E
4107     //dw.dxfHex(330, 0xC);                       // C
4108     dw.dxfString(100, "AcDbDictionary");
4109     dw.dxfInt(281, 1);
4110     dw.dxfString(  3, "Normal");
4111     dw.dxfHex(350, 0xF);
4112     //dw.dxfHex(350, dw.getNextHandle()+5);        // F
4113     dw.dxfString(100, "AcDbDictionaryWithDefault");
4114     dw.dxfHex(340, 0xF);
4115     //dw.dxfHex(340, dw.getNextHandle()+5);        // F
4116     dw.dxfString(  0, "ACDBPLACEHOLDER");
4117     dw.dxfHex(5, 0xF);
4118     //dw.handle();                                    // F
4119     //dw.dxfHex(330, dicId4);                      // E
4120     dw.dxfString(  0, "DICTIONARY");
4121     //dicId3 = dw.handle();                           // 17
4122     dw.dxfHex(5, 0x17);
4123     //dw.dxfHex(330, 0xC);                       // C
4124     dw.dxfString(100, "AcDbDictionary");
4125     dw.dxfInt(280, 0);
4126     dw.dxfInt(281, 1);
4127     dw.dxfString(  3, "Standard");
4128     dw.dxfHex(350, 0x18);
4129     //dw.dxfHex(350, dw.getNextHandle()+5);        // 18
4130     dw.dxfString(  0, "MLINESTYLE");
4131     dw.dxfHex(5, 0x18);
4132     //dw.handle();                                    // 18
4133     //dw.dxfHex(330, dicId3);                      // 17
4134     dw.dxfString(100, "AcDbMlineStyle");
4135     dw.dxfString(  2, "STANDARD");
4136     dw.dxfInt( 70, 0);
4137     dw.dxfString(  3, "");
4138     dw.dxfInt( 62, 256);
4139     dw.dxfReal( 51, 90.0);
4140     dw.dxfReal( 52, 90.0);
4141     dw.dxfInt( 71, 2);
4142     dw.dxfReal( 49, 0.5);
4143     dw.dxfInt( 62, 256);
4144     dw.dxfString(  6, "BYLAYER");
4145     dw.dxfReal( 49, -0.5);
4146     dw.dxfInt( 62, 256);
4147     dw.dxfString(  6, "BYLAYER");
4148     dw.dxfString(  0, "DICTIONARY");
4149     dw.dxfHex(5, 0x19);
4150     //dw.handle();                           // 17
4151     //dw.dxfHex(330, 0xC);                       // C
4152     dw.dxfString(100, "AcDbDictionary");
4153     dw.dxfInt(280, 0);
4154     dw.dxfInt(281, 1);
4155     dw.dxfString(  0, "DICTIONARY");
4156     //dicId2 = dw.handle();                           // 1A
4157     dw.dxfHex(5, 0x1A);
4158     //dw.dxfHex(330, 0xC);
4159     dw.dxfString(100, "AcDbDictionary");
4160     dw.dxfInt(281, 1);
4161     dw.dxfString(  3, "Layout1");
4162     dw.dxfHex(350, 0x1E);
4163     //dw.dxfHex(350, dw.getNextHandle()+2);        // 1E
4164     dw.dxfString(  3, "Layout2");
4165     dw.dxfHex(350, 0x26);
4166     //dw.dxfHex(350, dw.getNextHandle()+4);        // 26
4167     dw.dxfString(  3, "Model");
4168     dw.dxfHex(350, 0x22);
4169     //dw.dxfHex(350, dw.getNextHandle()+5);        // 22
4170
4171     dw.dxfString(  0, "LAYOUT");
4172     dw.dxfHex(5, 0x1E);
4173     //dw.handle();                                    // 1E
4174     //dw.dxfHex(330, dicId2);                      // 1A
4175     dw.dxfString(100, "AcDbPlotSettings");
4176     dw.dxfString(  1, "");
4177     dw.dxfString(  2, "C:\\Program Files\\AutoCAD 2002\\plotters\\DWF ePlot (optimized for plotting).pc3");
4178     dw.dxfString(  4, "");
4179     dw.dxfString(  6, "");
4180     dw.dxfReal( 40, 0.0);
4181     dw.dxfReal( 41, 0.0);
4182     dw.dxfReal( 42, 0.0);
4183     dw.dxfReal( 43, 0.0);
4184     dw.dxfReal( 44, 0.0);
4185     dw.dxfReal( 45, 0.0);
4186     dw.dxfReal( 46, 0.0);
4187     dw.dxfReal( 47, 0.0);
4188     dw.dxfReal( 48, 0.0);
4189     dw.dxfReal( 49, 0.0);
4190     dw.dxfReal(140, 0.0);
4191     dw.dxfReal(141, 0.0);
4192     dw.dxfReal(142, 1.0);
4193     dw.dxfReal(143, 1.0);
4194     dw.dxfInt( 70, 688);
4195     dw.dxfInt( 72, 0);
4196     dw.dxfInt( 73, 0);
4197     dw.dxfInt( 74, 5);
4198     dw.dxfString(  7, "");
4199     dw.dxfInt( 75, 16);
4200     dw.dxfReal(147, 1.0);
4201     dw.dxfReal(148, 0.0);
4202     dw.dxfReal(149, 0.0);
4203     dw.dxfString(100, "AcDbLayout");
4204     dw.dxfString(  1, "Layout1");
4205     dw.dxfInt( 70, 1);
4206     dw.dxfInt( 71, 1);
4207     dw.dxfReal( 10, 0.0);
4208     dw.dxfReal( 20, 0.0);
4209     dw.dxfReal( 11, 420.0);
4210     dw.dxfReal( 21, 297.0);
4211     dw.dxfReal( 12, 0.0);
4212     dw.dxfReal( 22, 0.0);
4213     dw.dxfReal( 32, 0.0);
4214     dw.dxfReal( 14, 1.000000000000000E+20);
4215     dw.dxfReal( 24, 1.000000000000000E+20);
4216     dw.dxfReal( 34, 1.000000000000000E+20);
4217     dw.dxfReal( 15, -1.000000000000000E+20);
4218     dw.dxfReal( 25, -1.000000000000000E+20);
4219     dw.dxfReal( 35, -1.000000000000000E+20);
4220     dw.dxfReal(146, 0.0);
4221     dw.dxfReal( 13, 0.0);
4222     dw.dxfReal( 23, 0.0);
4223     dw.dxfReal( 33, 0.0);
4224     dw.dxfReal( 16, 1.0);
4225     dw.dxfReal( 26, 0.0);
4226     dw.dxfReal( 36, 0.0);
4227     dw.dxfReal( 17, 0.0);
4228     dw.dxfReal( 27, 1.0);
4229     dw.dxfReal( 37, 0.0);
4230     dw.dxfInt( 76, 0);
4231     //dw.dxfHex(330, dw.getPaperSpaceHandle());    // 1B
4232     dw.dxfHex(330, 0x1B);
4233     dw.dxfString(  0, "LAYOUT");
4234     dw.dxfHex(5, 0x22);
4235     //dw.handle();                                    // 22
4236     //dw.dxfHex(330, dicId2);                      // 1A
4237     dw.dxfString(100, "AcDbPlotSettings");
4238     dw.dxfString(  1, "");
4239     dw.dxfString(  2, "C:\\Program Files\\AutoCAD 2002\\plotters\\DWF ePlot (optimized for plotting).pc3");
4240     dw.dxfString(  4, "");
4241     dw.dxfString(  6, "");
4242     dw.dxfReal( 40, 0.0);
4243     dw.dxfReal( 41, 0.0);
4244     dw.dxfReal( 42, 0.0);
4245     dw.dxfReal( 43, 0.0);
4246     dw.dxfReal( 44, 0.0);
4247     dw.dxfReal( 45, 0.0);
4248     dw.dxfReal( 46, 0.0);
4249     dw.dxfReal( 47, 0.0);
4250     dw.dxfReal( 48, 0.0);
4251     dw.dxfReal( 49, 0.0);
4252     dw.dxfReal(140, 0.0);
4253     dw.dxfReal(141, 0.0);
4254     dw.dxfReal(142, 1.0);
4255     dw.dxfReal(143, 1.0);
4256     dw.dxfInt( 70, 1712);
4257     dw.dxfInt( 72, 0);
4258     dw.dxfInt( 73, 0);
4259     dw.dxfInt( 74, 0);
4260     dw.dxfString(  7, "");
4261     dw.dxfInt( 75, 0);
4262     dw.dxfReal(147, 1.0);
4263     dw.dxfReal(148, 0.0);
4264     dw.dxfReal(149, 0.0);
4265     dw.dxfString(100, "AcDbLayout");
4266     dw.dxfString(  1, "Model");
4267     dw.dxfInt( 70, 1);
4268     dw.dxfInt( 71, 0);
4269     dw.dxfReal( 10, 0.0);
4270     dw.dxfReal( 20, 0.0);
4271     dw.dxfReal( 11, 12.0);
4272     dw.dxfReal( 21, 9.0);
4273     dw.dxfReal( 12, 0.0);
4274     dw.dxfReal( 22, 0.0);
4275     dw.dxfReal( 32, 0.0);
4276     dw.dxfReal( 14, 0.0);
4277     dw.dxfReal( 24, 0.0);
4278     dw.dxfReal( 34, 0.0);
4279     dw.dxfReal( 15, 0.0);
4280     dw.dxfReal( 25, 0.0);
4281     dw.dxfReal( 35, 0.0);
4282     dw.dxfReal(146, 0.0);
4283     dw.dxfReal( 13, 0.0);
4284     dw.dxfReal( 23, 0.0);
4285     dw.dxfReal( 33, 0.0);
4286     dw.dxfReal( 16, 1.0);
4287     dw.dxfReal( 26, 0.0);
4288     dw.dxfReal( 36, 0.0);
4289     dw.dxfReal( 17, 0.0);
4290     dw.dxfReal( 27, 1.0);
4291     dw.dxfReal( 37, 0.0);
4292     dw.dxfInt( 76, 0);
4293     //dw.dxfHex(330, dw.getModelSpaceHandle());    // 1F
4294     dw.dxfHex(330, 0x1F);
4295     dw.dxfString(  0, "LAYOUT");
4296     //dw.handle();                                    // 26
4297     dw.dxfHex(5, 0x26);
4298     //dw.dxfHex(330, dicId2);                      // 1A
4299     dw.dxfString(100, "AcDbPlotSettings");
4300     dw.dxfString(  1, "");
4301     dw.dxfString(  2, "C:\\Program Files\\AutoCAD 2002\\plotters\\DWF ePlot (optimized for plotting).pc3");
4302     dw.dxfString(  4, "");
4303     dw.dxfString(  6, "");
4304     dw.dxfReal( 40, 0.0);
4305     dw.dxfReal( 41, 0.0);
4306     dw.dxfReal( 42, 0.0);
4307     dw.dxfReal( 43, 0.0);
4308     dw.dxfReal( 44, 0.0);
4309     dw.dxfReal( 45, 0.0);
4310     dw.dxfReal( 46, 0.0);
4311     dw.dxfReal( 47, 0.0);
4312     dw.dxfReal( 48, 0.0);
4313     dw.dxfReal( 49, 0.0);
4314     dw.dxfReal(140, 0.0);
4315     dw.dxfReal(141, 0.0);
4316     dw.dxfReal(142, 1.0);
4317     dw.dxfReal(143, 1.0);
4318     dw.dxfInt( 70, 688);
4319     dw.dxfInt( 72, 0);
4320     dw.dxfInt( 73, 0);
4321     dw.dxfInt( 74, 5);
4322     dw.dxfString(  7, "");
4323     dw.dxfInt( 75, 16);
4324     dw.dxfReal(147, 1.0);
4325     dw.dxfReal(148, 0.0);
4326     dw.dxfReal(149, 0.0);
4327     dw.dxfString(100, "AcDbLayout");
4328     dw.dxfString(  1, "Layout2");
4329     dw.dxfInt( 70, 1);
4330     dw.dxfInt( 71, 2);
4331     dw.dxfReal( 10, 0.0);
4332     dw.dxfReal( 20, 0.0);
4333     dw.dxfReal( 11, 12.0);
4334     dw.dxfReal( 21, 9.0);
4335     dw.dxfReal( 12, 0.0);
4336     dw.dxfReal( 22, 0.0);
4337     dw.dxfReal( 32, 0.0);
4338     dw.dxfReal( 14, 0.0);
4339     dw.dxfReal( 24, 0.0);
4340     dw.dxfReal( 34, 0.0);
4341     dw.dxfReal( 15, 0.0);
4342     dw.dxfReal( 25, 0.0);
4343     dw.dxfReal( 35, 0.0);
4344     dw.dxfReal(146, 0.0);
4345     dw.dxfReal( 13, 0.0);
4346     dw.dxfReal( 23, 0.0);
4347     dw.dxfReal( 33, 0.0);
4348     dw.dxfReal( 16, 1.0);
4349     dw.dxfReal( 26, 0.0);
4350     dw.dxfReal( 36, 0.0);
4351     dw.dxfReal( 17, 0.0);
4352     dw.dxfReal( 27, 1.0);
4353     dw.dxfReal( 37, 0.0);
4354     dw.dxfInt( 76, 0);
4355     //dw.dxfHex(330, dw.getPaperSpace0Handle());   // 23
4356     dw.dxfHex(330, 0x23);
4357     dw.dxfString(  0, "DICTIONARY");
4358     //dw.dxfHex(5, 0x2C);
4359     //dicId5 =
4360     dw.handle();                           // 2C
4361     //dw.dxfHex(330, 0xC);                       // C
4362     dw.dxfString(100, "AcDbDictionary");
4363     dw.dxfInt(281, 1);
4364     dw.dxfString(  3, "DIMASSOC");
4365     //dw.dxfHex(350, 0x2F);
4366     dw.dxfHex(350, dw.getNextHandle()+1);        // 2E
4367     dw.dxfString(  3, "HIDETEXT");
4368     //dw.dxfHex(350, 0x2E);
4369     dw.dxfHex(350, dw.getNextHandle());        // 2D
4370     dw.dxfString(  0, "DICTIONARYVAR");
4371     //dw.dxfHex(5, 0x2E);
4372     dw.handle();                                    // 2E
4373     //dw.dxfHex(330, dicId5);                      // 2C
4374     dw.dxfString(100, "DictionaryVariables");
4375     dw.dxfInt(280, 0);
4376     dw.dxfInt(  1, 2);
4377     dw.dxfString(  0, "DICTIONARYVAR");
4378     //dw.dxfHex(5, 0x2D);
4379     dw.handle();                                    // 2D
4380     //dw.dxfHex(330, dicId5);                      // 2C
4381     dw.dxfString(100, "DictionaryVariables");
4382     dw.dxfInt(280, 0);
4383     dw.dxfInt(  1, 1);
4384 }
4385
4386
4387 /**
4388  * Writes the end of the objects section. This section is needed in VER_R13.
4389  * Note that this method currently only writes a faked OBJECTS section
4390  * to make the file readable by Aut*cad.
4391  */
4392 void DL_Dxf::writeObjectsEnd(DL_WriterA& dw) {
4393     dw.dxfString(  0, "ENDSEC");
4394 }
4395
4396
4397
4398 /**
4399  * Checks if the given variable is known by the given DXF version.
4400  */
4401 bool DL_Dxf::checkVariable(const char* var, DL_Codes::version version) {
4402     if (version>=VER_2000) {
4403         return true;
4404     } else if (version==VER_R12) {
4405         // these are all the variables recognized by dxf r12:
4406         if (!strcmp(var, "$ACADVER")) {
4407             return true;
4408         }
4409         if (!strcmp(var, "$ACADVER")) {
4410             return true;
4411         }
4412         if (!strcmp(var, "$ANGBASE")) {
4413             return true;
4414         }
4415         if (!strcmp(var, "$ANGDIR")) {
4416             return true;
4417         }
4418         if (!strcmp(var, "$ATTDIA")) {
4419             return true;
4420         }
4421         if (!strcmp(var, "$ATTMODE")) {
4422             return true;
4423         }
4424         if (!strcmp(var, "$ATTREQ")) {
4425             return true;
4426         }
4427         if (!strcmp(var, "$AUNITS")) {
4428             return true;
4429         }
4430         if (!strcmp(var, "$AUPREC")) {
4431             return true;
4432         }
4433         if (!strcmp(var, "$AXISMODE")) {
4434             return true;
4435         }
4436         if (!strcmp(var, "$AXISUNIT")) {
4437             return true;
4438         }
4439         if (!strcmp(var, "$BLIPMODE")) {
4440             return true;
4441         }
4442         if (!strcmp(var, "$CECOLOR")) {
4443             return true;
4444         }
4445         if (!strcmp(var, "$CELTYPE")) {
4446             return true;
4447         }
4448         if (!strcmp(var, "$CHAMFERA")) {
4449             return true;
4450         }
4451         if (!strcmp(var, "$CHAMFERB")) {
4452             return true;
4453         }
4454         if (!strcmp(var, "$CLAYER")) {
4455             return true;
4456         }
4457         if (!strcmp(var, "$COORDS")) {
4458             return true;
4459         }
4460         if (!strcmp(var, "$DIMALT")) {
4461             return true;
4462         }
4463         if (!strcmp(var, "$DIMALTD")) {
4464             return true;
4465         }
4466         if (!strcmp(var, "$DIMALTF")) {
4467             return true;
4468         }
4469         if (!strcmp(var, "$DIMAPOST")) {
4470             return true;
4471         }
4472         if (!strcmp(var, "$DIMASO")) {
4473             return true;
4474         }
4475         if (!strcmp(var, "$DIMASZ")) {
4476             return true;
4477         }
4478         if (!strcmp(var, "$DIMBLK")) {
4479             return true;
4480         }
4481         if (!strcmp(var, "$DIMBLK1")) {
4482             return true;
4483         }
4484         if (!strcmp(var, "$DIMBLK2")) {
4485             return true;
4486         }
4487         if (!strcmp(var, "$DIMCEN")) {
4488             return true;
4489         }
4490         if (!strcmp(var, "$DIMCLRD")) {
4491             return true;
4492         }
4493         if (!strcmp(var, "$DIMCLRE")) {
4494             return true;
4495         }
4496         if (!strcmp(var, "$DIMCLRT")) {
4497             return true;
4498         }
4499         if (!strcmp(var, "$DIMDLE")) {
4500             return true;
4501         }
4502         if (!strcmp(var, "$DIMDLI")) {
4503             return true;
4504         }
4505         if (!strcmp(var, "$DIMEXE")) {
4506             return true;
4507         }
4508         if (!strcmp(var, "$DIMEXO")) {
4509             return true;
4510         }
4511         if (!strcmp(var, "$DIMGAP")) {
4512             return true;
4513         }
4514         if (!strcmp(var, "$DIMLFAC")) {
4515             return true;
4516         }
4517         if (!strcmp(var, "$DIMLIM")) {
4518             return true;
4519         }
4520         if (!strcmp(var, "$DIMPOST")) {
4521             return true;
4522         }
4523         if (!strcmp(var, "$DIMRND")) {
4524             return true;
4525         }
4526         if (!strcmp(var, "$DIMSAH")) {
4527             return true;
4528         }
4529         if (!strcmp(var, "$DIMSCALE")) {
4530             return true;
4531         }
4532         if (!strcmp(var, "$DIMSE1")) {
4533             return true;
4534         }
4535         if (!strcmp(var, "$DIMSE2")) {
4536             return true;
4537         }
4538         if (!strcmp(var, "$DIMSHO")) {
4539             return true;
4540         }
4541         if (!strcmp(var, "$DIMSOXD")) {
4542             return true;
4543         }
4544         if (!strcmp(var, "$DIMSTYLE")) {
4545             return true;
4546         }
4547         if (!strcmp(var, "$DIMTAD")) {
4548             return true;
4549         }
4550         if (!strcmp(var, "$DIMTFAC")) {
4551             return true;
4552         }
4553         if (!strcmp(var, "$DIMTIH")) {
4554             return true;
4555         }
4556         if (!strcmp(var, "$DIMTIX")) {
4557             return true;
4558         }
4559         if (!strcmp(var, "$DIMTM")) {
4560             return true;
4561         }
4562         if (!strcmp(var, "$DIMTOFL")) {
4563             return true;
4564         }
4565         if (!strcmp(var, "$DIMTOH")) {
4566             return true;
4567         }
4568         if (!strcmp(var, "$DIMTOL")) {
4569             return true;
4570         }
4571         if (!strcmp(var, "$DIMTP")) {
4572             return true;
4573         }
4574         if (!strcmp(var, "$DIMTSZ")) {
4575             return true;
4576         }
4577         if (!strcmp(var, "$DIMTVP")) {
4578             return true;
4579         }
4580         if (!strcmp(var, "$DIMTXT")) {
4581             return true;
4582         }
4583         if (!strcmp(var, "$DIMZIN")) {
4584             return true;
4585         }
4586         if (!strcmp(var, "$DWGCODEPAGE")) {
4587             return true;
4588         }
4589         if (!strcmp(var, "$DRAGMODE")) {
4590             return true;
4591         }
4592         if (!strcmp(var, "$ELEVATION")) {
4593             return true;
4594         }
4595         if (!strcmp(var, "$EXTMAX")) {
4596             return true;
4597         }
4598         if (!strcmp(var, "$EXTMIN")) {
4599             return true;
4600         }
4601         if (!strcmp(var, "$FILLETRAD")) {
4602             return true;
4603         }
4604         if (!strcmp(var, "$FILLMODE")) {
4605             return true;
4606         }
4607         if (!strcmp(var, "$HANDLING")) {
4608             return true;
4609         }
4610         if (!strcmp(var, "$HANDSEED")) {
4611             return true;
4612         }
4613         if (!strcmp(var, "$INSBASE")) {
4614             return true;
4615         }
4616         if (!strcmp(var, "$LIMCHECK")) {
4617             return true;
4618         }
4619         if (!strcmp(var, "$LIMMAX")) {
4620             return true;
4621         }
4622         if (!strcmp(var, "$LIMMIN")) {
4623             return true;
4624         }
4625         if (!strcmp(var, "$LTSCALE")) {
4626             return true;
4627         }
4628         if (!strcmp(var, "$LUNITS")) {
4629             return true;
4630         }
4631         if (!strcmp(var, "$LUPREC")) {
4632             return true;
4633         }
4634         if (!strcmp(var, "$MAXACTVP")) {
4635             return true;
4636         }
4637         if (!strcmp(var, "$MENU")) {
4638             return true;
4639         }
4640         if (!strcmp(var, "$MIRRTEXT")) {
4641             return true;
4642         }
4643         if (!strcmp(var, "$ORTHOMODE")) {
4644             return true;
4645         }
4646         if (!strcmp(var, "$OSMODE")) {
4647             return true;
4648         }
4649         if (!strcmp(var, "$PDMODE")) {
4650             return true;
4651         }
4652         if (!strcmp(var, "$PDSIZE")) {
4653             return true;
4654         }
4655         if (!strcmp(var, "$PELEVATION")) {
4656             return true;
4657         }
4658         if (!strcmp(var, "$PEXTMAX")) {
4659             return true;
4660         }
4661         if (!strcmp(var, "$PEXTMIN")) {
4662             return true;
4663         }
4664         if (!strcmp(var, "$PLIMCHECK")) {
4665             return true;
4666         }
4667         if (!strcmp(var, "$PLIMMAX")) {
4668             return true;
4669         }
4670         if (!strcmp(var, "$PLIMMIN")) {
4671             return true;
4672         }
4673         if (!strcmp(var, "$PLINEGEN")) {
4674             return true;
4675         }
4676         if (!strcmp(var, "$PLINEWID")) {
4677             return true;
4678         }
4679         if (!strcmp(var, "$PSLTSCALE")) {
4680             return true;
4681         }
4682         if (!strcmp(var, "$PUCSNAME")) {
4683             return true;
4684         }
4685         if (!strcmp(var, "$PUCSORG")) {
4686             return true;
4687         }
4688         if (!strcmp(var, "$PUCSXDIR")) {
4689             return true;
4690         }
4691         if (!strcmp(var, "$PUCSYDIR")) {
4692             return true;
4693         }
4694         if (!strcmp(var, "$QTEXTMODE")) {
4695             return true;
4696         }
4697         if (!strcmp(var, "$REGENMODE")) {
4698             return true;
4699         }
4700         if (!strcmp(var, "$SHADEDGE")) {
4701             return true;
4702         }
4703         if (!strcmp(var, "$SHADEDIF")) {
4704             return true;
4705         }
4706         if (!strcmp(var, "$SKETCHINC")) {
4707             return true;
4708         }
4709         if (!strcmp(var, "$SKPOLY")) {
4710             return true;
4711         }
4712         if (!strcmp(var, "$SPLFRAME")) {
4713             return true;
4714         }
4715         if (!strcmp(var, "$SPLINESEGS")) {
4716             return true;
4717         }
4718         if (!strcmp(var, "$SPLINETYPE")) {
4719             return true;
4720         }
4721         if (!strcmp(var, "$SURFTAB1")) {
4722             return true;
4723         }
4724         if (!strcmp(var, "$SURFTAB2")) {
4725             return true;
4726         }
4727         if (!strcmp(var, "$SURFTYPE")) {
4728             return true;
4729         }
4730         if (!strcmp(var, "$SURFU")) {
4731             return true;
4732         }
4733         if (!strcmp(var, "$SURFV")) {
4734             return true;
4735         }
4736         if (!strcmp(var, "$TDCREATE")) {
4737             return true;
4738         }
4739         if (!strcmp(var, "$TDINDWG")) {
4740             return true;
4741         }
4742         if (!strcmp(var, "$TDUPDATE")) {
4743             return true;
4744         }
4745         if (!strcmp(var, "$TDUSRTIMER")) {
4746             return true;
4747         }
4748         if (!strcmp(var, "$TEXTSIZE")) {
4749             return true;
4750         }
4751         if (!strcmp(var, "$TEXTSTYLE")) {
4752             return true;
4753         }
4754         if (!strcmp(var, "$THICKNESS")) {
4755             return true;
4756         }
4757         if (!strcmp(var, "$TILEMODE")) {
4758             return true;
4759         }
4760         if (!strcmp(var, "$TRACEWID")) {
4761             return true;
4762         }
4763         if (!strcmp(var, "$UCSNAME")) {
4764             return true;
4765         }
4766         if (!strcmp(var, "$UCSORG")) {
4767             return true;
4768         }
4769         if (!strcmp(var, "$UCSXDIR")) {
4770             return true;
4771         }
4772         if (!strcmp(var, "$UCSYDIR")) {
4773             return true;
4774         }
4775         if (!strcmp(var, "$UNITMODE")) {
4776             return true;
4777         }
4778         if (!strcmp(var, "$USERI1")) {
4779             return true;
4780         }
4781         if (!strcmp(var, "$USERR1")) {
4782             return true;
4783         }
4784         if (!strcmp(var, "$USRTIMER")) {
4785             return true;
4786         }
4787         if (!strcmp(var, "$VISRETAIN")) {
4788             return true;
4789         }
4790         if (!strcmp(var, "$WORLDVIEW")) {
4791             return true;
4792         }
4793         if (!strcmp(var, "$FASTZOOM")) {
4794             return true;
4795         }
4796         if (!strcmp(var, "$GRIDMODE")) {
4797             return true;
4798         }
4799         if (!strcmp(var, "$GRIDUNIT")) {
4800             return true;
4801         }
4802         if (!strcmp(var, "$SNAPANG")) {
4803             return true;
4804         }
4805         if (!strcmp(var, "$SNAPBASE")) {
4806             return true;
4807         }
4808         if (!strcmp(var, "$SNAPISOPAIR")) {
4809             return true;
4810         }
4811         if (!strcmp(var, "$SNAPMODE")) {
4812             return true;
4813         }
4814         if (!strcmp(var, "$SNAPSTYLE")) {
4815             return true;
4816         }
4817         if (!strcmp(var, "$SNAPUNIT")) {
4818             return true;
4819         }
4820         if (!strcmp(var, "$VIEWCTR")) {
4821             return true;
4822         }
4823         if (!strcmp(var, "$VIEWDIR")) {
4824             return true;
4825         }
4826         if (!strcmp(var, "$VIEWSIZE")) {
4827             return true;
4828         }
4829         return false;
4830     }
4831
4832     return false;
4833 }
4834
4835
4836
4837 /**
4838  * @returns the library version as int (4 bytes, each byte one version number).
4839  * e.g. if str = "2.0.2.0" getLibVersion returns 0x02000200
4840  */
4841 int DL_Dxf::getLibVersion(const char* str) {
4842     int d[4];
4843     int idx = 0;
4844     char v[4][5];
4845     int ret = 0;
4846
4847     for (unsigned int i=0; i<strlen(str) && idx<3; ++i) {
4848         if (str[i]=='.') {
4849             d[idx] = i;
4850             idx++;
4851         }
4852     }
4853
4854     if (idx==3) {
4855         d[3] = strlen(str);
4856
4857         strncpy(v[0], str, d[0]);
4858         v[0][d[0]] = '\0';
4859         //std::cout << "v[0]: " << atoi(v[0]) << "\n";
4860
4861         strncpy(v[1], &str[d[0]+1], d[1]-d[0]-1);
4862         v[1][d[1]-d[0]-1] = '\0';
4863         //std::cout << "v[1]: " << atoi(v[1]) << "\n";
4864
4865         strncpy(v[2], &str[d[1]+1], d[2]-d[1]-1);
4866         v[2][d[2]-d[1]-1] = '\0';
4867         //std::cout << "v[2]: " << atoi(v[2]) << "\n";
4868
4869         strncpy(v[3], &str[d[2]+1], d[3]-d[2]-1);
4870         v[3][d[3]-d[2]-1] = '\0';
4871         //std::cout << "v[3]: " << atoi(v[3]) << "\n";
4872
4873         ret = (atoi(v[0])<<(3*8)) +
4874               (atoi(v[1])<<(2*8)) +
4875               (atoi(v[2])<<(1*8)) +
4876               (atoi(v[3])<<(0*8));
4877
4878         return ret;
4879     } else {
4880         std::cerr << "DL_Dxf::getLibVersion: invalid version number: " << str << "\n";
4881         return 0;
4882     }
4883 }
4884
4885
4886
4887 /**
4888  * Some test routines.
4889  */
4890 void DL_Dxf::test() {
4891     char* buf1;
4892     char* buf2;
4893     char* buf3;
4894     char* buf4;
4895     char* buf5;
4896     char* buf6;
4897
4898     buf1 = new char[10];
4899     buf2 = new char[10];
4900     buf3 = new char[10];
4901     buf4 = new char[10];
4902     buf5 = new char[10];
4903     buf6 = new char[10];
4904
4905     strcpy(buf1, "  10\n");
4906     strcpy(buf2, "10");
4907     strcpy(buf3, "10\n");
4908     strcpy(buf4, "  10 \n");
4909     strcpy(buf5, "  10 \r");
4910     strcpy(buf6, "\t10 \n");
4911
4912     std::cout << "1 buf1: '" << buf1 << "'\n";
4913     stripWhiteSpace(&buf1);
4914     std::cout << "2 buf1: '" << buf1 << "'\n";
4915     //assert(!strcmp(buf1, "10"));
4916
4917     std::cout << "1 buf2: '" << buf2 << "'\n";
4918     stripWhiteSpace(&buf2);
4919     std::cout << "2 buf2: '" << buf2 << "'\n";
4920
4921     std::cout << "1 buf3: '" << buf3 << "'\n";
4922     stripWhiteSpace(&buf3);
4923     std::cout << "2 buf3: '" << buf3 << "'\n";
4924
4925     std::cout << "1 buf4: '" << buf4 << "'\n";
4926     stripWhiteSpace(&buf4);
4927     std::cout << "2 buf4: '" << buf4 << "'\n";
4928
4929     std::cout << "1 buf5: '" << buf5 << "'\n";
4930     stripWhiteSpace(&buf5);
4931     std::cout << "2 buf5: '" << buf5 << "'\n";
4932
4933     std::cout << "1 buf6: '" << buf6 << "'\n";
4934     stripWhiteSpace(&buf6);
4935     std::cout << "2 buf6: '" << buf6 << "'\n";
4936
4937 }
4938
4939