You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

750 lines
14 KiB

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