1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (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, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <ctype.h>
24 #ifdef HAVE_STDLIB_H
25 #include <stdlib.h>
26 #endif
27
28 #include <math.h>
29
30 #include "libgeda_priv.h"
31
32 #ifdef HAVE_LIBDMALLOC
33 #include <dmalloc.h>
34 #endif
35
36 /*! \todo Finish function documentation!!!
37 * \brief
38 * \par Function Description
39 *
40 */
s_cue_postscript_fillbox(TOPLEVEL * toplevel,FILE * fp,int x,int y)41 void s_cue_postscript_fillbox(TOPLEVEL * toplevel, FILE * fp, int x,
42 int y)
43 {
44 int offset;
45 int offset2;
46
47 /* hard coded values */
48 offset = CUE_BOX_SIZE;
49 offset2 = offset*2;
50
51 f_print_set_color(toplevel, fp, NET_ENDPOINT_COLOR);
52
53 fprintf(fp, "%d %d %d %d fbox\n",
54 offset2, offset2, x-offset, y-offset);
55 }
56
57 /*! \todo Finish function documentation!!!
58 * \brief
59 * \par Function Description
60 *
61 */
s_cue_postscript_junction(TOPLEVEL * toplevel,FILE * fp,int x,int y,int bus_involved)62 void s_cue_postscript_junction (TOPLEVEL * toplevel, FILE * fp,
63 int x, int y, int bus_involved)
64 {
65 int offset2;
66
67 if (bus_involved) {
68 offset2 = JUNCTION_CUE_SIZE_BUS;
69 } else {
70 offset2 = JUNCTION_CUE_SIZE_NET;
71 }
72
73 f_print_set_color(toplevel, fp, JUNCTION_COLOR);
74
75 fprintf(fp, "newpath\n");
76 fprintf(fp, "%d %d\n", x, y);
77 fprintf(fp, "%d\n", offset2 / 2);
78 fprintf(fp, "0 360 arc\n");
79 fprintf(fp, "fill\n");
80 }
81
82 /*! \brief Draw an arrow at the end of a net.
83 */
84 void
s_cue_postscript_arrow(TOPLEVEL * toplevel,FILE * fp,int x,int y,int dx,int dy)85 s_cue_postscript_arrow (TOPLEVEL *toplevel, FILE *fp,
86 int x, int y, int dx, int dy)
87 {
88 int offset = CUE_BOX_SIZE;
89
90 f_print_set_color (toplevel, fp, JUNCTION_COLOR);
91
92 fprintf (fp, "gsave\n");
93
94 /* We compute a transformation so that the arrowhead is aligned with
95 * the net segment. */
96 double len = hypot (dx, dy);
97 if (len != 0) {
98 double c = dx / len;
99 double s = dy / len;
100 fprintf (fp, "[ %.2f %.2f %.2f %.2f %d %d ] concat\n", c, -s, s, c, x, y);
101 } else {
102 fprintf (fp, "%d %d translate\n", x, y); /* Translate to centre point of the arrow */
103 }
104
105 /* Now draw a simple arrowhead */
106 fprintf (fp, "newpath\n");
107 fprintf (fp, "%d %d moveto\n", -offset, -offset);
108 fprintf (fp, "%d %d lineto\n", -offset, offset);
109 fprintf (fp, "%d %d lineto\n", offset, 0);
110 fprintf (fp, "closepath\n"
111 "fill\n"
112 "grestore\n");
113 }
114
115 /*! \todo Finish function documentation!!!
116 * \brief
117 * \par Function Description
118 *
119 */
s_cue_output_all(TOPLEVEL * toplevel,const GList * obj_list,FILE * fp,int type)120 void s_cue_output_all (TOPLEVEL * toplevel, const GList *obj_list, FILE * fp,
121 int type)
122 {
123 OBJECT *o_current;
124 const GList *iter;
125
126 iter = obj_list;
127 while (iter != NULL) {
128 o_current = (OBJECT *)iter->data;
129 switch (o_current->type) {
130 case (OBJ_NET):
131 case (OBJ_BUS):
132 case (OBJ_PIN):
133 s_cue_output_single(toplevel, o_current, fp, type);
134 break;
135
136 case (OBJ_COMPLEX):
137 case (OBJ_PLACEHOLDER):
138 s_cue_output_all(toplevel, o_current->complex->prim_objs, fp,
139 type);
140 break;
141
142 }
143 iter = g_list_next (iter);
144 }
145 }
146
147 /*! \todo Finish function documentation!!!
148 * \brief
149 * \par Function Description
150 *
151 */
s_cue_output_lowlevel(TOPLEVEL * toplevel,OBJECT * object,int whichone,FILE * fp,int output_type)152 void s_cue_output_lowlevel(TOPLEVEL * toplevel, OBJECT * object, int whichone,
153 FILE * fp, int output_type)
154 {
155 int x, y;
156 GList *cl_current;
157 CONN *conn;
158 int type, count = 0;
159 int done = FALSE;
160 int bus_involved = FALSE;
161
162 x = object->line->x[whichone];
163 y = object->line->y[whichone];
164
165 type = CONN_ENDPOINT;
166
167 if (object->type == OBJ_BUS ||
168 (object->type == OBJ_PIN && object->pin_type == PIN_TYPE_BUS))
169 bus_involved = TRUE;
170
171 cl_current = object->conn_list;
172 while (cl_current != NULL && !done) {
173 conn = (CONN *) cl_current->data;
174
175 if (conn->x == x && conn->y == y) {
176
177 if (conn->other_object &&
178 (conn->other_object->type == OBJ_BUS ||
179 (conn->other_object->type == OBJ_PIN &&
180 conn->other_object->pin_type == PIN_TYPE_BUS)))
181 bus_involved=TRUE;
182
183 switch (conn->type) {
184
185 case (CONN_ENDPOINT):
186 count++;
187 break;
188
189 case (CONN_MIDPOINT):
190 type = CONN_MIDPOINT;
191 done = TRUE;
192 count = 0;
193 break;
194 }
195 }
196
197 cl_current = g_list_next(cl_current);
198 }
199
200 #if DEBUG
201 printf("type: %d count: %d\n", type, count);
202 #endif
203
204 switch (type) {
205
206 case (CONN_ENDPOINT):
207 if (object->type == OBJ_NET || object->type == OBJ_PIN) {
208 if (count < 1) { /* Didn't find anything connected there */
209 if ((object->type == OBJ_NET)
210 && o_net_is_fully_connected (toplevel, object)) {
211 /* Probably connected, so draw friendly arrowhead. The
212 * additional parameters are needed to allow the arrowhead
213 * to be pointed in the direction of the net. */
214 if (output_type == POSTSCRIPT) {
215 s_cue_postscript_arrow (toplevel, fp, x, y,
216 object->line->x[whichone] - object->line->x[!whichone],
217 object->line->y[whichone] - object->line->y[!whichone]);
218 }
219 } else {
220 s_cue_postscript_fillbox (toplevel, fp, x, y);
221 }
222 } else if (count >= 2) {
223 if (output_type == POSTSCRIPT)
224 s_cue_postscript_junction (toplevel, fp, x, y, bus_involved);
225 }
226 }
227 break;
228
229 case (CONN_MIDPOINT):
230 if (output_type == POSTSCRIPT)
231 s_cue_postscript_junction (toplevel, fp, x, y, bus_involved);
232 break;
233 }
234
235 }
236
237 /*! \todo Finish function documentation!!!
238 * \brief
239 * \par Function Description
240 *
241 */
s_cue_output_lowlevel_midpoints(TOPLEVEL * toplevel,OBJECT * object,FILE * fp,int output_type)242 void s_cue_output_lowlevel_midpoints(TOPLEVEL * toplevel, OBJECT * object,
243 FILE * fp, int output_type)
244 {
245 int x, y;
246 GList *cl_current;
247 CONN *conn;
248 int bus_involved = FALSE;
249
250 if (object->type == OBJ_BUS)
251 bus_involved = TRUE;
252
253 cl_current = object->conn_list;
254 while (cl_current != NULL) {
255 conn = (CONN *) cl_current->data;
256
257 switch (conn->type) {
258 case (CONN_MIDPOINT):
259
260 x = conn->x;
261 y = conn->y;
262
263 if (conn->other_object && conn->other_object->type == OBJ_BUS)
264 bus_involved = TRUE;
265
266 if (output_type == POSTSCRIPT) {
267 s_cue_postscript_junction (toplevel, fp, x, y, bus_involved);
268 }
269 break;
270 }
271
272
273 cl_current = g_list_next(cl_current);
274 }
275 }
276
277 /*! \brief Output cues for a single object
278 *
279 * \par Function Description
280 * Cues are drawn on pins, nets and buses.
281 * Two types of cues are drawn:
282 * - endpoint cues (identifying unconnected ends of objects)
283 * - junction cues (identifying net/pin/bus junctions)
284 *
285 * \param [in] toplevel The TOPLEVEL object
286 * \param [in] object The OBJECT to output cues for
287 * \param [in] fp The file handle to output to
288 * \param [in] type The type of output being produced
289 */
s_cue_output_single(TOPLEVEL * toplevel,OBJECT * object,FILE * fp,int type)290 void s_cue_output_single(TOPLEVEL * toplevel, OBJECT * object, FILE * fp,
291 int type)
292 {
293 g_return_if_fail (object != NULL);
294
295 switch (object->type) {
296 case (OBJ_NET):
297 s_cue_output_lowlevel(toplevel, object, 0, fp, type);
298 s_cue_output_lowlevel(toplevel, object, 1, fp, type);
299 break;
300 case (OBJ_BUS):
301 s_cue_output_lowlevel(toplevel, object, 0, fp, type);
302 s_cue_output_lowlevel(toplevel, object, 1, fp, type);
303 break;
304 case (OBJ_PIN):
305 s_cue_output_lowlevel(toplevel, object, object->whichend, fp, type);
306 break;
307 default:
308 return;
309 }
310 s_cue_output_lowlevel_midpoints(toplevel, object, fp, type);
311 }
312
313
314
315