1 /**********************************************************
2  * Version $Id: dl_writer.h 911 2011-02-14 16:38:15Z reklov_w $
3  *********************************************************/
4 /****************************************************************************
5 ** $Id: dl_writer.h 911 2011-02-14 16:38:15Z reklov_w $
6 **
7 ** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
8 ** Copyright (C) 2001 Robert J. Campbell Jr.
9 **
10 ** This file is part of the dxflib project.
11 **
12 ** This file may be distributed and/or modified under the terms of the
13 ** GNU General Public License version 2 as published by the Free Software
14 ** Foundation and appearing in the file LICENSE.GPL included in the
15 ** packaging of this file.
16 **
17 ** Licensees holding valid dxflib Professional Edition licenses may use
18 ** this file in accordance with the dxflib Commercial License
19 ** Agreement provided with the Software.
20 **
21 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
22 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 **
24 ** See http://www.ribbonsoft.com for further details.
25 **
26 ** Contact info@ribbonsoft.com if any conditions of this licensing are
27 ** not clear to you.
28 **
29 **********************************************************************/
30 
31 #ifndef DL_WRITER_H
32 #define DL_WRITER_H
33 
34 #if _MSC_VER > 1000
35 #pragma once
36 #endif // _MSC_VER > 1000
37 
38 #if defined(__OS2__)||defined(__EMX__)
39 #define strcasecmp(s,t) stricmp(s,t)
40 #endif
41 
42 #if defined(WIN32)
43 #define strcasecmp(s,t) _stricmp(s,t)
44 #endif
45 
46 #include <iostream>
47 
48 #include "dl_attributes.h"
49 #include "dl_codes.h"
50 
51 
52 
53 /**
54  * Defines interface for writing low level DXF constructs to
55  * a file. Implementation is defined in derived classes that write
56  * to binary or ASCII files.
57  *
58  * Implements functions that write higher level constructs in terms of
59  * the low level ones.
60  *
61  * @todo Add error checking for string/entry length.
62  */
63 class DL_Writer {
64 public:
65     /**
66      * @para version DXF version. Defaults to VER_2002.
67      */
DL_Writer(DL_Codes::version version)68     DL_Writer(DL_Codes::version version) : m_handle(0x30) {
69         this->version = version;
70         modelSpaceHandle = 0;
71         paperSpaceHandle = 0;
72         paperSpace0Handle = 0;
73     }
74 
~DL_Writer()75     virtual ~DL_Writer() {}
76     ;
77 
78     /** Generic section for section 'name'.
79      *
80      * <pre>
81      *   0
82      *  SECTION
83      *   2
84      *  name
85      * </pre>
86      */
section(const char * name)87     void section(const char* name) const {
88         dxfString(0, "SECTION");
89         dxfString(2, name);
90     }
91 
92     /**
93      * Section HEADER
94      *
95      * <pre>
96      *   0
97      *  SECTION
98      *   2
99      *  HEADER
100      * </pre>
101      */
sectionHeader()102     void sectionHeader() const {
103         section("HEADER");
104     }
105 
106     /**
107      * Section TABLES
108      *
109      * <pre>
110      *   0
111      *  SECTION
112      *   2
113      *  TABLES
114      * </pre>
115      */
sectionTables()116     void sectionTables() const {
117         section("TABLES");
118     }
119 
120     /**
121      * Section BLOCKS
122      *
123      * <pre>
124      *   0
125      *  SECTION
126      *   2
127      *  BLOCKS
128      * </pre>
129      */
sectionBlocks()130     void sectionBlocks() const {
131         section("BLOCKS");
132     }
133 
134     /**
135      * Section ENTITIES
136      *
137      * <pre>
138      *   0
139      *  SECTION
140      *   2
141      *  ENTITIES
142      * </pre>
143      */
sectionEntities()144     void sectionEntities() const {
145         section("ENTITIES");
146     }
147 
148     /**
149      * Section CLASSES
150      *
151      * <pre>
152      *   0
153      *  SECTION
154      *   2
155      *  CLASSES
156      * </pre>
157      */
sectionClasses()158     void sectionClasses() const {
159         section("CLASSES");
160     }
161 
162     /**
163      * Section OBJECTS
164      *
165      * <pre>
166      *   0
167      *  SECTION
168      *   2
169      *  OBJECTS
170      * </pre>
171      */
sectionObjects()172     void sectionObjects() const {
173         section("OBJECTS");
174     }
175 
176     /**
177      * End of a section.
178      *
179      * <pre>
180      *   0
181      *  ENDSEC
182      * </pre>
183      */
sectionEnd()184     void sectionEnd() const {
185         dxfString(0, "ENDSEC");
186     }
187 
188     /**
189      * Generic table for table 'name' with 'num' entries:
190      *
191      * <pre>
192      *   0
193      *  TABLE
194      *   2
195      *  name
196      *  70
197      *   num
198      * </pre>
199      */
table(const char * name,int num,int handle)200     void table(const char* name, int num, int handle) const {
201         dxfString(0, "TABLE");
202         dxfString(2, name);
203         if (version>=VER_2000) {
204             dxfHex(5, handle);
205             dxfString(100, "AcDbSymbolTable");
206         }
207         dxfInt(70, num);
208     }
209 
210     /** Table for layers.
211      *
212      * @param num Number of layers in total.
213      *
214      * <pre>
215      *   0
216      *  TABLE
217      *   2
218      *  LAYER
219      *   70
220      *      num
221      * </pre>
222      */
tableLayers(int num)223     void tableLayers(int num) const {
224         table("LAYER", num, 2);
225     }
226 
227     /** Table for line types.
228      *
229      * @param num Number of line types in total.
230      *
231      * <pre>
232      *   0
233      *  TABLE
234      *   2
235      *  LTYPE
236      *   70
237      *      num
238      * </pre>
239      */
tableLineTypes(int num)240     void tableLineTypes(int num) const {
241         //lineTypeHandle = 5;
242         table("LTYPE", num, 5);
243     }
244 
245     /** Table for application id.
246      *
247      * @param num Number of registered applications in total.
248      *
249      * <pre>
250      *   0
251      *  TABLE
252      *   2
253      *  APPID
254      *   70
255      *      num
256      * </pre>
257      */
tableAppid(int num)258     void tableAppid(int num) const {
259         table("APPID", num, 9);
260     }
261 
262     /**
263      * End of a table.
264      *
265      * <pre>
266      *   0
267      *  ENDTAB
268      * </pre>
269      */
tableEnd()270     void tableEnd() const {
271         dxfString(0, "ENDTAB");
272     }
273 
274     /**
275      * End of the DXF file.
276      *
277      * <pre>
278      *   0
279      *  EOF
280      * </pre>
281      */
dxfEOF()282     void dxfEOF() const {
283         dxfString(0, "EOF");
284     }
285 
286     /**
287      * Comment.
288      *
289      * <pre>
290      *  999
291      *  text
292      * </pre>
293      */
comment(const char * text)294     void comment(const char* text) const {
295         dxfString(999, text);
296     }
297 
298     /**
299      * Entity.
300      *
301      * <pre>
302      *   0
303      *  entTypeName
304      * </pre>
305 	 *
306 	 * @return Unique handle or 0.
307      */
entity(const char * entTypeName)308     void entity(const char* entTypeName) const {
309         dxfString(0, entTypeName);
310         if (version>=VER_2000) {
311             handle();
312         }
313     }
314 
315     /**
316      * Attributes of an entity.
317      *
318      * <pre>
319      *   8
320      *  layer
321      *  62
322      *  color
323      *  39
324      *  width
325      *   6
326      *  linetype
327      * </pre>
328      */
entityAttributes(const DL_Attributes & attrib)329     void entityAttributes(const DL_Attributes& attrib) const {
330 
331 		// layer name:
332         dxfString(8, attrib.getLayer());
333 
334 		// R12 doesn't accept BYLAYER values. The value has to be missing
335 		//   in that case.
336         if (version>=VER_2000 ||
337 			attrib.getColor()!=256) {
338         	dxfInt(62, attrib.getColor());
339 		}
340         if (version>=VER_2000) {
341             dxfInt(370, attrib.getWidth());
342         }
343         if (version>=VER_2000 ||
344 			strcasecmp(attrib.getLineType().c_str(), "BYLAYER")) {
345 	        dxfString(6, attrib.getLineType());
346 		}
347     }
348 
349     /**
350      * Subclass.
351      */
subClass(const char * sub)352     void subClass(const char* sub) const {
353         dxfString(100, sub);
354     }
355 
356     /**
357      * Layer (must be in the TABLES section LAYER).
358      *
359      * <pre>
360      *   0
361      *  LAYER
362      * </pre>
363      */
364     void tableLayerEntry(unsigned long int h=0)  const {
365         dxfString(0, "LAYER");
366         if (version>=VER_2000) {
367             if (h==0) {
368                 handle();
369             } else {
370                 dxfHex(5, h);
371             }
372             dxfString(100, "AcDbSymbolTableRecord");
373             dxfString(100, "AcDbLayerTableRecord");
374         }
375     }
376 
377     /**
378      * Line type (must be in the TABLES section LTYPE).
379      *
380      * <pre>
381      *   0
382      *  LTYPE
383      * </pre>
384      */
385     void tableLineTypeEntry(unsigned long int h=0)  const {
386         dxfString(0, "LTYPE");
387         if (version>=VER_2000) {
388             if (h==0) {
389                 handle();
390             } else {
391                 dxfHex(5, h);
392             }
393             //dxfHex(330, 0x5);
394             dxfString(100, "AcDbSymbolTableRecord");
395             dxfString(100, "AcDbLinetypeTableRecord");
396         }
397     }
398 
399     /**
400      * Appid (must be in the TABLES section APPID).
401      *
402      * <pre>
403      *   0
404      *  APPID
405      * </pre>
406      */
407     void tableAppidEntry(unsigned long int h=0)  const {
408         dxfString(0, "APPID");
409         if (version>=VER_2000) {
410             if (h==0) {
411                 handle();
412             } else {
413                 dxfHex(5, h);
414             }
415             //dxfHex(330, 0x9);
416             dxfString(100, "AcDbSymbolTableRecord");
417             dxfString(100, "AcDbRegAppTableRecord");
418         }
419     }
420 
421     /**
422      * Block (must be in the section BLOCKS).
423      *
424      * <pre>
425      *   0
426      *  BLOCK
427      * </pre>
428      */
429     void sectionBlockEntry(unsigned long int h=0)  const {
430         dxfString(0, "BLOCK");
431         if (version>=VER_2000) {
432             if (h==0) {
433                 handle();
434             } else {
435                 dxfHex(5, h);
436             }
437             //dxfHex(330, blockHandle);
438             dxfString(100, "AcDbEntity");
439             if (h==0x1C) {
440                 dxfInt(67, 1);
441             }
442             dxfString(8, "0");                 // TODO: Layer for block
443             dxfString(100, "AcDbBlockBegin");
444         }
445     }
446 
447     /**
448      * End of Block (must be in the section BLOCKS).
449      *
450      * <pre>
451      *   0
452      *  ENDBLK
453      * </pre>
454      */
455     void sectionBlockEntryEnd(unsigned long int h=0)  const {
456         dxfString(0, "ENDBLK");
457         if (version>=VER_2000) {
458             if (h==0) {
459                 handle();
460             } else {
461                 dxfHex(5, h);
462             }
463             //dxfHex(330, blockHandle);
464             dxfString(100, "AcDbEntity");
465             if (h==0x1D) {
466                 dxfInt(67, 1);
467             }
468             dxfString(8, "0");                 // TODO: Layer for block
469             dxfString(100, "AcDbBlockEnd");
470         }
471     }
472 
473     void color(int col=256) const {
474         dxfInt(62, col);
475     }
lineType(const char * lt)476     void lineType(const char *lt) const {
477         dxfString(6, lt);
478     }
lineTypeScale(double scale)479     void lineTypeScale(double scale) const {
480         dxfReal(48, scale);
481     }
lineWeight(int lw)482     void lineWeight(int lw) const {
483         dxfInt(370, lw);
484     }
485 
486     void coord(int gc, double x, double y, double z=0) const {
487         dxfReal(gc, x);
488         dxfReal(gc+10, y);
489         dxfReal(gc+20, z);
490     }
491 
coordTriplet(int gc,const double * value)492     void coordTriplet(int gc, const double* value) const {
493         if (value) {
494             dxfReal(gc, *value++);
495             dxfReal(gc+10, *value++);
496             dxfReal(gc+20, *value++);
497         }
498     }
499 
resetHandle()500     void resetHandle() const {
501         m_handle = 1;
502     }
503 
504     /**
505      * Writes a unique handle and returns it.
506      */
507     unsigned long handle(int gc=5) const {
508         // handle has to be hex
509         dxfHex(gc, m_handle);
510         return m_handle++;
511     }
512 
513     /**
514      * @return Next handle that will be written.
515      */
getNextHandle()516     unsigned long getNextHandle() const {
517         return m_handle;
518     }
519 
520     /**
521      * Increases handle, so that the handle returned remains available.
522      */
incHandle()523     unsigned long incHandle() const {
524         return m_handle++;
525     }
526 
527     /**
528      * Sets the handle of the model space. Entities refer to
529      * this handle.
530      */
setModelSpaceHandle(unsigned long h)531     void setModelSpaceHandle(unsigned long h) {
532         modelSpaceHandle = h;
533     }
534 
getModelSpaceHandle()535     unsigned long getModelSpaceHandle() {
536         return modelSpaceHandle;
537     }
538 
539     /**
540      * Sets the handle of the paper space. Some special blocks refer to
541      * this handle.
542      */
setPaperSpaceHandle(unsigned long h)543     void setPaperSpaceHandle(unsigned long h) {
544         paperSpaceHandle = h;
545     }
546 
getPaperSpaceHandle()547     unsigned long getPaperSpaceHandle() {
548         return paperSpaceHandle;
549     }
550 
551     /**
552      * Sets the handle of the paper space 0. Some special blocks refer to
553      * this handle.
554      */
setPaperSpace0Handle(unsigned long h)555     void setPaperSpace0Handle(unsigned long h) {
556         paperSpace0Handle = h;
557     }
558 
getPaperSpace0Handle()559     unsigned long getPaperSpace0Handle() {
560         return paperSpace0Handle;
561     }
562 
563     /**
564      * Must be overwritten by the implementing class to write a
565      * real value to the file.
566      *
567      * @param gc Group code.
568      * @param value The real value.
569      */
570     virtual void dxfReal(int gc, double value) const = 0;
571 
572     /**
573      * Must be overwritten by the implementing class to write an
574      * int value to the file.
575      *
576      * @param gc Group code.
577      * @param value The int value.
578      */
579     virtual void dxfInt(int gc, int value) const = 0;
580 
581     /**
582      * Must be overwritten by the implementing class to write an
583      * int value (hex) to the file.
584      *
585      * @param gc Group code.
586      * @param value The int value.
587      */
588     virtual void dxfHex(int gc, int value) const = 0;
589 
590     /**
591      * Must be overwritten by the implementing class to write a
592      * string to the file.
593      *
594      * @param gc Group code.
595      * @param value The string.
596      */
597     virtual void dxfString(int gc, const char* value) const = 0;
598 
599     /**
600      * Must be overwritten by the implementing class to write a
601      * string to the file.
602      *
603      * @param gc Group code.
604      * @param value The string.
605      */
606     virtual void dxfString(int gc, const string& value) const = 0;
607 
608 protected:
609     mutable unsigned long m_handle;
610     mutable unsigned long modelSpaceHandle;
611     mutable unsigned long paperSpaceHandle;
612     mutable unsigned long paperSpace0Handle;
613 
614     /**
615      * DXF version to be created.
616      */
617     DL_Codes::version version;
618 private:
619 };
620 
621 #endif
622