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