1 /* Copyright (C) 2007 Claus-Justus Heine
2  *
3  * This file is part of Geomview.
4  *
5  * Geomview is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published
7  * by the Free Software Foundation; either version 2, or (at your option)
8  * any later version.
9  *
10  * Geomview is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with Geomview; see the file COPYING.  If not, write
17  * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
18  * USA, or visit http://www.gnu.org.
19  */
20 #ifndef _GV_NODEDATA_H_
21 #define _GV_NODEDATA_H_
22 
23 #include "geomclass.h"
24 #include "mg.h"
25 
26 /* A geometry hierarchy may refer aribitrarily often to the same
27  * Geometry object via "Handle" references. In some cases, however, we
28  * need data which is attached to a node in the hierarchy tree. For
29  * the time being the only case is the "tagged apperance" handle used
30  * to refer to appearances out of BSPTree nodes.
31  *
32  * "path" is a unique tag and is computed during hierarchy
33  * traversal. 'L' stands for a list element, 'I' for Inst.
34  *
35  * L -> (L) -> nil
36  * |     |
37  * G1    I
38  *       |
39  *       G2
40  *
41  * The leaf-nodes of the hierarchy will have the paths "L" and
42  * "LI". This should be a unique id for earch hierarchy node, because
43  * it records the history of the path through the hierarchy to the
44  * node. Only the head of a list is included in the path, so the
45  * second id is "LI" and not "LLI" in the example above.
46  */
47 typedef struct NodeData {
48   DblListNode   node;       /* Link into Geom->pernode */
49   char          *ppath;     /* The path to this geom in the hierarchy (copy).*/
50   const void    *tagged_ap; /* tagged appearance pointer */
51   const BSPTree *node_tree; /* BSP-tree we belong to, if any */
52 } NodeData;
53 
54 #define GeomMakePath(geom, c, path, pathlen)		\
55   int pathlen = (geom)->ppathlen+1;			\
56   char *path = alloca(pathlen+1);			\
57   							\
58   memcpy(path, (geom)->ppath, (geom)->ppathlen);	\
59   path[pathlen-1] = c;					\
60   path[pathlen] = '\0'
61 
62 /* Transfer one Geom's per-node data to another Geom. Priamrily meant
63  * as hack during ND-drawing
64  */
GeomNodeDataMove(Geom * from,Geom * to)65 static inline void GeomNodeDataMove(Geom *from, Geom *to)
66 {
67   DblListMove(&from->pernode, &to->pernode);
68   to->ppath = from->ppath;
69   to->ppathlen = from->ppathlen;
70 }
71 
GeomNodeDataByPath(Geom * geom,const char * ppath)72 static inline NodeData *GeomNodeDataByPath(Geom *geom, const char *ppath)
73 {
74   NodeData *pos;
75 
76   if (!ppath) {
77     ppath = geom->ppath ? geom->ppath : "";
78   }
79   DblListIterateNoDelete(&geom->pernode, NodeData, node, pos) {
80     if (strcmp(pos->ppath, ppath) == 0) {
81       return pos;
82     }
83   }
84 
85   return NULL;
86 }
87 
88 extern DEF_FREELIST(NodeData);
89 
GeomNodeDataCreate(Geom * geom,const char * ppath)90 static inline NodeData *GeomNodeDataCreate(Geom *geom, const char *ppath)
91 {
92   NodeData *data;
93 
94   if (!ppath) {
95     ppath = geom->ppath ? geom->ppath : "";
96   }
97   data = GeomNodeDataByPath(geom, ppath);
98   if (data == NULL) {
99     FREELIST_NEW(NodeData, data);
100     data->ppath = strdup(ppath);
101     data->tagged_ap = NULL;
102     data->node_tree = NULL;
103     DblListAdd(&geom->pernode, &data->node);
104   }
105 
106   return data;
107 }
108 
GeomNodeDataPrune(Geom * geom)109 static inline void GeomNodeDataPrune(Geom *geom)
110 {
111   NodeData *data, *data_next;
112 
113   DblListIterate(&geom->pernode, NodeData, node, data, data_next) {
114     DblListDelete(&data->node);
115     if (data->tagged_ap) {
116       mguntagappearance(data->tagged_ap);
117     }
118     if (data->node_tree) {
119       BSPTreeFreeTree(data->node_tree);
120     }
121     if (data->ppath) {
122 	free(data->ppath);
123 	data->ppath = NULL;
124     }
125     FREELIST_FREE(NodeData, data);
126   }
127 }
128 
NodeDataFreeListPrune(void)129 static inline void NodeDataFreeListPrune(void)
130 {
131   FreeListNode *old;
132   size_t size = 0;
133 
134   while (NodeDataFreeList) {
135     old = NodeDataFreeList;
136     NodeDataFreeList = old->next;
137     OOGLFree(old);
138     size += sizeof(NodeData);
139   }
140   OOGLWarn("Freed %ld bytes.\n", size);
141 }
142 
143 #endif
144