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.

449 lines
11 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, you may find one here:
  18. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  19. * or you may search the http://www.gnu.org website for the version 2 license,
  20. * or you may write to the Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  22. */
  23. #include <set>
  24. #include <map>
  25. #include <utility>
  26. #include <iterator>
  27. #include <cctype>
  28. #include <iostream>
  29. #include <algorithm>
  30. #include "vrml1_node.h"
  31. bool NAMEREGISTER::AddName( const std::string aName, WRL1NODE* aNode )
  32. {
  33. if( aName.empty() )
  34. return false;
  35. std::map< std::string, WRL1NODE* >::iterator ir = reg.find( aName );
  36. if( ir != reg.end() )
  37. reg.erase( ir );
  38. reg.insert( std::pair< std::string, WRL1NODE* >( aName, aNode ) );
  39. return true;
  40. }
  41. bool NAMEREGISTER::DelName( const std::string aName, WRL1NODE* aNode )
  42. {
  43. if( aName.empty() )
  44. return false;
  45. std::map< std::string, WRL1NODE* >::iterator ir = reg.find( aName );
  46. if( ir != reg.end() && ir->second == aNode )
  47. {
  48. reg.erase( ir );
  49. return true;
  50. }
  51. return false;
  52. }
  53. WRL1NODE* NAMEREGISTER::FindName( const std::string aName )
  54. {
  55. if( aName.empty() )
  56. return NULL;
  57. std::map< std::string, WRL1NODE* >::iterator ir = reg.find( aName );
  58. if( ir != reg.end() )
  59. return ir->second;
  60. return NULL;
  61. }
  62. typedef std::pair< std::string, WRL1NODES > NODEITEM;
  63. typedef std::map< std::string, WRL1NODES > NODEMAP;
  64. static NODEMAP nodenames;
  65. WRL1NODE::WRL1NODE( NAMEREGISTER* aDictionary )
  66. {
  67. m_sgNode = NULL;
  68. m_Parent = NULL;
  69. m_Type = WRL1_END;
  70. m_dictionary = aDictionary;
  71. if( nodenames.empty() )
  72. {
  73. nodenames.insert( NODEITEM( "AsciiText", WRL1_ASCIITEXT ) );
  74. nodenames.insert( NODEITEM( "Cone", WRL1_CONE ) );
  75. nodenames.insert( NODEITEM( "Coordinate3", WRL1_COORDINATE3 ) );
  76. nodenames.insert( NODEITEM( "Cube", WRL1_CUBE ) );
  77. nodenames.insert( NODEITEM( "Cylinder", WRL1_CYLINDER ) );
  78. nodenames.insert( NODEITEM( "DirectionalLight", WRL1_DIRECTIONALLIGHT ) );
  79. nodenames.insert( NODEITEM( "FontStyle", WRL1_FONTSTYLE ) );
  80. nodenames.insert( NODEITEM( "IndexedFaceSet", WRL1_INDEXEDFACESET ) );
  81. nodenames.insert( NODEITEM( "IndexedLineSet", WRL1_INDEXEDLINESET ) );
  82. nodenames.insert( NODEITEM( "Info", WRL1_INFO ) );
  83. nodenames.insert( NODEITEM( "LOD", WRL1_LOD ) );
  84. nodenames.insert( NODEITEM( "Material", WRL1_MATERIAL ) );
  85. nodenames.insert( NODEITEM( "MaterialBinding", WRL1_MATERIALBINDING ) );
  86. nodenames.insert( NODEITEM( "MatrixTransform", WRL1_MATRIXTRANSFORM ) );
  87. nodenames.insert( NODEITEM( "Normal", WRL1_NORMAL ) );
  88. nodenames.insert( NODEITEM( "NormalBinding", WRL1_NORMALBINDING ) );
  89. nodenames.insert( NODEITEM( "OrthographicCamera", WRL1_ORTHOCAMERA ) );
  90. nodenames.insert( NODEITEM( "PerspectiveCamera", WRL1_PERSPECTIVECAMERA ) );
  91. nodenames.insert( NODEITEM( "PointLight", WRL1_POINTLIGHT ) );
  92. nodenames.insert( NODEITEM( "PointSet", WRL1_POINTSET ) );
  93. nodenames.insert( NODEITEM( "Rotation", WRL1_ROTATION ) );
  94. nodenames.insert( NODEITEM( "Scale", WRL1_SCALE ) );
  95. nodenames.insert( NODEITEM( "Separator", WRL1_SEPARATOR ) );
  96. nodenames.insert( NODEITEM( "ShapeHints", WRL1_SHAPEHINTS ) );
  97. nodenames.insert( NODEITEM( "Sphere", WRL1_SPHERE ) );
  98. nodenames.insert( NODEITEM( "SpotLight", WRL1_SPOTLIGHT ) );
  99. nodenames.insert( NODEITEM( "Switch", WRL1_SWITCH ) );
  100. nodenames.insert( NODEITEM( "Texture2", WRL1_TEXTURE2 ) );
  101. nodenames.insert( NODEITEM( "Testure2Transform", WRL1_TEXTURE2TRANSFORM ) );
  102. nodenames.insert( NODEITEM( "TextureCoordinate2", WRL1_TEXTURECOORDINATE2 ) );
  103. nodenames.insert( NODEITEM( "Transform", WRL1_TRANSFORM ) );
  104. nodenames.insert( NODEITEM( "Translation", WRL1_TRANSLATION ) );
  105. nodenames.insert( NODEITEM( "WWWAnchor", WRL1_WWWANCHOR ) );
  106. nodenames.insert( NODEITEM( "WWWInline", WRL1_WWWINLINE ) );
  107. }
  108. return;
  109. }
  110. WRL1NODE::~WRL1NODE()
  111. {
  112. if( m_dictionary && !m_Name.empty() )
  113. m_dictionary->DelName( m_Name, this );
  114. if( m_Parent )
  115. m_Parent->unlinkChildNode( this );
  116. std::list< WRL1NODE* >::iterator sBP = m_BackPointers.begin();
  117. std::list< WRL1NODE* >::iterator eBP = m_BackPointers.end();
  118. while( sBP != eBP )
  119. {
  120. (*sBP)->unlinkRefNode( this );
  121. ++sBP;
  122. }
  123. m_Refs.clear();
  124. std::list< WRL1NODE* >::iterator sC = m_Children.begin();
  125. std::list< WRL1NODE* >::iterator eC = m_Children.end();
  126. while( sC != eC )
  127. {
  128. (*sC)->SetParent( NULL, false );
  129. delete *sC;
  130. ++sC;
  131. }
  132. m_Children.clear();
  133. return;
  134. }
  135. void WRL1NODE::addNodeRef( WRL1NODE* aNode )
  136. {
  137. // note: for VRML1 we allow even parent nodes to be held as references
  138. m_BackPointers.push_back( aNode );
  139. return;
  140. }
  141. void WRL1NODE::delNodeRef( WRL1NODE* aNode )
  142. {
  143. std::list< WRL1NODE* >::iterator np =
  144. std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode );
  145. if( np != m_BackPointers.end() )
  146. {
  147. m_BackPointers.erase( np );
  148. return;
  149. }
  150. #ifdef DEBUG_VRML1
  151. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  152. std::cerr << " * [BUG] delNodeRef() did not find its target\n";
  153. #endif
  154. return;
  155. }
  156. WRL1NODES WRL1NODE::GetNodeType( void ) const
  157. {
  158. return m_Type;
  159. }
  160. WRL1NODE* WRL1NODE::GetParent( void ) const
  161. {
  162. return m_Parent;
  163. }
  164. std::string WRL1NODE::GetName( void )
  165. {
  166. return m_Name;
  167. }
  168. bool WRL1NODE::SetName( const std::string& aName )
  169. {
  170. if( aName.empty() )
  171. return false;
  172. if( isdigit( aName[0] ) )
  173. {
  174. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
  175. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  176. std::cerr << " * [INFO] invalid node name '" << aName << "' (begins with digit)\n";
  177. #endif
  178. return false;
  179. }
  180. // The character '+' is not allowed in names as per the VRML1 specification;
  181. // however many parsers accept them and many bad generators use them so the rules
  182. // have been relaxed here.
  183. #define BAD_CHARS1 "\"\'#,.\\[]{}\x00\x01\x02\x03\x04\x05\x06\x09\x0A\x0B\x0C\x0D\x0E\x0F"
  184. #define BAD_CHARS2 "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
  185. if( std::string::npos != aName.find_first_of( BAD_CHARS1 )
  186. || std::string::npos != aName.find_first_of( BAD_CHARS2 ) )
  187. {
  188. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
  189. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  190. std::cerr << " * [INFO] invalid node name '" << aName;
  191. std::cerr<< "' (contains invalid character)\n";
  192. #endif
  193. return false;
  194. }
  195. m_Name = aName;
  196. if( m_dictionary )
  197. m_dictionary->AddName( aName, this );
  198. return true;
  199. }
  200. const char* WRL1NODE::GetNodeTypeName( WRL1NODES aNodeType ) const
  201. {
  202. if( aNodeType < WRL1_BASE || aNodeType >= WRL1_END )
  203. return "*INVALID_TYPE*";
  204. if( aNodeType == WRL1_BASE )
  205. return "*VIRTUAL_BASE*";
  206. NODEMAP::iterator it = nodenames.begin();
  207. advance( it, (aNodeType - WRL1_BEGIN) );
  208. return it->first.c_str();
  209. }
  210. WRL1STATUS* WRL1NODE::GetCurrentSettings( void )
  211. {
  212. return &m_current;
  213. }
  214. WRL1NODES WRL1NODE::getNodeTypeID( const std::string aNodeName )
  215. {
  216. NODEMAP::iterator it = nodenames.find( aNodeName );
  217. if( nodenames.end() != it )
  218. return it->second;
  219. return WRL1_INVALID;
  220. }
  221. std::string WRL1NODE::GetError( void )
  222. {
  223. return m_error;
  224. }
  225. WRL1NODE* WRL1NODE::FindNode( const std::string& aNodeName )
  226. {
  227. if( NULL == m_dictionary )
  228. return NULL;
  229. return m_dictionary->FindName( aNodeName );
  230. }
  231. bool WRL1NODE::SetParent( WRL1NODE* aParent, bool doUnlink )
  232. {
  233. if( aParent == m_Parent )
  234. return true;
  235. if( NULL != m_Parent && doUnlink )
  236. m_Parent->unlinkChildNode( this );
  237. m_Parent = aParent;
  238. if( NULL != m_Parent )
  239. m_Parent->AddChildNode( this );
  240. return true;
  241. }
  242. bool WRL1NODE::AddChildNode( WRL1NODE* aNode )
  243. {
  244. if( aNode->GetNodeType() == WRL1_BASE )
  245. {
  246. #ifdef DEBUG_VRML1
  247. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  248. std::cerr << " * [BUG] attempting to add a base node to another node\n";
  249. #endif
  250. return false;
  251. }
  252. std::list< WRL1NODE* >::iterator sC = m_Children.begin();
  253. std::list< WRL1NODE* >::iterator eC = m_Children.end();
  254. while( sC != eC )
  255. {
  256. if( *sC == aNode )
  257. return false;
  258. ++sC;
  259. }
  260. aNode->SetParent( this );
  261. m_Children.push_back( aNode );
  262. addItem( aNode );
  263. return true;
  264. }
  265. bool WRL1NODE::AddRefNode( WRL1NODE* aNode )
  266. {
  267. if( NULL == aNode )
  268. {
  269. #ifdef DEBUG_VRML1
  270. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  271. std::cerr << " * [BUG] NULL passed as node pointer\n";
  272. #endif
  273. return false;
  274. }
  275. if( aNode->GetNodeType() == WRL1_BASE )
  276. {
  277. #ifdef DEBUG_VRML1
  278. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  279. std::cerr << " * [BUG] attempting to add a base node ref to another base node\n";
  280. #endif
  281. return false;
  282. }
  283. // note: the VRML1 spec does not prevent the reuse of a node at
  284. // the same level; for example a Coordinate3 node can be recalled
  285. // at any time to set the current coordinate set.
  286. m_Refs.push_back( aNode );
  287. addItem( aNode );
  288. return true;
  289. }
  290. void WRL1NODE::unlinkChildNode( const WRL1NODE* aNode )
  291. {
  292. std::list< WRL1NODE* >::iterator sL = m_Children.begin();
  293. std::list< WRL1NODE* >::iterator eL = m_Children.end();
  294. while( sL != eL )
  295. {
  296. if( *sL == aNode )
  297. {
  298. m_Children.erase( sL );
  299. return;
  300. }
  301. ++sL;
  302. }
  303. delItem( aNode );
  304. return;
  305. }
  306. void WRL1NODE::unlinkRefNode( const WRL1NODE* aNode )
  307. {
  308. std::list< WRL1NODE* >::iterator sL = m_Refs.begin();
  309. std::list< WRL1NODE* >::iterator eL = m_Refs.end();
  310. while( sL != eL )
  311. {
  312. if( *sL == aNode )
  313. {
  314. m_Refs.erase( sL );
  315. return;
  316. }
  317. ++sL;
  318. }
  319. delItem( aNode );
  320. return;
  321. }
  322. void WRL1NODE::addItem( WRL1NODE* aNode )
  323. {
  324. m_Items.push_back( aNode );
  325. return;
  326. }
  327. void WRL1NODE::delItem( const WRL1NODE* aNode )
  328. {
  329. std::list< WRL1NODE* >::iterator sL = m_Items.begin();
  330. std::list< WRL1NODE* >::iterator eL = m_Items.end();
  331. while( sL != eL )
  332. {
  333. if( *sL == aNode )
  334. {
  335. m_Items.erase( sL );
  336. return;
  337. }
  338. ++sL;
  339. }
  340. return;
  341. }