1 /*
2 * Author: William Chia-Wei Cheng (bill.cheng@acm.org)
3 *
4 * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5 *
6 * This file may be distributed under the terms of the Q Public License
7 * as defined by Trolltech AS of Norway and appearing in the file
8 * LICENSE.QPL included in the packaging of this file.
9 *
10 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/obj.c,v 1.16 2011/05/16 16:21:58 william Exp $
19 */
20
21 #define _INCLUDE_FROM_OBJ_C_
22
23 #include "tgifdefs.h"
24
25 #include "arc.e"
26 #include "attr.e"
27 #include "auxtext.e"
28 #include "box.e"
29 #include "cmd.e"
30 #include "cursor.e"
31 #include "group.e"
32 #include "msg.e"
33 #include "obj.e"
34 #include "oval.e"
35 #include "page.e"
36 #include "pin.e"
37 #include "poly.e"
38 #include "polygon.e"
39 #include "rcbox.e"
40 #include "rect.e"
41 #include "setup.e"
42 #include "spline.e"
43 #include "stretch.e"
44 #include "text.e"
45 #include "xbitmap.e"
46 #include "xpixmap.e"
47
48 struct ObjRec *topObj=NULL, *botObj=NULL;
49
AddObj(PrevPtr,NextPtr,ObjPtr)50 void AddObj(PrevPtr, NextPtr, ObjPtr)
51 struct ObjRec *PrevPtr, *NextPtr, *ObjPtr;
52 /* add ObjPtr between PrevPtr and NextPtr */
53 {
54 ObjPtr->prev = PrevPtr;
55 ObjPtr->next = NextPtr;
56
57 if (PrevPtr == NULL) {
58 curPage->top = topObj = ObjPtr;
59 } else {
60 PrevPtr->next = ObjPtr;
61 }
62 if (NextPtr == NULL) {
63 curPage->bot = botObj = ObjPtr;
64 } else {
65 NextPtr->prev = ObjPtr;
66 }
67 }
68
UnlinkObj(ObjPtr)69 void UnlinkObj(ObjPtr)
70 struct ObjRec *ObjPtr;
71 {
72 if (topObj == ObjPtr) {
73 curPage->top = topObj = ObjPtr->next;
74 } else {
75 ObjPtr->prev->next = ObjPtr->next;
76 }
77 if (botObj == ObjPtr) {
78 curPage->bot = botObj = ObjPtr->prev;
79 } else {
80 ObjPtr->next->prev = ObjPtr->prev;
81 }
82 }
83
ReplaceObj(old_obj,new_obj)84 void ReplaceObj(old_obj, new_obj)
85 struct ObjRec *old_obj, *new_obj;
86 {
87 if (topObj == old_obj) {
88 curPage->top = topObj = new_obj;
89 new_obj->prev = NULL;
90 } else {
91 old_obj->prev->next = new_obj;
92 new_obj->prev = old_obj->prev;
93 }
94 if (botObj == old_obj) {
95 curPage->bot = botObj = new_obj;
96 new_obj->next = NULL;
97 } else {
98 old_obj->next->prev = new_obj;
99 new_obj->next = old_obj->next;
100 }
101 }
102
FreeObj(ObjPtr)103 void FreeObj(ObjPtr)
104 register struct ObjRec *ObjPtr;
105 {
106 if (ObjPtr == NULL) return;
107
108 if (ObjPtr->ctm != NULL) {
109 free(ObjPtr->ctm);
110 ObjPtr->ctm = NULL;
111 }
112 if (ObjPtr->creator_full_id != NULL) {
113 free(ObjPtr->creator_full_id);
114 ObjPtr->creator_full_id = NULL;
115 }
116 switch (ObjPtr->type) {
117 case OBJ_POLY: DelAllAttrs(ObjPtr->fattr); FreePolyObj(ObjPtr); break;
118 case OBJ_BOX: DelAllAttrs(ObjPtr->fattr); FreeBoxObj(ObjPtr); break;
119 case OBJ_OVAL: DelAllAttrs(ObjPtr->fattr); FreeOvalObj(ObjPtr); break;
120 case OBJ_TEXT: FreeTextObj(ObjPtr); break;
121 case OBJ_POLYGON: DelAllAttrs(ObjPtr->fattr); FreePolygonObj(ObjPtr); break;
122 case OBJ_ARC: DelAllAttrs(ObjPtr->fattr); FreeArcObj(ObjPtr); break;
123 case OBJ_RCBOX: DelAllAttrs(ObjPtr->fattr); FreeRCBoxObj(ObjPtr); break;
124 case OBJ_XBM: DelAllAttrs(ObjPtr->fattr); FreeXBmObj(ObjPtr); break;
125 case OBJ_XPM: DelAllAttrs(ObjPtr->fattr); FreeXPmObj(ObjPtr); break;
126 case OBJ_GROUP:
127 case OBJ_ICON:
128 case OBJ_SYM:
129 case OBJ_PIN: DelAllAttrs(ObjPtr->fattr); FreeGroupObj(ObjPtr); break;
130 }
131 }
132
DelObj(ObjPtr)133 void DelObj(ObjPtr)
134 struct ObjRec *ObjPtr;
135 {
136 if (ObjPtr->type == OBJ_POLY) {
137 if (ObjPtr->detail.p->start_conn != NULL) {
138 DelConnFromPoly(ObjPtr->detail.p->start_conn);
139 }
140 if (ObjPtr->detail.p->end_conn != NULL) {
141 DelConnFromPoly(ObjPtr->detail.p->end_conn);
142 }
143 } else if (ObjPtr->type == OBJ_PIN) {
144 while (ObjPtr->detail.r->pin_connected > 0) {
145 DelConnFromPin(ObjPtr->detail.p->end_conn);
146 }
147 }
148 if (topObj == ObjPtr) {
149 curPage->top = topObj = ObjPtr->next;
150 } else {
151 ObjPtr->prev->next = ObjPtr->next;
152 }
153 if (botObj == ObjPtr) {
154 curPage->bot = botObj = ObjPtr->prev;
155 } else {
156 ObjPtr->next->prev = ObjPtr->prev;
157 }
158 FreeObj(ObjPtr);
159 }
160
DelAllObj()161 void DelAllObj()
162 {
163 register struct ObjRec *ptr, *next_obj;
164
165 if (topObj == NULL) return;
166
167 for (ptr=topObj; ptr != NULL; ptr=next_obj) {
168 next_obj = ptr->next;
169 FreeObj(ptr);
170 }
171 if (curPage != NULL) curPage->top = curPage->bot = NULL;
172 topObj = botObj = NULL;
173 }
174
AdjObjOBBox(ObjPtr)175 void AdjObjOBBox(ObjPtr)
176 struct ObjRec *ObjPtr;
177 {
178 struct ObjRec *obj_ptr;
179 int oltx, olty, orbx, orby;
180
181 switch (ObjPtr->type) {
182 case OBJ_ARC:
183 CalcArcOBBox(ObjPtr);
184 break;
185 case OBJ_TEXT:
186 SetTextOBBox(ObjPtr, ObjPtr->detail.t->minilines.just,
187 ObjPtr->obbox.rbx-ObjPtr->obbox.ltx,
188 ObjPtr->obbox.rby-ObjPtr->obbox.lty,
189 ObjPtr->detail.t->min_lbearing,
190 ObjPtr->detail.t->max_rextra, ROTATE0);
191 break;
192 case OBJ_GROUP:
193 case OBJ_ICON:
194 case OBJ_SYM:
195 obj_ptr = ObjPtr->detail.r->last;
196 oltx = obj_ptr->obbox.ltx; olty = obj_ptr->obbox.lty;
197 orbx = obj_ptr->obbox.rbx; orby = obj_ptr->obbox.rby;
198 for (obj_ptr = obj_ptr->prev; obj_ptr != NULL; obj_ptr = obj_ptr->prev) {
199 if (obj_ptr->obbox.ltx < oltx) oltx = obj_ptr->obbox.ltx;
200 if (obj_ptr->obbox.lty < olty) olty = obj_ptr->obbox.lty;
201 if (obj_ptr->obbox.rbx > orbx) orbx = obj_ptr->obbox.rbx;
202 if (obj_ptr->obbox.rby > orby) orby = obj_ptr->obbox.rby;
203 }
204 ObjPtr->obbox.ltx = oltx; ObjPtr->obbox.lty = olty;
205 ObjPtr->obbox.rbx = orbx; ObjPtr->obbox.rby = orby;
206 break;
207 case OBJ_PIN:
208 obj_ptr = GetPinObj(ObjPtr);
209 oltx = obj_ptr->obbox.ltx; olty = obj_ptr->obbox.lty;
210 orbx = obj_ptr->obbox.rbx; orby = obj_ptr->obbox.rby;
211 ObjPtr->obbox.ltx = oltx; ObjPtr->obbox.lty = olty;
212 ObjPtr->obbox.rbx = orbx; ObjPtr->obbox.rby = orby;
213 break;
214 }
215 }
216
AdjObjBBox(ObjPtr)217 void AdjObjBBox(ObjPtr)
218 struct ObjRec *ObjPtr;
219 {
220 register int w=0;
221 register struct ObjRec *obj_ptr;
222 register struct AttrRec *attr_ptr;
223 int ltx, lty, rbx, rby;
224
225 AdjObjOBBox(ObjPtr);
226
227 switch (ObjPtr->type) {
228 case OBJ_POLY:
229 CalcPolyBBox(ObjPtr);
230 break;
231 case OBJ_ARC:
232 CalcArcBBox(ObjPtr, ObjPtr->obbox, &(ObjPtr->bbox));
233 break;
234 case OBJ_POLYGON: w = HALF_W(ObjPtr->detail.g->width); break;
235 case OBJ_BOX: w = HALF_W(ObjPtr->detail.b->width); break;
236 case OBJ_OVAL: w = HALF_W(ObjPtr->detail.o->width); break;
237 case OBJ_RCBOX: w = HALF_W(ObjPtr->detail.rcb->width); break;
238 case OBJ_XBM: break;
239 case OBJ_XPM: break;
240
241 case OBJ_GROUP:
242 case OBJ_ICON:
243 case OBJ_SYM:
244 obj_ptr = ObjPtr->detail.r->last;
245 ltx = obj_ptr->bbox.ltx; lty = obj_ptr->bbox.lty;
246 rbx = obj_ptr->bbox.rbx; rby = obj_ptr->bbox.rby;
247 for (obj_ptr = obj_ptr->prev; obj_ptr != NULL; obj_ptr = obj_ptr->prev) {
248 if (obj_ptr->bbox.ltx < ltx) ltx = obj_ptr->bbox.ltx;
249 if (obj_ptr->bbox.lty < lty) lty = obj_ptr->bbox.lty;
250 if (obj_ptr->bbox.rbx > rbx) rbx = obj_ptr->bbox.rbx;
251 if (obj_ptr->bbox.rby > rby) rby = obj_ptr->bbox.rby;
252 }
253 ObjPtr->bbox.ltx = ltx; ObjPtr->bbox.lty = lty;
254 ObjPtr->bbox.rbx = rbx; ObjPtr->bbox.rby = rby;
255 break;
256 case OBJ_PIN:
257 obj_ptr = GetPinObj(ObjPtr);
258 ltx = obj_ptr->bbox.ltx; lty = obj_ptr->bbox.lty;
259 rbx = obj_ptr->bbox.rbx; rby = obj_ptr->bbox.rby;
260 ObjPtr->bbox.ltx = ltx; ObjPtr->bbox.lty = lty;
261 ObjPtr->bbox.rbx = rbx; ObjPtr->bbox.rby = rby;
262 break;
263 }
264 switch (ObjPtr->type) {
265 case OBJ_POLY:
266 case OBJ_ARC:
267 break;
268 case OBJ_POLYGON:
269 case OBJ_BOX:
270 case OBJ_OVAL:
271 case OBJ_RCBOX:
272 case OBJ_XBM:
273 case OBJ_XPM:
274 ObjPtr->bbox.ltx = ObjPtr->obbox.ltx - w;
275 ObjPtr->bbox.lty = ObjPtr->obbox.lty - w;
276 ObjPtr->bbox.rbx = ObjPtr->obbox.rbx + w;
277 ObjPtr->bbox.rby = ObjPtr->obbox.rby + w;
278 break;
279 case OBJ_TEXT:
280 SetTextBBox(ObjPtr, ObjPtr->detail.t->minilines.just,
281 ObjPtr->obbox.rbx-ObjPtr->obbox.ltx,
282 ObjPtr->obbox.rby-ObjPtr->obbox.lty,
283 ObjPtr->detail.t->min_lbearing,
284 ObjPtr->detail.t->max_rextra, ROTATE0);
285 break;
286 }
287
288 attr_ptr = ObjPtr->fattr;
289
290 ltx = ObjPtr->bbox.ltx;
291 lty = ObjPtr->bbox.lty;
292 rbx = ObjPtr->bbox.rbx;
293 rby = ObjPtr->bbox.rby;
294 for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next) {
295 if (attr_ptr->shown) {
296 if (attr_ptr->obj->bbox.ltx < ltx) ltx = attr_ptr->obj->bbox.ltx;
297 if (attr_ptr->obj->bbox.lty < lty) lty = attr_ptr->obj->bbox.lty;
298 if (attr_ptr->obj->bbox.rbx > rbx) rbx = attr_ptr->obj->bbox.rbx;
299 if (attr_ptr->obj->bbox.rby > rby) rby = attr_ptr->obj->bbox.rby;
300 }
301 }
302 ObjPtr->bbox.ltx = ltx;
303 ObjPtr->bbox.lty = lty;
304 ObjPtr->bbox.rbx = rbx;
305 ObjPtr->bbox.rby = rby;
306
307 if (ObjPtr->type == OBJ_SYM) {
308 if (ObjPtr->obbox.ltx-QUARTER_INCH < ObjPtr->bbox.ltx) {
309 ObjPtr->bbox.ltx = ObjPtr->obbox.ltx - QUARTER_INCH;
310 }
311 if (ObjPtr->obbox.lty-QUARTER_INCH < ObjPtr->bbox.lty) {
312 ObjPtr->bbox.lty = ObjPtr->obbox.lty - QUARTER_INCH;
313 }
314 if (ObjPtr->obbox.rbx+QUARTER_INCH > ObjPtr->bbox.rbx) {
315 ObjPtr->bbox.rbx = ObjPtr->obbox.rbx + QUARTER_INCH;
316 }
317 if (ObjPtr->obbox.rby+QUARTER_INCH > ObjPtr->bbox.rby) {
318 ObjPtr->bbox.rby = ObjPtr->obbox.rby + QUARTER_INCH;
319 }
320 }
321 }
322
323 static
RecursivelyAdjAnObjBBox(target_obj,owner_obj)324 void RecursivelyAdjAnObjBBox(target_obj, owner_obj)
325 struct ObjRec *target_obj, *owner_obj;
326 {
327 if (target_obj == owner_obj) {
328 AdjObjBBox(target_obj);
329 } else {
330 struct ObjRec *obj_ptr=NULL;
331
332 switch (owner_obj->type) {
333 case OBJ_GROUP:
334 case OBJ_ICON:
335 case OBJ_SYM:
336 case OBJ_PIN:
337 for (obj_ptr=owner_obj->detail.r->first; obj_ptr!=NULL;
338 obj_ptr=obj_ptr->next) {
339 RecursivelyAdjAnObjBBox(target_obj, obj_ptr);
340 }
341 AdjObjBBox(owner_obj);
342 break;
343 default: break;
344 }
345 }
346 }
347
RecursivelyAdjObjBBox(sub_obj,owner_obj,top_owner)348 void RecursivelyAdjObjBBox(sub_obj, owner_obj, top_owner)
349 struct ObjRec *sub_obj, *owner_obj, *top_owner;
350 {
351 if (owner_obj == NULL) {
352 RecursivelyAdjAnObjBBox(sub_obj, sub_obj);
353 } else {
354 RecursivelyAdjAnObjBBox(sub_obj, top_owner);
355 }
356 }
357
358 static
InvalidateObjCache(ObjPtr)359 void InvalidateObjCache(ObjPtr)
360 struct ObjRec *ObjPtr;
361 {
362 int w=0, h=0, num_rows=0, num_cols=0;
363 struct TextRec *text_ptr=NULL;
364 struct XBmRec *xbm_ptr=NULL;
365 struct XPmRec *xpm_ptr=NULL;
366 struct ObjRec *obj_ptr=NULL;
367
368 w = ObjPtr->obbox.rbx - ObjPtr->obbox.ltx;
369 h = ObjPtr->obbox.rby - ObjPtr->obbox.lty;
370 switch (ObjPtr->type) {
371 case OBJ_POLY:
372 if (NeedsToCachePolyObj(ObjPtr)) {
373 struct PolyRec *poly_ptr=ObjPtr->detail.p;
374
375 if (poly_ptr->rotated_vlist != NULL) free(poly_ptr->rotated_vlist);
376 if (poly_ptr->rotated_asvlist != NULL) {
377 free(poly_ptr->rotated_asvlist);
378 }
379 poly_ptr->rotated_vlist = poly_ptr->rotated_asvlist = NULL;
380 poly_ptr->rotated_n = poly_ptr->rotated_asn = 0;
381 }
382 break;
383 case OBJ_BOX: break;
384
385 case OBJ_OVAL:
386 /* atan2(61/112) = 0.498721 rad = 28.5746 deg */
387 if (NeedsToCacheOvalObj(ObjPtr)) {
388 struct OvalRec *oval_ptr=ObjPtr->detail.o;
389
390 if (oval_ptr->rotated_vlist != NULL) free(oval_ptr->rotated_vlist);
391 oval_ptr->rotated_vlist = NULL;
392 oval_ptr->rotated_n = 0;
393 }
394 break;
395 case OBJ_POLYGON:
396 if (NeedsToCachePolygonObj(ObjPtr)) {
397 struct PolygonRec *polygon_ptr=ObjPtr->detail.g;
398
399 if (polygon_ptr->rotated_vlist != NULL) {
400 free(polygon_ptr->rotated_vlist);
401 }
402 polygon_ptr->rotated_vlist = NULL;
403 polygon_ptr->rotated_n = 0;
404 }
405 break;
406 case OBJ_ARC:
407 if (NeedsToCacheArcObj(ObjPtr)) {
408 struct ArcRec *arc_ptr=ObjPtr->detail.a;
409
410 if (arc_ptr->rotated_vlist != NULL) free(arc_ptr->rotated_vlist);
411 if (arc_ptr->rotated_asvlist != NULL) free(arc_ptr->rotated_asvlist);
412 arc_ptr->rotated_vlist = arc_ptr->rotated_asvlist = NULL;
413 arc_ptr->rotated_n = arc_ptr->rotated_asn = 0;
414 }
415 break;
416 case OBJ_RCBOX:
417 if (NeedsToCacheRCBoxObj(ObjPtr)) {
418 struct RCBoxRec *rcbox_ptr=ObjPtr->detail.rcb;
419
420 if (rcbox_ptr->rotated_vlist != NULL) free(rcbox_ptr->rotated_vlist);
421 rcbox_ptr->rotated_vlist = NULL;
422 rcbox_ptr->rotated_n = 0;
423 }
424 break;
425 case OBJ_TEXT:
426 text_ptr = ObjPtr->detail.t;
427 if (NeedsToCacheTextObj(ObjPtr)) {
428 if (text_ptr->cached_bitmap != None) {
429 XFreePixmap(mainDisplay, text_ptr->cached_bitmap);
430 }
431 if (text_ptr->cached_pixmap != None) {
432 XFreePixmap(mainDisplay, text_ptr->cached_pixmap);
433 }
434 if (text_ptr->cached_bg_bitmap != None) {
435 XFreePixmap(mainDisplay, text_ptr->cached_bg_bitmap);
436 }
437 text_ptr->cached_bitmap = None;
438 text_ptr->cached_pixmap = None;
439 text_ptr->cached_bg_bitmap = None;
440 if (zoomScale != 0) {
441 text_ptr->cached_zoom = 0;
442 }
443 }
444 break;
445 case OBJ_XBM:
446 xbm_ptr = ObjPtr->detail.xbm;
447 num_cols = (zoomedIn) ? (w<<zoomScale) : (w>>zoomScale);
448 num_rows = (zoomedIn) ? (h<<zoomScale) : (h>>zoomScale);
449 if (NeedsToCacheXBmObj(ObjPtr)) {
450 if (xbm_ptr->cached_bitmap != None) {
451 XFreePixmap(mainDisplay, xbm_ptr->cached_bitmap);
452 }
453 xbm_ptr->cached_bitmap = None;
454 if (zoomScale != 0) {
455 xbm_ptr->cached_zoom = 0;
456 }
457 }
458 break;
459 case OBJ_XPM:
460 xpm_ptr = ObjPtr->detail.xpm;
461 num_cols = (zoomedIn) ? (w<<zoomScale) : (w>>zoomScale);
462 num_rows = (zoomedIn) ? (h<<zoomScale) : (h>>zoomScale);
463 if (NeedsToCacheXPmObj(ObjPtr)) {
464 if (xpm_ptr->cached_pixmap != None) {
465 XFreePixmap(mainDisplay, xpm_ptr->cached_pixmap);
466 }
467 xpm_ptr->cached_pixmap = None;
468 if (xpm_ptr->cached_bitmap != None) {
469 XFreePixmap(mainDisplay, xpm_ptr->cached_bitmap);
470 }
471 xpm_ptr->cached_bitmap = None;
472 if (xpm_ptr->clip_mask != None) {
473 XFreePixmap(mainDisplay, xpm_ptr->clip_mask);
474 }
475 xpm_ptr->clip_mask = None;
476 if (zoomScale != 0) {
477 xpm_ptr->cached_zoom = 0;
478 }
479 xpm_ptr->cached_color = (-1);
480 }
481 break;
482
483 case OBJ_GROUP:
484 case OBJ_ICON:
485 case OBJ_SYM:
486 case OBJ_PIN:
487 for (obj_ptr=ObjPtr->detail.r->first; obj_ptr != NULL;
488 obj_ptr=obj_ptr->next) {
489 InvalidateObjCache(obj_ptr);
490 }
491 break;
492 }
493 }
494
AdjObjCache(ObjPtr)495 void AdjObjCache(ObjPtr)
496 struct ObjRec *ObjPtr;
497 {
498 register struct ObjRec *obj_ptr;
499 register struct AttrRec *attr_ptr;
500
501 GetTransformedOBBoxOffsetVs(ObjPtr, ObjPtr->rotated_obbox);
502 switch (ObjPtr->type) {
503 case OBJ_GROUP:
504 case OBJ_ICON:
505 case OBJ_SYM:
506 case OBJ_PIN:
507 for (obj_ptr=ObjPtr->detail.r->first; obj_ptr != NULL;
508 obj_ptr=obj_ptr->next) {
509 AdjObjCache(obj_ptr);
510 }
511 break;
512 default:
513 InvalidateObjCache(ObjPtr);
514 break;
515 }
516 for (attr_ptr=ObjPtr->fattr; attr_ptr!=NULL; attr_ptr=attr_ptr->next) {
517 if (attr_ptr->shown) {
518 AdjObjCache(attr_ptr->obj);
519 }
520 }
521 }
522
AdjCaches()523 void AdjCaches()
524 {
525 register struct ObjRec *obj_ptr, *ptr;
526 register struct AttrRec *attr_ptr;
527
528 if (topObj == NULL) return;
529
530 for (obj_ptr = topObj; obj_ptr != NULL; obj_ptr=obj_ptr->next) {
531 switch (obj_ptr->type) {
532 case OBJ_TEXT:
533 case OBJ_XBM:
534 case OBJ_XPM:
535 AdjObjCache(obj_ptr);
536 break;
537 case OBJ_GROUP:
538 case OBJ_ICON:
539 case OBJ_SYM:
540 case OBJ_PIN:
541 for (ptr=obj_ptr->detail.r->first; ptr != NULL; ptr=ptr->next) {
542 AdjObjCache(ptr);
543 }
544 break;
545 }
546 for (attr_ptr=obj_ptr->fattr; attr_ptr!=NULL; attr_ptr=attr_ptr->next) {
547 if (attr_ptr->shown) {
548 AdjObjCache(attr_ptr->obj);
549 }
550 }
551 }
552 }
553
554 static int dontAutoRetractArrow=FALSE;
555
556 #define RETREAT (0.8)
557
558 static
AdjArcCache(ObjPtr)559 void AdjArcCache(ObjPtr)
560 struct ObjRec *ObjPtr;
561 {
562 struct ArcRec *arc_ptr=ObjPtr->detail.a;
563 int a_angle1, a_angle2;
564
565 if (arc_ptr->style == LS_PLAIN) return;
566
567 a_angle1 = arc_ptr->angle1;
568 a_angle2 = arc_ptr->angle2;
569 GetArcArrowInfo(ObjPtr, NULL, NULL, NULL, &a_angle1,
570 NULL, NULL, NULL, &a_angle2);
571 arc_ptr->a_angle1 = a_angle1;
572 arc_ptr->a_angle2 = a_angle2;
573 }
574
575 static
AdjPolyCache(ObjPtr)576 void AdjPolyCache(ObjPtr)
577 struct ObjRec *ObjPtr;
578 {
579 struct PolyRec *poly_ptr=ObjPtr->detail.p;
580
581 if (poly_ptr->rotated_vlist != NULL) {
582 free(poly_ptr->rotated_vlist);
583 }
584 if (poly_ptr->rotated_asvlist != NULL) {
585 free(poly_ptr->rotated_asvlist);
586 }
587 poly_ptr->rotated_vlist = poly_ptr->rotated_asvlist = NULL;
588 poly_ptr->rotated_n = poly_ptr->rotated_asn = 0;
589
590 switch (poly_ptr->curved) {
591 case LT_STRAIGHT:
592 case LT_SPLINE:
593 if (poly_ptr->svlist != NULL) {
594 free(poly_ptr->svlist);
595 }
596 poly_ptr->svlist = MakeMultiSplinePolyVertex(
597 poly_ptr->curved, &(poly_ptr->sn), poly_ptr->smooth,
598 drawOrigX, drawOrigY,
599 poly_ptr->n, poly_ptr->vlist);
600 break;
601 case LT_STRUCT_SPLINE:
602 if (poly_ptr->svlist != NULL) free(poly_ptr->svlist);
603 if (poly_ptr->ssvlist != NULL) free(poly_ptr->ssvlist);
604 if (poly_ptr->ssmooth != NULL) free(poly_ptr->ssmooth);
605 if (poly_ptr->smooth != NULL) free(poly_ptr->smooth);
606 poly_ptr->smooth = NULL;
607 poly_ptr->ssvlist = MakeStructuredSplinePolyVertex(&(poly_ptr->ssn),
608 &(poly_ptr->ssmooth), poly_ptr->n, poly_ptr->vlist);
609 poly_ptr->svlist = MakeMultiSplinePolyVertex(
610 poly_ptr->curved, &(poly_ptr->sn), poly_ptr->ssmooth,
611 drawOrigX, drawOrigY, poly_ptr->ssn, poly_ptr->ssvlist);
612 break;
613 case LT_INTSPLINE:
614 if (poly_ptr->svlist != NULL) {
615 free(poly_ptr->svlist);
616 }
617 if (poly_ptr->intvlist != NULL) {
618 free(poly_ptr->intvlist);
619 }
620 if (!undoingOrRedoing && !dontAutoRetractArrow) {
621 if (AutoRetractedArrowAttr(ObjPtr, FALSE)) {
622 int new_x=0, new_y=0;
623 IntPoint *v=NULL;
624
625 if (poly_ptr->n != 3) {
626 int x0, y0, x2, y2;
627
628 v = poly_ptr->vlist;
629 x0 = v[0].x; y0 = v[0].y;
630 x2 = v[poly_ptr->n-1].x; y2 = v[poly_ptr->n-1].y;
631 if (poly_ptr->smooth != NULL) free(poly_ptr->smooth);
632 poly_ptr->smooth = (char*)malloc(4*sizeof(char));
633 if (poly_ptr->smooth == NULL) FailAllocMessage();
634 poly_ptr->smooth[0] = poly_ptr->smooth[1] =
635 poly_ptr->smooth[2] = FALSE;
636 if (poly_ptr->vlist != NULL) free(poly_ptr->vlist);
637 poly_ptr->vlist = (IntPoint*)malloc(4*sizeof(IntPoint));
638 if (poly_ptr->vlist == NULL) FailAllocMessage();
639 poly_ptr->vlist[0].x = x0; poly_ptr->vlist[0].y = y0;
640 poly_ptr->vlist[2].x = x2; poly_ptr->vlist[2].y = y2;
641 poly_ptr->n = 3;
642 }
643 v = poly_ptr->vlist;
644 CalcAutoRetractedArrowAttrBend(poly_ptr->style,
645 v[0].x, v[0].y, v[2].x, v[2].y, &new_x, &new_y);
646 v[1].x = new_x;
647 v[1].y = new_y;
648 }
649 }
650 poly_ptr->svlist = MakeIntSplinePolyVertex(
651 &(poly_ptr->sn), &(poly_ptr->intn),
652 &(poly_ptr->intvlist), drawOrigX, drawOrigY,
653 poly_ptr->n, poly_ptr->vlist);
654 break;
655 }
656 if (poly_ptr->style != LS_PLAIN) {
657 IntPoint *v=poly_ptr->vlist, *v_copy;
658 int i, n=poly_ptr->n, dx, dy, aw=poly_ptr->aw, retracted_arrow;
659 double len, sin_val, cos_val;
660
661 retracted_arrow = (RetractedArrowAttr(ObjPtr) ||
662 AutoRetractedArrowAttr(ObjPtr, TRUE));
663 if (poly_ptr->asvlist != NULL) {
664 free(poly_ptr->asvlist);
665 }
666 switch (poly_ptr->curved) {
667 case LT_STRAIGHT:
668 case LT_SPLINE:
669 v = poly_ptr->vlist;
670 n = poly_ptr->n;
671 break;
672 case LT_STRUCT_SPLINE:
673 v = poly_ptr->ssvlist;
674 n = poly_ptr->ssn;
675 break;
676 case LT_INTSPLINE:
677 v = poly_ptr->intvlist;
678 n = poly_ptr->intn;
679 break;
680 }
681 v_copy = (IntPoint *)malloc((n+1)*sizeof(IntPoint));
682 if (v_copy == NULL) FailAllocMessage();
683 for (i = 0; i < n; i++) {
684 v_copy[i].x = v[i].x;
685 v_copy[i].y = v[i].y;
686 }
687 if (aw == 0) aw = 1;
688
689 dx = v_copy[1].x - v_copy[0].x;
690 dy = v_copy[1].y - v_copy[0].y;
691 if (!retracted_arrow && (poly_ptr->style & LS_LEFT) &&
692 (dx != 0 || dy != 0)) {
693 len = (double)sqrt((double)(((double)dx)*((double)dx) +
694 ((double)dy)*((double)dy)));
695 sin_val = ((double)dy)/len;
696 cos_val = ((double)dx)/len;
697
698 v_copy[0].x = round(v_copy[0].x+RETREAT*aw*cos_val);
699 v_copy[0].y = round(v_copy[0].y+RETREAT*aw*sin_val);
700 }
701 dx = v_copy[n-1].x - v_copy[n-2].x;
702 dy = v_copy[n-1].y - v_copy[n-2].y;
703 if (!retracted_arrow && (poly_ptr->style & LS_RIGHT) &&
704 (dx != 0 || dy != 0)) {
705 len = (double)sqrt((double)(((double)dx)*((double)dx) +
706 ((double)dy)*((double)dy)));
707 sin_val = ((double)dy)/len;
708 cos_val = ((double)dx)/len;
709
710 v_copy[n-1].x = round(v_copy[n-1].x-RETREAT*aw*cos_val);
711 v_copy[n-1].y = round(v_copy[n-1].y-RETREAT*aw*sin_val);
712 }
713 switch (poly_ptr->curved) {
714 case LT_STRAIGHT:
715 case LT_SPLINE:
716 poly_ptr->asvlist = MakeMultiSplinePolyVertex(
717 poly_ptr->curved, &(poly_ptr->asn), poly_ptr->smooth,
718 drawOrigX, drawOrigY, n, v_copy);
719 break;
720 case LT_STRUCT_SPLINE:
721 poly_ptr->asvlist = MakeMultiSplinePolyVertex(
722 poly_ptr->curved, &(poly_ptr->asn), poly_ptr->ssmooth,
723 drawOrigX, drawOrigY, n, v_copy);
724 break;
725 case LT_INTSPLINE:
726 poly_ptr->asvlist = MakeSplinePolyVertex(0, poly_ptr->curved,
727 &(poly_ptr->asn), drawOrigX, drawOrigY, n, v_copy);
728 break;
729 }
730 free(v_copy);
731 }
732 }
733
734 static
AdjPolygonCache(ObjPtr)735 void AdjPolygonCache(ObjPtr)
736 struct ObjRec *ObjPtr;
737 {
738 struct PolygonRec *polygon_ptr=ObjPtr->detail.g;
739
740 if (polygon_ptr->rotated_vlist != NULL) {
741 free(polygon_ptr->rotated_vlist);
742 }
743 polygon_ptr->rotated_vlist = NULL;
744 polygon_ptr->rotated_n = 0;
745
746 switch (polygon_ptr->curved) {
747 case LT_STRAIGHT:
748 if (polygon_ptr->svlist != NULL) {
749 free(polygon_ptr->svlist);
750 }
751 polygon_ptr->svlist = MakeMultiSplinePolygonVertex(
752 polygon_ptr->curved, &(polygon_ptr->sn), polygon_ptr->smooth,
753 drawOrigX, drawOrigY,
754 polygon_ptr->n, polygon_ptr->vlist);
755 break;
756 case LT_SPLINE:
757 if (polygon_ptr->svlist != NULL) {
758 free(polygon_ptr->svlist);
759 }
760 polygon_ptr->svlist = MakeMultiSplinePolygonVertex(
761 polygon_ptr->curved, &(polygon_ptr->sn), polygon_ptr->smooth,
762 drawOrigX, drawOrigY,
763 polygon_ptr->n, polygon_ptr->vlist);
764 break;
765 case LT_STRUCT_SPLINE:
766 if (polygon_ptr->svlist != NULL) free(polygon_ptr->svlist);
767 if (polygon_ptr->ssvlist != NULL) free(polygon_ptr->ssvlist);
768 if (polygon_ptr->ssmooth != NULL) free(polygon_ptr->ssmooth);
769 if (polygon_ptr->smooth != NULL) free(polygon_ptr->smooth);
770 #ifdef _TGIF_DBG /* debug, do not translate */
771 TgAssert(polygon_ptr->n >= 7, "NumPts < 7 in AdjPolygonCache()", NULL);
772 #endif /* _TGIF_DBG */
773 polygon_ptr->smooth = NULL;
774 polygon_ptr->ssvlist = MakeStructuredSplinePolygonVertex(
775 &(polygon_ptr->ssn), &(polygon_ptr->ssmooth), polygon_ptr->n,
776 polygon_ptr->vlist);
777 polygon_ptr->svlist = MakeMultiSplinePolygonVertex(
778 polygon_ptr->curved, &(polygon_ptr->sn), polygon_ptr->ssmooth,
779 drawOrigX, drawOrigY,
780 polygon_ptr->ssn, polygon_ptr->ssvlist);
781 break;
782 case LT_INTSPLINE:
783 if (polygon_ptr->svlist != NULL) {
784 free(polygon_ptr->svlist);
785 }
786 if (polygon_ptr->intvlist != NULL) {
787 free(polygon_ptr->intvlist);
788 }
789 polygon_ptr->svlist = MakeIntSplinePolygonVertex(
790 &(polygon_ptr->sn), &(polygon_ptr->intn),
791 &(polygon_ptr->intvlist), drawOrigX, drawOrigY,
792 polygon_ptr->n, polygon_ptr->vlist);
793 break;
794 }
795 }
796
AdjObjSplineVs(ObjPtr)797 void AdjObjSplineVs(ObjPtr)
798 struct ObjRec *ObjPtr;
799 {
800 struct ObjRec *obj_ptr;
801
802 switch (ObjPtr->type) {
803 case OBJ_BOX: break;
804 case OBJ_XBM: break;
805 case OBJ_XPM: break;
806 case OBJ_OVAL: InvalidateObjCache(ObjPtr); break;
807 case OBJ_TEXT: break;
808 case OBJ_RCBOX: InvalidateObjCache(ObjPtr); break;
809 case OBJ_ARC: InvalidateObjCache(ObjPtr); AdjArcCache(ObjPtr); break;
810 case OBJ_POLY: AdjPolyCache(ObjPtr); break;
811 case OBJ_POLYGON: AdjPolygonCache(ObjPtr); break;
812
813 case OBJ_GROUP:
814 case OBJ_ICON:
815 case OBJ_SYM:
816 case OBJ_PIN:
817 for (obj_ptr=ObjPtr->detail.r->first; obj_ptr != NULL;
818 obj_ptr=obj_ptr->next) {
819 AdjObjSplineVs(obj_ptr);
820 }
821 break;
822 }
823 GetTransformedOBBoxOffsetVs(ObjPtr, ObjPtr->rotated_obbox);
824 }
825
AdjSplineVs()826 void AdjSplineVs()
827 {
828 register struct ObjRec *obj_ptr, *ptr;
829
830 if (topObj == NULL) return;
831
832 dontAutoRetractArrow = TRUE;
833 for (obj_ptr = topObj; obj_ptr != NULL; obj_ptr = obj_ptr->next) {
834 switch (obj_ptr->type) {
835 case OBJ_POLY:
836 case OBJ_BOX:
837 case OBJ_OVAL:
838 case OBJ_TEXT:
839 case OBJ_POLYGON:
840 case OBJ_ARC:
841 case OBJ_RCBOX:
842 case OBJ_XBM:
843 case OBJ_XPM:
844 AdjObjSplineVs(obj_ptr);
845 break;
846 case OBJ_GROUP:
847 case OBJ_ICON:
848 case OBJ_SYM:
849 case OBJ_PIN:
850 for (ptr=obj_ptr->detail.r->first; ptr != NULL; ptr=ptr->next) {
851 AdjObjSplineVs(ptr);
852 }
853 GetTransformedOBBoxOffsetVs(obj_ptr, obj_ptr->rotated_obbox);
854 break;
855 }
856 }
857 dontAutoRetractArrow = FALSE;
858 }
859
ClearObjCachesInAllPages()860 void ClearObjCachesInAllPages()
861 {
862 struct ObjRec *saved_top_obj=topObj, *saved_bot_obj=botObj;
863 struct PageRec *saved_cur_page=curPage;
864
865 for (curPage=firstPage; curPage != NULL; curPage=curPage->next) {
866 topObj = curPage->top;
867 botObj = curPage->bot;
868
869 AdjCaches();
870 AdjSplineVs();
871 curPage->draw_orig_x = drawOrigX;
872 curPage->draw_orig_y = drawOrigY;
873 curPage->zoom_scale = zoomScale;
874 curPage->zoomed_in = zoomedIn;
875 }
876 topObj = saved_top_obj;
877 botObj = saved_bot_obj;
878 curPage = saved_cur_page;
879 }
880
MoveRotatedObjCache(ObjPtr,AbsDx,AbsDy)881 void MoveRotatedObjCache(ObjPtr, AbsDx, AbsDy)
882 struct ObjRec *ObjPtr;
883 int AbsDx, AbsDy;
884 {
885 register int i;
886 int dx_off, dy_off, n=0;
887 XPoint *v=NULL;
888
889 if (ObjPtr->ctm == NULL) return;
890
891 dx_off = ZOOMED_SIZE(AbsDx);
892 dy_off = ZOOMED_SIZE(AbsDy);
893 for (i=0; i < 5; i++) {
894 ObjPtr->rotated_obbox[i].x += dx_off;
895 ObjPtr->rotated_obbox[i].y += dy_off;
896 }
897 ObjPtr->orig_obbox.ltx += AbsDx; ObjPtr->orig_obbox.lty += AbsDy;
898 ObjPtr->orig_obbox.rbx += AbsDx; ObjPtr->orig_obbox.rby += AbsDy;
899 switch (ObjPtr->type) {
900 case OBJ_POLY:
901 case OBJ_POLYGON:
902 case OBJ_OVAL:
903 case OBJ_ARC:
904 case OBJ_RCBOX:
905 switch (ObjPtr->type) {
906 case OBJ_POLY:
907 n = ObjPtr->detail.p->rotated_n;
908 v = ObjPtr->detail.p->rotated_vlist;
909 break;
910 case OBJ_POLYGON:
911 n = ObjPtr->detail.g->rotated_n;
912 v = ObjPtr->detail.g->rotated_vlist;
913 break;
914 case OBJ_OVAL:
915 n = ObjPtr->detail.o->rotated_n;
916 v = ObjPtr->detail.o->rotated_vlist;
917 break;
918 case OBJ_ARC:
919 n = ObjPtr->detail.a->rotated_n;
920 v = ObjPtr->detail.a->rotated_vlist;
921 break;
922 case OBJ_RCBOX:
923 n = ObjPtr->detail.rcb->rotated_n;
924 v = ObjPtr->detail.rcb->rotated_vlist;
925 break;
926 }
927 if (v != NULL) {
928 for (i=0; i < n; i++) {
929 v[i].x += dx_off;
930 v[i].y += dy_off;
931 }
932 }
933 if (ObjPtr->type == OBJ_POLY) {
934 n = ObjPtr->detail.p->rotated_asn;
935 v = ObjPtr->detail.p->rotated_asvlist;
936 if (v != NULL) {
937 for (i=0; i < n; i++) {
938 v[i].x += dx_off;
939 v[i].y += dy_off;
940 }
941 }
942 }
943 break;
944 case OBJ_BOX:
945 case OBJ_GROUP:
946 case OBJ_ICON:
947 case OBJ_SYM:
948 case OBJ_PIN:
949 case OBJ_XBM:
950 case OBJ_XPM:
951 break;
952 case OBJ_TEXT:
953 ObjPtr->detail.t->orig_bbox.ltx += AbsDx;
954 ObjPtr->detail.t->orig_bbox.lty += AbsDy;
955 ObjPtr->detail.t->orig_bbox.rbx += AbsDx;
956 ObjPtr->detail.t->orig_bbox.rby += AbsDy;
957 break;
958 }
959 }
960
AdjHotSpots()961 void AdjHotSpots()
962 {
963 }
964
AdjObjHotSpot()965 void AdjObjHotSpot()
966 {
967 }
968
IsTopLevelObject(ObjPtr)969 int IsTopLevelObject(ObjPtr)
970 struct ObjRec *ObjPtr;
971 {
972 struct ObjRec *obj_ptr=NULL;
973
974 for (obj_ptr=topObj; obj_ptr != NULL; obj_ptr=obj_ptr->next) {
975 if (obj_ptr == ObjPtr) {
976 return TRUE;
977 }
978 }
979 return FALSE;
980 }
981
GetTopOwner(ObjPtr)982 struct ObjRec *GetTopOwner(ObjPtr)
983 struct ObjRec *ObjPtr;
984 {
985 struct ObjRec *top_owner=ObjPtr;
986
987 while (top_owner->tmp_parent != NULL) {
988 top_owner = top_owner->tmp_parent;
989 }
990 return top_owner;
991 }
992