|
NCBI Home IEB Home C Toolkit docs C++ Toolkit source browser C Toolkit source browser (2) |
NCBI C Toolkit Cross ReferenceC/vibrant/drawing.c |
source navigation diff markup identifier search freetext search file search |
1 /* drawing.c
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information (NCBI)
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government do not place any restriction on its use or reproduction.
13 * We would, however, appreciate having the NCBI and the author cited in
14 * any work or product based on this material
15 *
16 * Although all reasonable efforts have been taken to ensure the accuracy
17 * and reliability of the software and data, the NLM and the U.S.
18 * Government do not and cannot warrant the performance or results that
19 * may be obtained by using this software or data. The NLM and the U.S.
20 * Government disclaim all warranties, express or implied, including
21 * warranties of performance, merchantability or fitness for any particular
22 * purpose.
23 *
24 * ===========================================================================
25 *
26 * File Name: drawing.c
27 *
28 * Author: Jonathan Kans, Alex Smirnov, Jill Shermer, Denis Vakatov
29 *
30 * Version Creation Date: 11/13/92
31 *
32 * $Revision: 6.16 $
33 *
34 * File Description:
35 *
36 * Modifications:
37 * --------------------------------------------------------------------------
38 * $Log: drawing.c,v $
39 * Revision 6.16 2003/03/18 17:00:10 kans
40 * Nlm_AddSilentSegRect does not absorb clicks, SegRect reverted to absorb clicks, so desktop click responsiveness is maintained
41 *
42 * Revision 6.15 2003/02/19 17:36:19 rsmith
43 * SegRect (borders around a SegmenT) can not longer absorb clicks.
44 *
45 * Revision 6.14 2001/12/13 14:51:31 kans
46 * DrawSegment calls SetPrimAttribute only if it will be drawing
47 *
48 * Revision 6.13 2000/10/25 20:47:17 vakatov
49 * Rollback R6.10 (still may need add. fix for MS-Windows) [w/ V.Chetvernin]
50 *
51 * Revision 6.12 1999/10/04 17:16:30 kans
52 * include ncbidraw.h instead of vibrant.h, a couple Nlm_ prefixes
53 *
54 * Revision 6.11 1998/07/01 18:27:39 vakatov
55 * Use "const" qualifier somewhere
56 *
57 * Revision 6.10 1998/06/25 18:41:12 vakatov
58 * s_DoRoundRect(): oval_[hc] -- multiply by 2 when using Paint/FrameRoundRect
59 *
60 * Revision 6.9 1998/06/15 22:07:44 vakatov
61 * RecDrawProc(), RoRecDrawProc() -- do not add extra pixel to the
62 * horiz. and vert. dimensions; thus get it in-sync with other primitives
63 *
64 * Revision 6.8 1998/06/01 17:29:18 vakatov
65 * Extended rounded rect. options -- let it roundup only two(adjacent)
66 * corners(see "flags" arg in Nlm_AddRoundedRectangle())
67 *
68 * Revision 6.7 1998/04/27 16:03:57 vakatov
69 * Added rounded rectangles
70 * Re-implemented the ovals -- dont emulate them by polygons anymore,
71 * use the "native" drawing functions instead
72 *
73 * Revision 6.6 1997/12/16 18:38:39 kans
74 * sentinel draw callback has draw info context parameter
75 *
76 * Revision 6.5 1997/12/15 18:10:46 kans
77 * added cleanup data function to sentinel
78 *
79 * Revision 6.4 1997/11/19 17:38:09 kans
80 * added ChangeSentinelRectangle
81 *
82 * Revision 6.3 1997/11/13 21:41:31 vakatov
83 * Added "sentinel rectangle" primitive[Nlm_AddSntRectangle] which
84 * calls its callback procedure[Nlm_SntOnDrawProc] on each redraw
85 *
86 * Revision 6.2 1997/10/30 20:01:40 vakatov
87 * Added Nlm_PrimitiveBox()
88 *
89 * Revision 6.1 1997/09/16 18:56:54 vakatov
90 * RecDrawProc(): setup WIDTH_ATT for non-filled rectangle
91 *
92 * Revision 5.4 1997/07/23 19:48:54 vakatov
93 * Use Nlm_PaintStringEx function where non-display HDC can be used
94 * (on MS-Win, MoveToEx()/GetCurrentPositionEx() don't work in this case)
95 *
96 * Revision 5.3 1997/05/08 14:05:21 vakatov
97 * [WIN_MSWIN] PaintStringWin() is obsolete; replaced by MoveTo + PaintString
98 *
99 * Revision 5.2 1996/11/07 15:06:06 kans
100 * extra break needed
101 *
102 * Revision 5.1 1996/11/05 22:30:11 vakatov
103 * MakeAlignRect()/...Box(): Made the alignment be UPPER_LEFT by default
104 *
105 * Revision 4.7 1996/03/21 21:05:23 vakatov
106 * Arrow-rectangle FRAME_PRIMITIVE highlighting now merely
107 * draw a box embracing RECTANGLE or LINE primitive
108 *
109 * Revision 4.6 1996/03/15 19:49:52 vakatov
110 * Arrow-rectangle FRAME_PRIMITIVE highlighting corrected
111 *
112 * Revision 4.5 1995/11/17 20:44:48 smirnov
113 * Alex: fix DrawArc function.
114 *
115 * Revision 4.4 1995/11/09 16:35:55 kans
116 * removed static from AddArc
117 *
118 * Revision 4.3 1995/11/07 23:21:53 kans
119 * moved Nlm_DrawSegment from viewer.c to drawing.c (for GIF without Vibrant)
120 *
121 * Revision 4.1 1995/09/12 00:39:10 ostell
122 * changes for text to appear in windows metafiles
123 *
124 * ==========================================================================
125 */
126
127 #ifndef _NCBIDRAW_
128 #include <ncbidraw.h>
129 #endif
130
131 #ifndef _PICTURE_
132 #include <picture.h>
133 #endif
134
135 #ifndef _PICTUREP_
136 #include <picturep.h>
137 #endif
138
139 #ifndef _MAPPINGP_
140 #include <mappingp.h>
141 #endif
142
143 #ifndef _DRAWINGP_
144 #include <drawingp.h>
145 #endif
146
147 #ifndef _VIEWERP_
148 #include <viewerp.h>
149 #endif
150
151 /*****************************************************************************
152 *
153 * DEFINES
154 *
155 *****************************************************************************/
156 #define ARROWWIDTH2 36
157
158 /*****************************************************************************
159 *
160 * EXTERNAL VARIABLES
161 *
162 *****************************************************************************/
163 FonT smallFont = NULL;
164 FonT mediumFont = NULL;
165 FonT largeFont = NULL;
166
167 AttPData blackAttPData =
168 { {0,0,0}, SOLID_LINE, SOLID_SHADING, STD_PEN_WIDTH, COPY_MODE };
169 AttPData whiteAttPData =
170 { {255,255,255}, SOLID_LINE, SOLID_SHADING, STD_PEN_WIDTH, COPY_MODE };
171
172 /*****************************************************************************
173 *
174 * STATIC VARIABLES
175 *
176 *****************************************************************************/
177 static Int1 sin100[91] = {
178 0,2,3,5,7,9,10,12,14,16,17,19,21,22,24,26,28,29,31,33,34,36,37,39,41,42,
179 44,45,47,48,50,51,53,54,56,57,59,60,62,63,64,66,67,68,69,71,72,73,74,75,
180 77,78,79,80,81,82,83,84,85,86,87,87,88,89,90,91,91,92,93,93,94,95,95,96,
181 96,97,97,97,98,98,98,99,99,99,99,100,100,100,100,100,100 };
182
183 static Int1 atan100[101] = {
184 0,1,1,2,2,3,3,4,5,5,6,6,7,7,8,9,9,10,10,11,11,12,12,13,13,14,15,15,16,16,17,
185 17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,27,28,28,29,
186 29,30,30,31,31,31,32,32,33,33,33,34,34,35,35,35,36,36,37,37,37,38,38,38,39,
187 39,39,40,40,40,41,41,41,42,42,42,43,43,43,44,44,44,44,45,45 };
188
189 static PoinT polyPoints[362];
190
191 static Uint1 thinNews [] = {
192 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88
193 };
194 static Uint1 thinNwse [] = {
195 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11
196 };
197 static Uint1 thickNews [] = {
198 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC, 0x99
199 };
200 static Uint1 thickNwse [] = {
201 0x99, 0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33
202 };
203 static Uint1 thinHoriz [] = {
204 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00
205 };
206 static Uint1 thinVert [] = {
207 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
208 };
209 static Uint1 thickHoriz [] = {
210 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00
211 };
212 static Uint1 thickVert [] = {
213 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33
214 };
215
216 #ifdef WIN_MAC
217 static Int1 userArrowSize = 10;
218 #endif
219 #ifdef WIN_MSWIN
220 static Int1 userArrowSize = 7;
221 #endif
222 #ifdef WIN_MOTIF
223 static Int1 userArrowSize = 10;
224 #endif
225
226 /*****************************************************************************
227 *
228 * SetXXXFont (void)
229 * Creates fonts of various sizes.
230 *
231 *****************************************************************************/
232
233 FonT SetSmallFont (void)
234
235 {
236 if (smallFont == NULL) {
237 #ifdef WIN_MAC
238 smallFont = ParseFont ("Monaco,9");
239 #endif
240 #ifdef WIN_MSWIN
241 smallFont = ParseFont ("Courier,9");
242 #endif
243 #ifdef WIN_MOTIF
244 smallFont = ParseFont ("Courier,12");
245 #endif
246 }
247 return smallFont;
248 }
249
250 FonT SetMediumFont (void)
251
252 {
253 if (mediumFont == NULL) {
254 #ifdef WIN_MAC
255 mediumFont = ParseFont ("Monaco,12");
256 #endif
257 #ifdef WIN_MSWIN
258 mediumFont = ParseFont ("Courier,12");
259 #endif
260 #ifdef WIN_MOTIF
261 mediumFont = ParseFont ("Courier,14");
262 #endif
263 }
264 return mediumFont;
265 }
266
267 FonT SetLargeFont (void)
268
269 {
270 if (largeFont == NULL) {
271 #ifdef WIN_MAC
272 largeFont = ParseFont ("Monaco,18");
273 #endif
274 #ifdef WIN_MSWIN
275 largeFont = ParseFont ("Courier,18");
276 #endif
277 #ifdef WIN_MOTIF
278 largeFont = ParseFont ("Courier,18");
279 #endif
280 }
281 return largeFont;
282 }
283
284 /*****************************************************************************
285 *
286 * DISPATCHERS FOR GENERIC PRIMITIVE OPERATIONS
287 *
288 *****************************************************************************/
289
290 /*****************************************************************************
291 *
292 * GetPrimDrawAttribute (primdrawcontect, ...)
293 * helper function for PrimDrawProc
294 *
295 *****************************************************************************/
296
297 void Nlm_GetPrimDrawAttribute (PrimitivE prim,
298 Uint1Ptr color, Int1Ptr plinestyle,
299 Int1Ptr pshading, Int1Ptr ppenwidth,
300 Int1Ptr pmode, Int1Ptr phighlight)
301 {
302 AttPData* atts;
303
304 if (prim != NULL ) {
305 atts = &(((GenPPtr)prim)->att);
306 if (color != NULL) {
307 color[0] = atts->color[0];
308 color[1] = atts->color[1];
309 color[2] = atts->color[2];
310 }
311 if (plinestyle != NULL) *plinestyle = atts->linestyle;
312 if (pshading != NULL) *pshading = atts->shading;
313 if (ppenwidth != NULL) *ppenwidth = atts->penwidth;
314 if (pmode != NULL) *pmode = atts->mode;
315 if (phighlight != NULL) *phighlight = ((GenPPtr)prim)->highlight;
316 }
317 }
318
319 /*****************************************************************************
320 *
321 * HELPER FUNCTIONS
322 *
323 *****************************************************************************/
324 Nlm_BoxPtr Nlm_GetWorldWindow (Nlm_PrimDrawContext pdc) {
325 if ( pdc != NULL ){
326 return ( &(((DrawInfoPtr)pdc)->scale.worldWindow) );
327 }
328 return NULL;
329 }
330
331 Int4 Nlm_GetScaleX (PrimDrawContext pdc){
332 if ( pdc != NULL ){
333 return ( ((DrawInfoPtr)pdc)->scale.scaleX );
334 }
335 return 0;
336 }
337
338 Int4 Nlm_GetScaleY (Nlm_PrimDrawContext pdc){
339 if ( pdc != NULL ){
340 return ( ((DrawInfoPtr)pdc)->scale.scaleY );
341 }
342 return 0;
343 }
344
345 Int4 Nlm_GetOffsetX (PrimDrawContext pdc){
346 if ( pdc != NULL ){
347 return ( ((DrawInfoPtr)pdc)->scale.offsetX );
348 }
349 return 0;
350 }
351
352 Int4 Nlm_GetOffsetY (PrimDrawContext pdc){
353 if ( pdc != NULL ){
354 return ( ((DrawInfoPtr)pdc)->scale.offsetY );
355 }
356 return 0;
357 }
358
359 Boolean Nlm_isPrimInWindow (PrimDrawContext pdc){
360 if ( pdc != NULL ){
361 return ( ((DrawInfoPtr)pdc)->checked );
362 }
363 return FALSE;
364 }
365
366 Int1 Nlm_GetPrimHligh (PrimDrawContext pdc){
367 if ( pdc != NULL ){
368 return ( ((DrawInfoPtr)pdc)->highlight );
369 }
370 return PLAIN_SEGMENT;
371 }
372
373 BoxPtr Nlm_GetHitWindow (PrimHitContext phc){
374 if ( phc != NULL ){
375 return ( &(((ScalePtr)phc)->worldWindow) );
376 }
377 return NULL;
378 }
379
380 void Nlm_SetPrimAttribute (PrimDrawContext pdc, Nlm_Uint1 flags ){
381 AttPPtr atts;
382
383 if (pdc != NULL) {
384 atts = ((DrawInfoPtr)pdc)->primattrib;
385 if ( flags & COLOR_ATT ) {
386 SelectColor (atts->color [0], atts->color [1], atts->color [2]);
387 }
388 if ( flags & WIDTH_ATT ){
389 WidePen (atts->penwidth);
390 }
391 if ( flags & STYLE_ATT ) {
392 switch (atts->linestyle) {
393 case SOLID_LINE :
394 Solid ();
395 break;
396 case DOTTED_LINE :
397 Dotted ();
398 break;
399 case DASHED_LINE :
400 Dashed ();
401 }
402 }
403 if ( flags & SHADING_ATT ) {
404 switch (atts->shading) {
405 case SOLID_SHADING :
406 Solid ();
407 break;
408 case DARK_SHADING :
409 Dark ();
410 break;
411 case MEDIUM_SHADING :
412 Medium ();
413 break;
414 case LIGHT_SHADING :
415 Light ();
416 break;
417 case EMPTY_SHADING :
418 Empty ();
419 break;
420 case THIN_HORIZ_SHADING :
421 SetPenPattern (thinHoriz);
422 break;
423 case THIN_VERT_SHADING :
424 SetPenPattern (thinVert);
425 break;
426 case THICK_HORIZ_SHADING :
427 SetPenPattern (thickHoriz);
428 break;
429 case THICK_VERT_SHADING :
430 SetPenPattern (thickVert);
431 break;
432 case THIN_NESW_SHADING :
433 SetPenPattern (thinNews);
434 break;
435 case THIN_NWSE_SHADING :
436 SetPenPattern (thinNwse);
437 break;
438 case THICK_NESW_SHADING :
439 SetPenPattern (thickNews);
440 break;
441 case THICK_NWSE_SHADING :
442 SetPenPattern (thickNwse);
443 }
444 }
445 if ( flags & MODE_ATT ) {
446 switch (atts->mode) {
447 case COPY_MODE :
448 CopyMode ();
449 break;
450 case MERGE_MODE :
451 MergeMode ();
452 break;
453 case INVERT_MODE :
454 InvertMode ();
455 break;
456 case ERASE_MODE :
457 EraseMode ();
458 }
459 }
460 }
461 }
462
463 void Nlm_RestorePrimAttribute (PrimDrawContext pdc){
464 Nlm_SetPrimAttribute (pdc, (Uint1)0xFF);
465 }
466
467 /*****************************************************************************
468 *
469 * OPERATIONS ON PRIMITIVES
470 *
471 *****************************************************************************/
472 /*****************************************************************************
473 *
474 * Set Arrow Size
475 *
476 *****************************************************************************/
477 void Nlm_SetDefArrowSize ( Int1 arrowSize )
478 {
479 if ( arrowSize < 4 ) arrowSize = 4;
480 if ( arrowSize > 16 ) arrowSize = 16;
481 userArrowSize = arrowSize;
482 }
483
484 static void MakeAlignRect ( Int2 x, Int2 y, Int2 width, Int2 height,
485 Int2 offset, Int2 align, RectPtr rPtr )
486 {
487 RecT r;
488
489 switch (align) {
490 case UPPER_CENTER :
491 r.left = x - (width>>1); r.top = y - height - offset;
492 break;
493 case UPPER_RIGHT :
494 r.left = x + offset; r.top = y - height - offset;
495 break;
496 case MIDDLE_LEFT :
497 r.left = x - width - offset; r.top = y - (height>>1);
498 break;
499 case MIDDLE_CENTER :
500 r.left = x - (width>>1); r.top = y - (height>>1);
501 break;
502 case MIDDLE_RIGHT :
503 r.left = x + offset; r.top = y - (height>>1);
504 break;
505 case LOWER_LEFT :
506 r.left = x - width - offset; r.top = y + offset;
507 break;
508 case LOWER_CENTER :
509 r.left = x - (width>>1); r.top = y + offset;
510 break;
511 case LOWER_RIGHT :
512 r.left = x + offset; r.top = y + offset;
513 break;
514 case UPPER_LEFT :
515 default:
516 r.left = x - width - offset; r.top = y - height - offset;
517 break;
518 }
519 r.right = r.left + width; r.bottom = r.top + height;
520 *rPtr = r;
521 }
522
523 static void MakeAlignBox ( Int4 x, Int4 y, Int4 width, Int4 height,
524 Int4 offsetX, Int4 offsetY, Int2 align,
525 BoxPtr boxPtr )
526 {
527 BoxInfo box;
528
529 switch (align) {
530 case UPPER_CENTER :
531 box.left = x - (width>>1); box.top = y + height + offsetY;
532 break;
533 case UPPER_RIGHT :
534 box.left = x + offsetX; box.top = y + height + offsetY;
535 break;
536 case MIDDLE_LEFT :
537 box.left = x - width - offsetX; box.top = y + (height>>1);
538 break;
539 case MIDDLE_CENTER :
540 box.left = x - (width>>1); box.top = y + (height>>1);
541 break;
542 case MIDDLE_RIGHT :
543 box.left = x + offsetX; box.top = y + (height>>1);
544 break;
545 case LOWER_LEFT :
546 box.left = x - width - offsetX; box.top = y - offsetY;
547 break;
548 case LOWER_CENTER :
549 box.left = x - (width>>1); box.top = y - offsetY;
550 break;
551 case LOWER_RIGHT :
552 box.left = x + offsetX; box.top = y - offsetY;
553 break;
554 case UPPER_LEFT :
555 default:
556 box.left = x - width - offsetX; box.top = y + height + offsetY;
557 break;
558 }
559 box.right = box.left + width; box.bottom = box.top - height;
560 *boxPtr = box;
561 }
562
563 /*****************************************************************************
564 *
565 * DrawPrimitive (item, scale)
566 * Draws a primitive
567 *
568 *****************************************************************************/
569
570 void Nlm_DrawPrimitive (BasePPtr item, DrawInfoPtr drawinfo)
571 {
572 PrimDefPtr pdp;
573
574 if (item != NULL && drawinfo != NULL) {
575 switch (item->code) {
576 case GENERIC :
577 pdp = ((GenPPtr)item)->pdp;
578 if ( pdp != NULL && pdp->draw != NULL) {
579 pdp->draw ( &(((GenPPtr)item)->data), (PrimDrawContext)drawinfo);
580 }
581 break;
582 default :
583 Message (MSG_ERROR, "DrawPrimitive item unknown");
584 break;
585 }
586 }
587 }
588
589 /*****************************************************************************
590 *
591 * PrimitiveIsCloseToPoint (item, &id)
592 *
593 *****************************************************************************/
594
595 Boolean Nlm_PrimitiveIsCloseToPoint (BasePPtr item, ScalePtr scale )
596 {
597 PrimDefPtr pdp;
598
599 if (item != NULL && scale != NULL) {
600 switch (item->code) {
601 case GENERIC :
602 pdp = ((GenPPtr)item)->pdp;
603 if ( pdp != NULL && pdp->hittest != NULL) {
604 return pdp->hittest ( &(((GenPPtr)item)->data),
605 (PrimHitContext)scale);
606 }
607 break;
608 default :
609 Message (MSG_ERROR, "PrimitiveIsCloseToPoint item unknown");
610 break;
611 }
612 }
613 return FALSE;
614 }
615
616 /*****************************************************************************
617 *
618 * TryHighlightPrimitive (item, highlight)
619 *
620 *****************************************************************************/
621
622 Boolean Nlm_TryHighlightPrimitive (BasePPtr item, Int1 highlight)
623 {
624 if (item != NULL) {
625 switch (item->code) {
626 case GENERIC :
627 ((GenPPtr)item)->highlight = highlight;
628 return TRUE;
629 default:
630 Message (MSG_ERROR, "TryHighlightPrimitive item unknown");
631 break;
632 }
633 }
634 return FALSE;
635 }
636
637 /*****************************************************************************
638 *
639 * TryOffsetPrimitive (item, deltaX, deltaY)
640 *
641 *****************************************************************************/
642
643 Boolean Nlm_TryOffsetPrimitive (BasePPtr item, Int4 deltaX, Int4 deltaY)
644 {
645 PrimDefPtr pdp;
646
647 if (item != NULL) {
648 switch (item->code) {
649 case GENERIC :
650 pdp = ((GenPPtr)item)->pdp;
651 if ( pdp != NULL && pdp->offset != NULL) {
652 return pdp->offset ( &(((GenPPtr)item)->data), deltaX, deltaY);
653 }
654 break;
655 default:
656 Message (MSG_ERROR, "TryOffsetPrimitive item unknown");
657 break;
658 }
659 }
660 return FALSE;
661 }
662
663 /*****************************************************************************
664 *
665 * TryGetPrimitiveLimits (item, scaleX, scaleY, pLimits)
666 *
667 *****************************************************************************/
668 Nlm_Boolean Nlm_TryGetPrimitiveLimits (Nlm_BasePPtr item, Nlm_Int4 scaleX,
669 Nlm_Int4 scaleY, Nlm_BoxPtr pLimits)
670 {
671 PrimDefPtr pdp;
672
673 if (item != NULL) {
674 switch (item->code) {
675 case GENERIC :
676 pdp = ((GenPPtr)item)->pdp;
677 if ( pdp != NULL && pdp->getlimits != NULL) {
678 return pdp->getlimits ( &(((GenPPtr)item)->data), scaleX, scaleY,
679 pLimits );
680 }
681 break;
682 default:
683 Message (MSG_ERROR, "TryOffsetPrimitive item unknown");
684 break;
685 }
686 }
687 return FALSE;
688 }
689
690 extern Nlm_Boolean Nlm_PrimitiveBox(Nlm_PrimitivE prim,
691 Nlm_Int4 scaleX, Nlm_Int4 scaleY,
692 Nlm_BoxPtr pBox) {
693 return Nlm_TryGetPrimitiveLimits((Nlm_BasePPtr)prim, scaleX, scaleY, pBox);
694 }
695
696
697 /*****************************************************************************
698 *
699 * CleanupPrimitive (item)
700 * Deleted all data, owned by primitive
701 *
702 *****************************************************************************/
703
704 void Nlm_CleanupPrimitive (BasePPtr item)
705 {
706 PrimDefPtr pdp;
707
708 if (item != NULL) {
709 switch (item->code) {
710 case GENERIC :
711 pdp = ((GenPPtr)item)->pdp;
712 if ( pdp != NULL && pdp->cleanup != NULL) {
713 pdp->cleanup ( &(((GenPPtr)item)->data) );
714 }
715 break;
716 default:
717 Message (MSG_ERROR, "CleanupPrimitive item unknown");
718 break;
719 }
720 }
721 }
722
723 /*****************************************************************************
724 *
725 * PRIMITIVES
726 *
727 *****************************************************************************/
728
729 /*****************************************************************************
730 *
731 * INVISIBLE FRAME
732 *
733 *****************************************************************************/
734
735 typedef struct frampdata {
736 BoxInfo box;
737 } FramPData, PNTR FramPDataPtr;
738
739 static Boolean FramHitTestProc ( FramPDataPtr pdata, PrimHitContext phc)
740 {
741 register ScalePtr dInfoPtr;
742
743 dInfoPtr = (ScalePtr)phc;
744 if ( (pdata->box.left < dInfoPtr->worldWindow.right) &&
745 (pdata->box.right > dInfoPtr->worldWindow.left) &&
746 (pdata->box.top > dInfoPtr->worldWindow.bottom) &&
747 (pdata->box.bottom < dInfoPtr->worldWindow.top) ) return TRUE;
748 return FALSE;
749 }
750
751 static Boolean FramOffsetProc ( FramPDataPtr pdata, Int4 deltaX,
752 Int4 deltaY )
753 {
754 pdata->box.left += deltaX;
755 pdata->box.right += deltaX;
756 pdata->box.top += deltaY;
757 pdata->box.bottom += deltaY;
758 return TRUE;
759 }
760
761 static Boolean FramGetLimitsProc ( FramPDataPtr pdata, Int4 scaleX,
762 Int4 scaleY, BoxPtr pLimits )
763 {
764 *pLimits = pdata->box;
765 return TRUE;
766 }
767
768 static PrimDef framPrimDef = {
769 (PrimDrawProc) NULL,
770 (PrimHitTestProc) FramHitTestProc,
771 (PrimOffsetProc) FramOffsetProc,
772 (PrimCleanupProc) NULL,
773 (PrimGetLimitsProc) FramGetLimitsProc
774 };
775
776 /*****************************************************************************
777 *
778 * AddInvFrame (parent, left, top, right, bottom, primID)
779 *
780 *****************************************************************************/
781
782 PrimitivE AddInvFrame (SegmenT parent, Int4 left, Int4 top, Int4 right,
783 Int4 bottom, Uint2 primID)
784 {
785 FramPData data;
786 Int4 swap;
787
788 if (left > right) {
789 swap = left;
790 left = right;
791 right = swap;
792 }
793 if (bottom > top) {
794 swap = bottom;
795 bottom = top;
796 top = swap;
797 }
798 data.box.left = left;
799 data.box.top = top;
800 data.box.right = right;
801 data.box.bottom = bottom;
802 return AddPrimitive (&framPrimDef, parent, primID, (VoidPtr)&data,
803 sizeof(FramPData));
804 }
805
806
807 /*****************************************************************************
808 *
809 * RECTANGLE
810 *
811 *****************************************************************************/
812
813 typedef struct recpdata {
814 BoxInfo box;
815 Int2 arrow;
816 Int1 arrowSize;
817 Boolean fill;
818 } RecPData, PNTR RecPDataPtr;
819
820
821 static void RecDrawProc (RecPDataPtr pdata, PrimDrawContext pdc)
822 {
823 register DrawInfoPtr dInfoPtr = (DrawInfoPtr)pdc;
824 BoxInfo tmpBox;
825 RecT r;
826 Int4 curScale;
827 PoinT pts [3];
828 Int1 arrowSize;
829 Boolean vis = TRUE;
830 RecT rect;
831
832 tmpBox = pdata->box;
833 if ( (tmpBox.left > dInfoPtr->scale.worldWindow.right ) ||
834 (tmpBox.right < dInfoPtr->scale.worldWindow.left ) ||
835 (tmpBox.top < dInfoPtr->scale.worldWindow.bottom) ||
836 (tmpBox.bottom > dInfoPtr->scale.worldWindow.top ) )
837 return;
838
839 if ( dInfoPtr->checked == FALSE ) {
840 if ( tmpBox.left < dInfoPtr->scale.worldWindow16.left )
841 tmpBox.left = dInfoPtr->scale.worldWindow16.left;
842 if ( tmpBox.right > dInfoPtr->scale.worldWindow16.right )
843 tmpBox.right = dInfoPtr->scale.worldWindow16.right;
844 if ( tmpBox.top > dInfoPtr->scale.worldWindow16.top )
845 tmpBox.top = dInfoPtr->scale.worldWindow16.top;
846 if ( tmpBox.bottom < dInfoPtr->scale.worldWindow16.bottom )
847 tmpBox.bottom = dInfoPtr->scale.worldWindow16.bottom;
848 }
849
850 arrowSize = pdata->arrowSize;
851 curScale = dInfoPtr->scale.scaleX;
852 r.left = (Int2)((dInfoPtr->scale.offsetX + tmpBox.left ) / curScale);
853 r.right = (Int2)((dInfoPtr->scale.offsetX + tmpBox.right) / curScale);
854 curScale = dInfoPtr->scale.scaleY;
855 r.top = (Int2)((dInfoPtr->scale.offsetY - tmpBox.top ) / curScale);
856 r.bottom = (Int2)((dInfoPtr->scale.offsetY - tmpBox.bottom) / curScale);
857
858 /* calculate vertexes */
859 rect = r;
860
861 switch ( pdata->arrow )
862 {
863 Int2 oldPoint;
864
865 case LEFT_ARROW :
866 oldPoint = r.left;
867 if (r.right - r.left > (Int2)arrowSize) r.left += (Int2)arrowSize;
868 else r.left += (Int2)(arrowSize>>1);
869 pts[0].x = r.left; pts[0].y = r.bottom + (Int2)2;
870 pts[1].x = oldPoint; pts[1].y = (r.bottom + r.top)>>1;
871 pts[2].x = r.left; pts[2].y = r.top - (Int2)2;
872 if (r.right < r.left)
873 {
874 vis = FALSE;
875 rect.left = pts[1].x;
876 rect.right = pts[0].x;
877 }
878 break;
879
880 case RIGHT_ARROW :
881 oldPoint = r.right;
882 if (r.right - r.left >= arrowSize) r.right -= (Int2)arrowSize;
883 else r.right -= (Int2)(arrowSize>>1);
884 if ( r.right < r.left ) vis = FALSE;
885 pts[0].x = r.right; pts[0].y = r.bottom + (Int2)2;
886 pts[1].x = oldPoint; pts[1].y = (r.bottom + r.top)>>1;
887 pts[2].x = r.right; pts[2].y = r.top - (Int2)2;
888 if (r.right < r.left)
889 {
890 vis = FALSE;
891 rect.left = pts[0].x;
892 rect.right = pts[1].x;
893 }
894 break;
895
896 case UP_ARROW :
897 oldPoint = r.top;
898 if (r.bottom - r.top >= (Int2)arrowSize) r.top += (Int2)arrowSize;
899 else r.top += (Int2)(arrowSize>>1);
900 if ( r.bottom < r.top ) vis = FALSE;
901 pts[0].x = r.right + (Int2)2; pts[0].y = r.top;
902 pts[1].x = (r.right+r.left)>>1; pts[1].y = oldPoint;
903 pts[2].x = r.left - (Int2)2; pts[2].y = r.top;
904 if (r.right < r.left)
905 {
906 vis = FALSE;
907 rect.top = pts[1].y;
908 rect.bottom = pts[0].y;
909 }
910 break;
911
912 case DOWN_ARROW :
913 oldPoint = r.bottom;
914 if (r.bottom - r.top >= (Int2)arrowSize) r.bottom -= (Int2)arrowSize;
915 else r.bottom -= (Int2)(arrowSize>>1);
916 if ( r.bottom < r.top ) vis = FALSE;
917 pts[0].x = r.right + (Int2)2; pts[0].y = r.bottom;
918 pts[1].x = (r.right+r.left)>>1; pts[1].y = oldPoint;
919 pts[2].x = r.left - (Int2)2; pts[2].y = r.bottom;
920 if (r.right < r.left)
921 {
922 vis = FALSE;
923 rect.top = pts[0].y;
924 rect.bottom = pts[1].y;
925 }
926 break;
927 }
928
929 SetPrimAttribute (pdc, COLOR_ATT|SHADING_ATT|MODE_ATT);
930 if ( !pdata->fill )
931 SetPrimAttribute (pdc, WIDTH_ATT);
932
933 /* draw arrow */
934 if (pdata->arrow != NO_ARROW)
935 {
936 if (pdata->fill)
937 PaintPoly (3, pts);
938 else
939 FramePoly (3, pts);
940
941 if (dInfoPtr->highlight == FILL_PRIMITIVE)
942 PaintPoly(3, pts);
943 }
944
945 /* draw rectangle */
946 if ( vis ) {
947 if ( pdata->fill )
948 PaintRect( &r );
949 else
950 FrameRect( &r );
951 }
952
953 /* highlighting */
954 switch ( dInfoPtr->highlight )
955 {
956 case PLAIN_PRIMITIVE:
957 break;
958 case FRAME_PRIMITIVE:
959 case OUTLINE_PRIMITIVE:
960 Black();
961 WidePen( 1 );
962 InsetRect(&rect, -3, -3);
963 FrameRect( &rect );
964 InsetRect(&rect, +3, +3);
965 break;
966 case FILL_PRIMITIVE:
967 InsetRect(&rect, -2, -2);
968 PaintRect( &rect );
969 InsetRect(&rect, +2, +2);
970 break;
971 }
972 }
973
974
975 static Boolean RecHitTestProc ( RecPDataPtr pdata, PrimHitContext phc)
976 {
977 register ScalePtr dInfoPtr;
978
979 dInfoPtr = (ScalePtr)phc;
980 if ( (pdata->box.left < dInfoPtr->worldWindow.right) &&
981 (pdata->box.right > dInfoPtr->worldWindow.left) &&
982 (pdata->box.top > dInfoPtr->worldWindow.bottom) &&
983 (pdata->box.bottom < dInfoPtr->worldWindow.top) ) return TRUE;
984 return FALSE;
985 }
986
987 static Boolean RecOffsetProc ( RecPDataPtr pdata, Int4 deltaX,
988 Int4 deltaY )
989 {
990 pdata->box.left += deltaX;
991 pdata->box.right += deltaX;
992 pdata->box.top += deltaY;
993 pdata->box.bottom += deltaY;
994 return TRUE;
995 }
996
997 static Boolean RecGetLimitsProc ( RecPDataPtr pdata, Int4 scaleX,
998 Int4 scaleY, BoxPtr pLimits )
999 {
1000 Int4 arrowSize;
1001
1002 *pLimits = pdata->box;
1003 switch ( pdata->arrow ){
1004 case LEFT_ARROW :
1005 arrowSize = pdata->arrowSize*scaleX/2;
1006 if ( pLimits->right - pLimits->left < arrowSize )
1007 pLimits->right = pLimits->left + arrowSize;
1008 break;
1009 case RIGHT_ARROW :
1010 arrowSize = pdata->arrowSize*scaleX/2;
1011 if ( pLimits->right - pLimits->left < arrowSize )
1012 pLimits->left = pLimits->right - arrowSize;
1013 break;
1014 case UP_ARROW :
1015 arrowSize = pdata->arrowSize*scaleY/2;
1016 if ( pLimits->top - pLimits->bottom < arrowSize )
1017 pLimits->bottom = pLimits->top - arrowSize;
1018 break;
1019 case DOWN_ARROW :
1020 arrowSize = pdata->arrowSize*scaleY/2;
1021 if ( pLimits->top - pLimits->bottom < arrowSize )
1022 pLimits->top = pLimits->bottom + arrowSize;
1023 }
1024 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
1025 return TRUE;
1026 }
1027
1028 static PrimDef recPrimDef = {
1029 (PrimDrawProc) RecDrawProc,
1030 (PrimHitTestProc) RecHitTestProc,
1031 (PrimOffsetProc) RecOffsetProc,
1032 (PrimCleanupProc) NULL,
1033 (PrimGetLimitsProc) RecGetLimitsProc
1034 };
1035
1036 /*****************************************************************************
1037 *
1038 * AddRectangle (parent, left, top, right, bottom, arrow, fill, primID)
1039 *
1040 *****************************************************************************/
1041
1042 PrimitivE AddRectangle (SegmenT parent, Int4 left, Int4 top, Int4 right,
1043 Int4 bottom, Int2 arrow, Boolean fill, Uint2 primID)
1044 {
1045 RecPData data;
1046 Int4 swap;
1047
1048 if (left > right) {
1049 swap = left;
1050 left = right;
1051 right = swap;
1052 }
1053 if (bottom > top) {
1054 swap = bottom;
1055 bottom = top;
1056 top = swap;
1057 }
1058 data.box.left = left;
1059 data.box.top = top;
1060 data.box.right = right;
1061 data.box.bottom = bottom;
1062 data.fill = fill;
1063 data.arrow = arrow;
1064 data.arrowSize = userArrowSize;
1065 return AddPrimitive (&recPrimDef, parent, primID, (VoidPtr)&data,
1066 sizeof(RecPData));
1067 }
1068
1069
1070 /*****************************************************************************
1071 *
1072 * ROUNDED RECTANGLE
1073 *
1074 *****************************************************************************/
1075
1076 typedef struct {
1077 BoxInfo box;
1078 Int4 oval_w;
1079 Int4 oval_h;
1080 Boolean fill;
1081 Uint4 flags;
1082 } RoRecPData, PNTR RoRecPDataPtr;
1083
1084
1085 static void s_DoRoundRect(RectPtr r,
1086 Int2 oval_w, Int2 oval_h, Boolean fill, Uint4 flags)
1087 {
1088 Int2 W, dW, H, dH;
1089 RecT r1, r2, qr1, qr2;
1090 EQuadrant q1, q2;
1091 PoinT p1, p2;
1092
1093 if (!flags ||
1094 (flags & ROREC_TOP && flags & ROREC_BOTTOM) ||
1095 (flags & ROREC_LEFT && flags & ROREC_RIGHT)) {
1096 if ( fill )
1097 PaintRoundRect(r, oval_w, oval_h);
1098 else
1099 FrameRoundRect(r, oval_w, oval_h);
1100 return;
1101 }
1102
1103 W = r->right - r->left;
1104 H = r->bottom - r->top;
1105 LoadRect(&r1, 0, 0, 0, 0);
1106 LoadRect(&r2, 0, 0, 0, 0);
1107
1108 if (flags & ROREC_TOP || flags & ROREC_BOTTOM) {
1109 if (2 * oval_w > W)
1110 oval_w = W / 2;
1111 dW = W - 2 * oval_w;
1112
1113 if (oval_h > H)
1114 oval_h = H;
1115 dH = H - oval_h;
1116 }
1117 else { /* ROREC_LEFT || ROREC_RIGHT */
1118 if (2 * oval_h > H)
1119 oval_h = H / 2;
1120 dH = H - 2 * oval_h;
1121
1122 if (oval_w > W)
1123 oval_w = W;
1124 dW = W - oval_w;
1125 }
1126
1127 if (oval_w < 2 || oval_h < 2) {
1128 if ( fill )
1129 PaintRect(r);
1130 else
1131 FrameRect(r);
1132 return;
1133 }
1134
1135
1136 if (flags & ROREC_TOP || flags & ROREC_BOTTOM) {
1137 if (flags & ROREC_TOP) {
1138 if ( dW )
1139 LoadRect(&r1, (Int2)(r->left + oval_w), r->top,
1140 (Int2)(r->right - oval_w), (Int2)(r->top + oval_h));
1141 if ( dH )
1142 LoadRect(&r2, r->left, (Int2)(r->top + oval_h),
1143 r->right, r->bottom);
1144 q1 = eQ_LeftTop;
1145 LoadRect(&qr1, r->left, r->top,
1146 (Int2)(r->left + oval_w), (Int2)(r->top + oval_h));
1147 q2 = eQ_RightTop;
1148 LoadRect(&qr2, (Int2)(r->right - oval_w), r->top,
1149 r->right, (Int2)(r->top + oval_h));
1150
1151 if ( !fill ) {
1152 p1.y = p2.y = r->bottom; p1.x = r->left; p2.x = r->right;
1153 DrawLine(p1, p2);
1154 if ( dW ) {
1155 p1.y = p2.y = r1.top; p1.x = r1.left; p2.x = r1.right;
1156 DrawLine(p1, p2);
1157 }
1158 }
1159 }
1160 else { /* ROREC_BOTTOM */
1161 if ( dW )
1162 LoadRect(&r1, (Int2)(r->left + oval_w), (Int2)(r->bottom - oval_h),
1163 (Int2)(r->right - oval_w), r->bottom);
1164 if ( dH )
1165 LoadRect(&r2, r->left, r->top,
1166 r->right, (Int2)(r->bottom - oval_h));
1167 q1 = eQ_LeftBottom;
1168 LoadRect(&qr1, r->left, r->bottom,
1169 (Int2)(r->left + oval_w), (Int2)(r->bottom - oval_h));
1170 q2 = eQ_RightBottom;
1171 LoadRect(&qr2, (Int2)(r->right - oval_w), r->bottom,
1172 r->right, (Int2)(r->bottom - oval_h));
1173
1174 if ( !fill ) {
1175 p1.y = p2.y = r->top; p1.x = r->left; p2.x = r->right;
1176 DrawLine(p1, p2);
1177 if ( dW ) {
1178 p1.y = p2.y = r->bottom; p1.x = r1.left; p2.x = r1.right;
1179 DrawLine(p1, p2);
1180 }
1181 }
1182 }
1183
1184 if (!fill && dH) {
1185 p1.y = r2.top; p2.y = r2.bottom;
1186
1187 p1.x = p2.x = r->left;
1188 DrawLine(p1, p2);
1189 p1.x = p2.x = r->right;
1190 DrawLine(p1, p2);
1191 }
1192 }
1193
1194 else { /* ROREC_LEFT | ROREC_RIGHT */
1195 if (flags & ROREC_LEFT) {
1196 if ( dH )
1197 LoadRect(&r1, r->left, (Int2)(r->top + oval_h),
1198 (Int2)(r->left + oval_w), (Int2)(r->bottom - oval_h));
1199 if ( dW )
1200 LoadRect(&r2, (Int2)(r->left + oval_w), r->top,
1201 r->right, r->bottom);
1202 q1 = eQ_LeftTop;
1203 LoadRect(&qr1, r->left, r->top,
1204 (Int2)(r->left + oval_w), (Int2)(r->top + oval_h));
1205 q2 = eQ_LeftBottom;
1206 LoadRect(&qr2, r->left, r->bottom,
1207 (Int2)(r->left + oval_w), (Int2)(r->bottom - oval_h));
1208
1209 if ( !fill ) {
1210 p1.x = p2.x = r->right; p1.y = r->top; p2.y = r->bottom;
1211 DrawLine(p1, p2);
1212 if ( dW ) {
1213 p1.x = p2.x = r->left; p1.y = r1.top; p2.y = r1.bottom;
1214 DrawLine(p1, p2);
1215 }
1216 }
1217 }
1218 else { /* ROREC_RIGHT */
1219 if ( dH )
1220 LoadRect(&r1, (Int2)(r->right - oval_w), (Int2)(r->top + oval_h),
1221 r->right, (Int2)(r->bottom - oval_h));
1222 if ( dW )
1223 LoadRect(&r2, r->left, r->top,
1224 (Int2)(r->right - oval_w), r->bottom);
1225 q1 = eQ_RightTop;
1226 LoadRect(&qr1, (Int2)(r->right - oval_w), r->top,
1227 r->right, (Int2)(r->top + oval_h));
1228 q2 = eQ_RightBottom;
1229 LoadRect(&qr2, (Int2)(r->right - oval_w), r->bottom,
1230 r->right, (Int2)(r->bottom - oval_h));
1231
1232 if ( !fill ) {
1233 p1.x = p2.x = r->left; p1.y = r->top; p2.y = r->bottom;
1234 DrawLine(p1, p2);
1235 if ( dW ) {
1236 p1.x = p2.x = r->right; p1.y = r1.top; p2.y = r1.bottom;
1237 DrawLine(p1, p2);
1238 }
1239 }
1240 }
1241
1242 if (!fill && dH) {
1243 p1.x = r2.left; p2.x = r2.right;
1244
1245 p1.y = p2.y = r->top;
1246 DrawLine(p1, p2);
1247 p1.y = p2.y = r->bottom;
1248 DrawLine(p1, p2);
1249 }
1250 }
1251
1252 if ( fill ) {
1253 if ( !EmptyRect(&r1) )
1254 PaintRect(&r1);
1255 if ( !EmptyRect(&r2) )
1256 PaintRect(&r2);
1257 PaintQuadrant(&qr1, q1);
1258 PaintQuadrant(&qr2, q2);
1259 } else {
1260 FrameQuadrant(&qr1, q1);
1261 FrameQuadrant(&qr2, q2);
1262 }
1263 }
1264
1265
1266 static void RoRecDrawProc(RoRecPDataPtr pdata, PrimDrawContext pdc)
1267 {
1268 register DrawInfoPtr dInfoPtr = (DrawInfoPtr)pdc;
1269 BoxInfo tmpBox;
1270 RecT r;
1271 Int4 curScale;
1272 Int2 oval_w, oval_h;
1273
1274 /* check limits */
1275 tmpBox = pdata->box;
1276 if ( (tmpBox.left > dInfoPtr->scale.worldWindow.right ) ||
1277 (tmpBox.right < dInfoPtr->scale.worldWindow.left ) ||
1278 (tmpBox.top < dInfoPtr->scale.worldWindow.bottom) ||
1279 (tmpBox.bottom > dInfoPtr->scale.worldWindow.top ) )
1280 return;
1281
1282 if ( dInfoPtr->checked == FALSE ) {
1283 if ( tmpBox.left < dInfoPtr->scale.worldWindow16.left )
1284 tmpBox.left = dInfoPtr->scale.worldWindow16.left;
1285 if ( tmpBox.right > dInfoPtr->scale.worldWindow16.right )
1286 tmpBox.right = dInfoPtr->scale.worldWindow16.right;
1287 if ( tmpBox.top > dInfoPtr->scale.worldWindow16.top )
1288 tmpBox.top = dInfoPtr->scale.worldWindow16.top;
1289 if ( tmpBox.bottom < dInfoPtr->scale.worldWindow16.bottom )
1290 tmpBox.bottom = dInfoPtr->scale.worldWindow16.bottom;
1291 }
1292
1293 /* scale */
1294 curScale = dInfoPtr->scale.scaleX;
1295 r.left = (Int2)((dInfoPtr->scale.offsetX + tmpBox.left ) / curScale);
1296 r.right = (Int2)((dInfoPtr->scale.offsetX + tmpBox.right) / curScale);
1297 oval_w = (Int2)(pdata->oval_w / curScale);
1298
1299 curScale = dInfoPtr->scale.scaleY;
1300 r.top = (Int2)((dInfoPtr->scale.offsetY - tmpBox.top ) / curScale);
1301 r.bottom = (Int2)((dInfoPtr->scale.offsetY - tmpBox.bottom) / curScale);
1302 oval_h = (Int2)(pdata->oval_h / curScale);
1303
1304 /* attributes */
1305 SetPrimAttribute(pdc, COLOR_ATT|SHADING_ATT|MODE_ATT);
1306 if ( !pdata->fill )
1307 SetPrimAttribute(pdc, WIDTH_ATT);
1308
1309 /* draw */
1310 s_DoRoundRect(&r, oval_w, oval_h, pdata->fill, pdata->flags);
1311
1312 /* highlight */
1313 switch ( dInfoPtr->highlight ) {
1314 case PLAIN_PRIMITIVE:
1315 break;
1316 case FRAME_PRIMITIVE:
1317 case OUTLINE_PRIMITIVE:
1318 Black();
1319 WidePen( 1 );
1320 InsetRect(&r, -3, -3);
1321 s_DoRoundRect(&r, (Int2)(oval_w + 3), (Int2)(oval_h + 3),
1322 FALSE, pdata->flags);
1323 break;
1324 case FILL_PRIMITIVE:
1325 InsetRect(&r, -2, -2);
1326 s_DoRoundRect(&r, (Int2)(oval_w + 3), (Int2)(oval_h + 3),
1327 TRUE, pdata->flags);
1328 break;
1329 }
1330 }
1331
1332
1333 static Boolean RoRecHitTestProc(RoRecPDataPtr pdata, PrimHitContext phc)
1334 {
1335 ScalePtr dInfoPtr = (ScalePtr)phc;
1336
1337 return (Boolean)
1338 ((pdata->box.left < dInfoPtr->worldWindow.right) &&
1339 (pdata->box.right > dInfoPtr->worldWindow.left) &&
1340 (pdata->box.top > dInfoPtr->worldWindow.bottom) &&
1341 (pdata->box.bottom < dInfoPtr->worldWindow.top));
1342 }
1343
1344 static Boolean RoRecOffsetProc(RoRecPDataPtr pdata, Int4 deltaX, Int4 deltaY)
1345 {
1346 pdata->box.left += deltaX;
1347 pdata->box.right += deltaX;
1348 pdata->box.top += deltaY;
1349 pdata->box.bottom += deltaY;
1350 return TRUE;
1351 }
1352
1353 static Boolean RoRecGetLimitsProc(RoRecPDataPtr pdata,
1354 Int4 scaleX, Int4 scaleY, BoxPtr pLimits )
1355 {
1356 *pLimits = pdata->box;
1357 OutsetBox(pLimits, scaleX<<2, scaleY<<2);
1358 return TRUE;
1359 }
1360
1361 static PrimDef rorecPrimDef = {
1362 (PrimDrawProc ) RoRecDrawProc,
1363 (PrimHitTestProc ) RoRecHitTestProc,
1364 (PrimOffsetProc ) RoRecOffsetProc,
1365 (PrimCleanupProc ) 0,
1366 (PrimGetLimitsProc) RoRecGetLimitsProc
1367 };
1368
1369
1370 /*****************************************************************************
1371 *
1372 * AddRoundedRectangle
1373 *
1374 *****************************************************************************/
1375
1376 PrimitivE AddRoundedRectangle(SegmenT parent,
1377 Int4 left, Int4 top, Int4 right, Int4 bottom,
1378 Int4 oval_w, Int4 oval_h, Boolean fill,
1379 Uint4 flags, Uint2 primID)
1380 {
1381 RoRecPData data;
1382 Int4 tmp;
1383
1384 if (left > right) {
1385 tmp = left;
1386 left = right;
1387 right = tmp;
1388 }
1389 if (bottom > top) {
1390 tmp = bottom;
1391 bottom = top;
1392 top = tmp;
1393 }
1394
1395 data.box.left = left;
1396 data.box.top = top;
1397 data.box.right = right;
1398 data.box.bottom = bottom;
1399
1400 data.flags = flags;
1401
1402 data.oval_w = oval_w;
1403 data.oval_h = oval_h;
1404
1405 data.fill = fill;
1406 return AddPrimitive(&rorecPrimDef, parent, primID, (VoidPtr)&data,
1407 sizeof(RoRecPData));
1408 }
1409
1410
1411 /*****************************************************************************
1412 *
1413 * SEGMENT RECTANGLE
1414 *
1415 *****************************************************************************/
1416
1417 typedef struct segrecpdata {
1418 BoxPtr parentBox;
1419 Boolean fill;
1420 } SegRecPData, PNTR SegRecPDataPtr;
1421
1422 static void SegRecDrawProc (SegRecPDataPtr pdata, PrimDrawContext pdc)
1423 {
1424 register DrawInfoPtr dInfoPtr;
1425 BoxInfo tmpBox;
1426 Int4 curScale;
1427 RecT r;
1428
1429 dInfoPtr = (DrawInfoPtr)pdc;
1430 tmpBox = *(pdata->parentBox);
1431 if ( (tmpBox.left > dInfoPtr->scale.worldWindow.right) ||
1432 (tmpBox.right < dInfoPtr->scale.worldWindow.left) ||
1433 (tmpBox.top < dInfoPtr->scale.worldWindow.bottom) ||
1434 (tmpBox.bottom > dInfoPtr->scale.worldWindow.top) ) return;
1435 if ( dInfoPtr->checked == FALSE ) {
1436 if ( tmpBox.left < dInfoPtr->scale.worldWindow16.left )
1437 tmpBox.left = dInfoPtr->scale.worldWindow16.left;
1438 if ( tmpBox.right > dInfoPtr->scale.worldWindow16.right )
1439 tmpBox.right = dInfoPtr->scale.worldWindow16.right;
1440 if ( tmpBox.top > dInfoPtr->scale.worldWindow16.top )
1441 tmpBox.top = dInfoPtr->scale.worldWindow16.top;
1442 if ( tmpBox.bottom < dInfoPtr->scale.worldWindow16.bottom )
1443 tmpBox.bottom = dInfoPtr->scale.worldWindow16.bottom;
1444 }
1445 if (pdata->fill) {
1446 SetPrimAttribute (pdc, COLOR_ATT|SHADING_ATT|MODE_ATT);
1447 } else {
1448 SetPrimAttribute (pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
1449 }
1450 curScale = dInfoPtr->scale.scaleX;
1451 r.left = (Int2)((dInfoPtr->scale.offsetX + tmpBox.left) / curScale);
1452 r.right = (Int2)((dInfoPtr->scale.offsetX + tmpBox.right) / curScale);
1453 curScale = dInfoPtr->scale.scaleY;
1454 r.top = (Int2)((dInfoPtr->scale.offsetY - tmpBox.top) / curScale);
1455 r.bottom = (Int2)((dInfoPtr->scale.offsetY - tmpBox.bottom) / curScale);
1456 r.right++; r.bottom++;
1457 if ( pdata->fill ) PaintRect (&r);
1458 else FrameRect (&r);
1459 r.right--; r.bottom--;
1460 switch ( dInfoPtr->highlight ) {
1461 case FRAME_PRIMITIVE:
1462 case OUTLINE_PRIMITIVE:
1463 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
1464 WidePen((Int2)(dInfoPtr->primattrib->penwidth + 1));
1465 r.right ++; r.bottom ++;
1466 FrameRect (&r);
1467 InsetRect (&r, -1, -1 );
1468 FrameRect (&r);
1469 break;
1470 case FILL_PRIMITIVE:
1471 SetPrimAttribute (pdc, SHADING_ATT);
1472 r.right ++; r.bottom ++;
1473 InsetRect (&r, -1, -1);
1474 PaintRect (&r);
1475 }
1476 }
1477
1478 static Boolean SegRecHitTestProc ( SegRecPDataPtr pdata, PrimHitContext phc)
1479 {
1480 register ScalePtr dInfoPtr;
1481 BoxInfo tmpBox;
1482
1483
1484
1485 dInfoPtr = (ScalePtr)phc;
1486 tmpBox = *(pdata->parentBox);
1487 if ( (tmpBox.left < dInfoPtr->worldWindow.right) &&
1488 (tmpBox.right > dInfoPtr->worldWindow.left) &&
1489 (tmpBox.top > dInfoPtr->worldWindow.bottom) &&
1490 (tmpBox.bottom < dInfoPtr->worldWindow.top) ) return TRUE;
1491 return FALSE;
1492 }
1493
1494 static Boolean SegRecOffsetProc ( SegRecPDataPtr pdata, Int4 deltaX,
1495 Int4 deltaY )
1496 {
1497 return FALSE;
1498 }
1499
1500 static Boolean SegRecGetLimitsProc ( SegRecPDataPtr pdata, Int4 scaleX,
1501 Int4 scaleY, BoxPtr pLimits )
1502 {
1503 *pLimits = *(pdata->parentBox);
1504 return TRUE;
1505 }
1506
1507 static PrimDef segrecPrimDef = {
1508 (PrimDrawProc) SegRecDrawProc,
1509 (PrimHitTestProc) SegRecHitTestProc,
1510 (PrimOffsetProc) SegRecOffsetProc,
1511 (PrimCleanupProc) NULL,
1512 (PrimGetLimitsProc) SegRecGetLimitsProc
1513 };
1514
1515 Nlm_PrimitivE Nlm_AddSegRect ( SegmenT parent, Boolean fill,
1516 Uint2 primID )
1517 {
1518 SegRecPData data;
1519
1520 data.parentBox = &(((SegPPtr)parent)->seg.box);
1521 data.fill = fill;
1522 return AddPrimitive (&segrecPrimDef, parent, primID, (VoidPtr)&data,
1523 sizeof(SegRecPData));
1524 }
1525
1526 static Boolean SilentSegRecHitTestProc ( SegRecPDataPtr pdata, PrimHitContext phc)
1527 {
1528 /* SilentSegRect's should never absorb clicks */
1529 return FALSE;
1530 }
1531
1532 static PrimDef silentSegrecPrimDef = {
1533 (PrimDrawProc) SegRecDrawProc,
1534 (PrimHitTestProc) SilentSegRecHitTestProc,
1535 (PrimOffsetProc) SegRecOffsetProc,
1536 (PrimCleanupProc) NULL,
1537 (PrimGetLimitsProc) SegRecGetLimitsProc
1538 };
1539
1540 Nlm_PrimitivE Nlm_AddSilentSegRect ( SegmenT parent, Boolean fill,
1541 Uint2 primID )
1542 {
1543 SegRecPData data;
1544
1545 data.parentBox = &(((SegPPtr)parent)->seg.box);
1546 data.fill = fill;
1547 return AddPrimitive (&silentSegrecPrimDef, parent, primID, (VoidPtr)&data,
1548 sizeof(SegRecPData));
1549 }
1550
1551 /*****************************************************************************
1552 *
1553 * H - LINE
1554 *
1555 *****************************************************************************/
1556 typedef struct hlinepdata {
1557 Int4 x1;
1558 Int4 x2;
1559 Int4 y;
1560 Int1 fArrowPoint;
1561 Int1 arrowSize;
1562 } HLinePData, PNTR HLinePDataPtr;
1563
1564 static void HLineDrawProc (HLinePDataPtr pdata, PrimDrawContext pdc)
1565 {
1566 register DrawInfoPtr dInfoPtr;
1567 Int4 curScale;
1568 Int4 x1,x2,y;
1569 PoinT pt1, pt2;
1570 PoinT pts [3];
1571 Int2 oldPoint;
1572 Int1 arrowSize;
1573 Boolean vis = TRUE;
1574 RecT rect;
1575
1576 dInfoPtr = (DrawInfoPtr)pdc;
1577 x1 = pdata->x1;
1578 x2 = pdata->x2;
1579 y = pdata->y;
1580 if ( (y > dInfoPtr->scale.worldWindow.top ) ||
1581 (y < dInfoPtr->scale.worldWindow.bottom) ||
1582 (x1 > dInfoPtr->scale.worldWindow.right ) ||
1583 (x2 < dInfoPtr->scale.worldWindow.left ) )
1584 return;
1585
1586 if ( dInfoPtr->checked == FALSE ) {
1587 curScale = dInfoPtr->scale.worldWindow16.left;
1588 if ( x1 < curScale ) x1 = curScale;
1589 curScale = dInfoPtr->scale.worldWindow16.right;
1590 if ( x2 > curScale ) x2 = curScale;
1591 }
1592
1593 SetPrimAttribute (pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
1594
1595 arrowSize = pdata->arrowSize;
1596 curScale = dInfoPtr->scale.scaleX;
1597 pt1.x = (Int2)((dInfoPtr->scale.offsetX + x1) / curScale);
1598 pt2.x = (Int2)((dInfoPtr->scale.offsetX + x2) / curScale);
1599 curScale = dInfoPtr->scale.scaleY;
1600 pt1.y = pt2.y = (Int2)((dInfoPtr->scale.offsetY - y) / curScale);
1601
1602 if (dInfoPtr->highlight != PLAIN_PRIMITIVE)
1603 {
1604 rect.left = pt1.x;
1605 rect.right = pt2.x;
1606 rect.top = rect.bottom = pt1.y;
1607 }
1608
1609 switch ( pdata->fArrowPoint ) {
1610 case 0:
1611 oldPoint = pt2.x;
1612 if (pt2.x - pt1.x > (Int2)arrowSize) pt2.x -= (Int2)arrowSize;
1613 else pt2.x -= (Int2)(arrowSize>>1);
1614 if ( pt2.x < pt1.x ) vis = FALSE;
1615 pts[1].x = oldPoint; pts[1].y = pt1.y;
1616 oldPoint = (Int2)ARROWWIDTH2 * (Int2)arrowSize / (Int2)100;
1617 pts[0].x = pt2.x; pts[0].y = pt1.y + oldPoint;
1618 pts[2].x = pt2.x; pts[2].y = pt2.y - oldPoint ;
1619 break;
1620 case 1:
1621 oldPoint = pt1.x;
1622 if (pt2.x - pt1.x > (Int2)arrowSize) pt1.x += (Int2)arrowSize;
1623 else pt1.x += (Int2)(arrowSize>>1);
1624 if ( pt2.x < pt1.x ) vis = FALSE;
1625 pts[1].x = oldPoint; pts[1].y = pt1.y;
1626 oldPoint = (Int2)ARROWWIDTH2 * (Int2)arrowSize / (Int2)100;
1627 pts[0].x = pt1.x; pts[0].y = pt1.y - oldPoint;
1628 pts[2].x = pt1.x; pts[2].y = pt2.y + oldPoint ;
1629 }
1630
1631 if ( vis ) DrawLine (pt1, pt2);
1632 if ( pdata->fArrowPoint != 0xF ){
1633 SetPrimAttribute (pdc, SHADING_ATT);
1634 PaintPoly (3, pts);
1635 }
1636
1637 switch ( dInfoPtr->highlight )
1638 {
1639 case PLAIN_PRIMITIVE:
1640 break;
1641 case FRAME_PRIMITIVE:
1642 case OUTLINE_PRIMITIVE:
1643 Black();
1644 WidePen( 1 );
1645 InsetRect(&rect, -2, -2);
1646 rect.bottom++;
1647 FrameRect( &rect );
1648 break;
1649 case FILL_PRIMITIVE:
1650 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
1651 WidePen((Int2)(((DrawInfoPtr)pdc)->primattrib->penwidth + 2));
1652 if ( vis ) DrawLine (pt1, pt2);
1653 if ( pdata->fArrowPoint != 0xF ){
1654 FramePoly (3, pts);
1655 SetPrimAttribute (pdc, SHADING_ATT);
1656 PaintPoly (3, pts);
1657 }
1658 break;
1659 }
1660 }
1661
1662
1663 static Boolean HLineHitTestProc ( HLinePDataPtr pdata, PrimHitContext phc)
1664 {
1665 register ScalePtr dInfoPtr;
1666
1667 dInfoPtr = (ScalePtr)phc;
1668 if ( (pdata->x1 < dInfoPtr->worldWindow.right) &&
1669 (pdata->x2 > dInfoPtr->worldWindow.left) &&
1670 (pdata->y > dInfoPtr->worldWindow.bottom) &&
1671 (pdata->y < dInfoPtr->worldWindow.top) ) return TRUE;
1672 return FALSE;
1673 }
1674
1675 static Boolean HLineOffsetProc ( HLinePDataPtr pdata, Int4 deltaX,
1676 Int4 deltaY )
1677 {
1678 pdata->x1 += deltaX;
1679 pdata->x2 += deltaX;
1680 pdata->y += deltaY;
1681 return TRUE;
1682 }
1683
1684 static Boolean HLineGetLimitsProc ( HLinePDataPtr pdata, Int4 scaleX,
1685 Int4 scaleY, BoxPtr pLimits )
1686 {
1687 Int4 arrowSize;
1688
1689 switch ( pdata->fArrowPoint ) {
1690 case 0:
1691 arrowSize = pdata->arrowSize*scaleX/2;
1692 if ( pdata->x2 - pdata->x1 < arrowSize )
1693 pLimits->left = pdata->x2 - arrowSize;
1694 else pLimits->left = pdata->x1;
1695 pLimits->right = pdata->x2;
1696 pLimits->top = pdata->y + arrowSize;
1697 pLimits->bottom = pdata->y - arrowSize;
1698 break;
1699 case 1:
1700 arrowSize = pdata->arrowSize*scaleX/2;
1701 if ( pdata->x2 - pdata->x1 < arrowSize )
1702 pLimits->right = pdata->x2 - arrowSize;
1703 else pLimits->right = pdata->x2;
1704 pLimits->left = pdata->x1;
1705 pLimits->top = pdata->y + arrowSize;
1706 pLimits->bottom = pdata->y - arrowSize;
1707 break;
1708 default:
1709 pLimits->left = pdata->x1;
1710 pLimits->right = pdata->x2;
1711 pLimits->top = pLimits->bottom = pdata->y;
1712 }
1713 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
1714 return TRUE;
1715 }
1716
1717 static PrimDef hlinePrimDef = {
1718 (PrimDrawProc) HLineDrawProc,
1719 (PrimHitTestProc) HLineHitTestProc,
1720 (PrimOffsetProc) HLineOffsetProc,
1721 (PrimCleanupProc) NULL,
1722 (PrimGetLimitsProc) HLineGetLimitsProc
1723 };
1724
1725 /*****************************************************************************
1726 *
1727 * AddHLine (parent, x1, x2, y, arrow, primID)
1728 *
1729 *****************************************************************************/
1730
1731 static PrimitivE Nlm_AddHLine ( SegmenT parent, Int4 pnt1X, Int4 pnt2X,
1732 Int4 pntY, Boolean arrow, Uint2 primID )
1733 {
1734 HLinePData data;
1735
1736 if ( pnt1X == pnt2X ) arrow = FALSE;
1737 data.y = pntY;
1738 data.arrowSize = userArrowSize;
1739 if ( pnt2X >= pnt1X ) {
1740 data.x1 = pnt1X;
1741 data.x2 = pnt2X;
1742 data.fArrowPoint = 0;
1743 } else {
1744 data.x1 = pnt2X;
1745 data.x2 = pnt1X;
1746 data.fArrowPoint = 1;
1747 }
1748 if ( !arrow ) data.fArrowPoint = (Int1)0xF;
1749 return AddPrimitive (&hlinePrimDef, parent, primID, (VoidPtr)&data,
1750 sizeof(HLinePData));
1751 }
1752
1753 /*****************************************************************************
1754 *
1755 * V - LINE
1756 *
1757 *****************************************************************************/
1758 typedef struct vlinepdata {
1759 Int4 y1;
1760 Int4 y2;
1761 Int4 x;
1762 Int1 fArrowPoint;
1763 Int1 arrowSize;
1764 } VLinePData, PNTR VLinePDataPtr;
1765
1766 static void VLineDrawProc (VLinePDataPtr pdata, PrimDrawContext pdc)
1767 {
1768 register DrawInfoPtr dInfoPtr;
1769 Int4 curScale;
1770 Int4 y1,y2,x;
1771 PoinT pt1, pt2;
1772 PoinT pts [3];
1773 Int2 oldPoint;
1774 Int1 arrowSize;
1775 Boolean vis = TRUE;
1776
1777 dInfoPtr = (DrawInfoPtr)pdc;
1778 y1 = pdata->y1;
1779 y2 = pdata->y2;
1780 x = pdata->x;
1781 if ( (y1 > dInfoPtr->scale.worldWindow.top) ||
1782 (y2 < dInfoPtr->scale.worldWindow.bottom) ||
1783 (x > dInfoPtr->scale.worldWindow.right) ||
1784 (x < dInfoPtr->scale.worldWindow.left) ) return;
1785 if ( dInfoPtr->checked == FALSE ) {
1786 curScale = dInfoPtr->scale.worldWindow16.bottom;
1787 if ( y1 < curScale ) y1 = curScale;
1788 curScale = dInfoPtr->scale.worldWindow16.top;
1789 if ( y2 > curScale ) y2 = curScale;
1790 }
1791 SetPrimAttribute (pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
1792 arrowSize = pdata->arrowSize;
1793 curScale = dInfoPtr->scale.scaleY;
1794 pt1.y = (Int2)((dInfoPtr->scale.offsetY - y1) / curScale);
1795 pt2.y = (Int2)((dInfoPtr->scale.offsetY - y2) / curScale);
1796 curScale = dInfoPtr->scale.scaleX;
1797 pt1.x = pt2.x = (Int2)((dInfoPtr->scale.offsetX + x) / curScale);
1798 switch ( pdata->fArrowPoint ) {
1799 case 0:
1800 oldPoint = pt2.y;
1801 if (pt1.y - pt2.y > (Int2)arrowSize) pt2.y += (Int2)arrowSize;
1802 else pt2.y += (Int2)(arrowSize>>1);
1803 if ( pt2.y > pt1.y ) vis = FALSE;
1804 pts[1].x = pt1.x; pts[1].y = oldPoint;
1805 oldPoint = (Int2)ARROWWIDTH2 * (Int2)arrowSize / (Int2)100;
1806 pts[0].x = pt1.x - oldPoint; pts[0].y = pt2.y;
1807 pts[2].x = pt1.x + oldPoint; pts[2].y = pt2.y;
1808 break;
1809 case 1:
1810 oldPoint = pt1.y;
1811 if (pt1.y - pt2.y > (Int2)arrowSize) pt1.y -= (Int2)arrowSize;
1812 else pt1.y -= (Int2)(arrowSize>>1);
1813 if ( pt2.y > pt1.y ) vis = FALSE;
1814 pts[1].x = pt1.x; pts[1].y = oldPoint;
1815 oldPoint = (Int2)ARROWWIDTH2 * (Int2)arrowSize / (Int2)100;
1816 pts[0].x = pt1.x + oldPoint; pts[0].y = pt1.y;
1817 pts[2].x = pt1.x - oldPoint; pts[2].y = pt1.y;
1818 }
1819 if ( vis ) DrawLine (pt1, pt2);
1820 if ( pdata->fArrowPoint != 0xF ){
1821 FramePoly (3, pts);
1822 SetPrimAttribute (pdc, SHADING_ATT);
1823 PaintPoly (3, pts);
1824 }
1825 if ( dInfoPtr->highlight != PLAIN_SEGMENT ) {
1826 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
1827 WidePen((Int2)(((DrawInfoPtr)pdc)->primattrib->penwidth + 2));
1828 if ( vis ) DrawLine (pt1, pt2);
1829 if ( pdata->fArrowPoint != 0xF ){
1830 SetPrimAttribute (pdc, SHADING_ATT);
1831 PaintPoly (3, pts);
1832 }
1833 }
1834 }
1835
1836 static Boolean VLineHitTestProc ( VLinePDataPtr pdata, PrimHitContext phc)
1837 {
1838 register ScalePtr dInfoPtr;
1839
1840 dInfoPtr = (ScalePtr)phc;
1841 if ( (pdata->x < dInfoPtr->worldWindow.right) &&
1842 (pdata->x > dInfoPtr->worldWindow.left) &&
1843 (pdata->y1 < dInfoPtr->worldWindow.top) &&
1844 (pdata->y2 > dInfoPtr->worldWindow.bottom) ) return TRUE;
1845 return FALSE;
1846 }
1847
1848 static Boolean VLineOffsetProc ( VLinePDataPtr pdata, Int4 deltaX,
1849 Int4 deltaY )
1850 {
1851 pdata->x += deltaX;
1852 pdata->y1 += deltaY;
1853 pdata->y2 += deltaY;
1854 return TRUE;
1855 }
1856
1857 static Boolean VLineGetLimitsProc ( VLinePDataPtr pdata, Int4 scaleX,
1858 Int4 scaleY, BoxPtr pLimits )
1859 {
1860 Int4 arrowSize;
1861
1862 switch ( pdata->fArrowPoint ) {
1863 case 0:
1864 arrowSize = pdata->arrowSize*scaleY/2;
1865 if ( pdata->y2 - pdata->y1 < arrowSize )
1866 pLimits->bottom = pdata->y2 + arrowSize;
1867 else pLimits->bottom = pdata->y1;
1868 pLimits->top = pdata->y2;
1869 pLimits->right = pdata->x + arrowSize;
1870 pLimits->left = pdata->x - arrowSize;
1871 break;
1872 case 1:
1873 arrowSize = pdata->arrowSize*scaleY/2;
1874 if ( pdata->y2 - pdata->y1 < arrowSize )
1875 pLimits->top = pdata->y1 - arrowSize;
1876 else pLimits->top = pdata->y2;
1877 pLimits->bottom = pdata->y1;
1878 pLimits->right = pdata->x + arrowSize;
1879 pLimits->left = pdata->x - arrowSize;
1880 break;
1881 default:
1882 pLimits->top = pdata->y2;
1883 pLimits->bottom = pdata->y1;
1884 pLimits->left = pLimits->right = pdata->x;
1885 }
1886 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
1887 return TRUE;
1888 }
1889
1890 static PrimDef vlinePrimDef = {
1891 (PrimDrawProc) VLineDrawProc,
1892 (PrimHitTestProc) VLineHitTestProc,
1893 (PrimOffsetProc) VLineOffsetProc,
1894 (PrimCleanupProc) NULL,
1895 (PrimGetLimitsProc) VLineGetLimitsProc
1896 };
1897
1898 /*****************************************************************************
1899 *
1900 * AddVLine (parent, x, y1, y2, arrow, primID)
1901 *
1902 *****************************************************************************/
1903
1904 static PrimitivE Nlm_AddVLine ( SegmenT parent, Int4 pntX, Int4 pnt1Y,
1905 Int4 pnt2Y, Boolean arrow, Uint2 primID )
1906 {
1907 VLinePData data;
1908
1909 if ( pnt1Y == pnt2Y ) arrow = FALSE;
1910 data.x = pntX;
1911 data.arrowSize = userArrowSize;
1912 if ( pnt2Y >= pnt1Y ) {
1913 data.y1 = pnt1Y;
1914 data.y2 = pnt2Y;
1915 data.fArrowPoint = 0;
1916 } else {
1917 data.y1 = pnt2Y;
1918 data.y2 = pnt1Y;
1919 data.fArrowPoint = 1;
1920 }
1921 if ( !arrow ) data.fArrowPoint = (Int1)0xF;
1922 return AddPrimitive (&vlinePrimDef, parent, primID, (VoidPtr)&data,
1923 sizeof(VLinePData));
1924 }
1925
1926 /*****************************************************************************
1927 *
1928 * LINE
1929 *
1930 *****************************************************************************/
1931
1932 typedef struct linepdata {
1933 BoxInfo box;
1934 Int1 fPoint;
1935 Int1 fArrowPoint;
1936 Int1 arrowSize;
1937 } LinePData, PNTR LinePDataPtr;
1938
1939 static Int2 MSin(Int4 a)
1940 {
1941 if (a < 0)
1942 a += INT4_MAX / 360 * 360;
1943 a %= 360;
1944
1945 if (a < 90)
1946 return sin100[a];
1947 if (a < 180)
1948 return sin100[180-a];
1949 if (a < 270)
1950 return -sin100[a-180];
1951 return -sin100[360-a];
1952 }
1953
1954 /* (for future use)
1955 static Int2 MCos(Int4 a)
1956 {
1957 if (a < 0)
1958 a += INT4_MAX / 360 * 360;
1959 a %= 360;
1960
1961 if (a < 90)
1962 return sin100[90 - a];
1963 if (a < 180)
1964 return -sin100[a - 90];
1965 if (a < 270)
1966 return -sin100[270 - a];
1967 return sin100[a-270];
1968 }
1969 */
1970
1971 static void LineDrawProc (LinePDataPtr pdata, PrimDrawContext pdc)
1972 {
1973 register DrawInfoPtr dInfoPtr;
1974 Int4 curScale;
1975 Int4 x1,y1,x2,y2;
1976 PoinT pt1, pt2;
1977 PoinT pts [3];
1978 Int2 angle;
1979 Int2 dangle = 20;
1980 Int2 arrowSize;
1981 Int2 arrowLen = 106;
1982 Int2 dx, dy;
1983 Boolean vis = TRUE;
1984
1985 dInfoPtr = (DrawInfoPtr)pdc;
1986 arrowSize = (Int2)pdata->arrowSize;
1987 x1 = pdata->box.left;
1988 x2 = pdata->box.right;
1989 if ( pdata->fPoint == 0 ) {
1990 y1 = pdata->box.bottom;
1991 y2 = pdata->box.top;
1992 } else {
1993 y1 = pdata->box.top;
1994 y2 = pdata->box.bottom;
1995 }
1996 if ( pdata->fArrowPoint == 0xF ) {
1997 if ( (x1 > dInfoPtr->scale.worldWindow.right) ||
1998 (x2 < dInfoPtr->scale.worldWindow.left) ||
1999 (pdata->box.bottom > dInfoPtr->scale.worldWindow.top) ||
2000 (pdata->box.top < dInfoPtr->scale.worldWindow.bottom) ) return;
2001 } else {
2002 curScale = arrowSize * dInfoPtr->scale.scaleX / 2;
2003 if ( ((x1+curScale) > dInfoPtr->scale.worldWindow.right) ||
2004 ((x2-curScale) < dInfoPtr->scale.worldWindow.left) ) return;
2005 curScale = arrowSize * dInfoPtr->scale.scaleY / 2;
2006 if ( ((pdata->box.bottom+curScale) > dInfoPtr->scale.worldWindow.top) ||
2007 ((pdata->box.top+curScale) < dInfoPtr->scale.worldWindow.bottom) )
2008 return;
2009 }
2010 if ( dInfoPtr->checked == FALSE ) {
2011 if ( LineIntoVPort ( &x1, &y1, &x2, &y2,
2012 &(dInfoPtr->scale.worldWindow16)) == FALSE ) return;
2013 }
2014 SetPrimAttribute (pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
2015 curScale = dInfoPtr->scale.scaleX;
2016 pt1.x = (Int2)((dInfoPtr->scale.offsetX + x1) / curScale);
2017 pt2.x = (Int2)((dInfoPtr->scale.offsetX + x2) / curScale);
2018 curScale = dInfoPtr->scale.scaleY;
2019 pt1.y = (Int2)((dInfoPtr->scale.offsetY - y1) / curScale);
2020 pt2.y = (Int2)((dInfoPtr->scale.offsetY - y2) / curScale);
2021 if ( pdata->fArrowPoint != 0xF ){
2022 dx = pt2.x - pt1.x;
2023 dy = pt2.y - pt1.y; if ( dy < 0 ) dy = -dy;
2024 if ( (dx < 4) || ( dy < 4 ) ){
2025 x2 -= x1;
2026 y2 -= y1; if ( y2 < 0 ) y2 = -y2;
2027 } else {
2028 x2 = (Int4)dx; y2 = (Int4)dy;
2029 }
2030 x1 = x2*x2 + y2*y2;
2031 y1 = (Int4)arrowSize * (Int4)arrowSize;
2032 if ( x1 < y1 ) {
2033 dangle = 36;
2034 arrowLen = 61;
2035 if ( x1 < y1/4 ) vis = FALSE;
2036 }
2037 if ( x2 > y2 ) {
2038 if ( x2 > 0xFFFFFF ) angle = atan100[ y2/(x2/100) ] ;
2039 else angle = atan100[ y2*100/x2 ] ;
2040 } else {
2041 if ( y2 > 0xFFFFFF ) angle = 90 - atan100[ x2/(y2/100) ] ;
2042 angle = 90 - atan100[ x2*100/y2 ] ;
2043 }
2044 switch ( pdata->fArrowPoint ){
2045 case 0:
2046 pts[0] = pt2;
2047 angle += 180;
2048 break;
2049 case 1:
2050 pts[0] = pt2;
2051 angle = 180 - angle;
2052 break;
2053 case 2:
2054 pts[0] = pt1;
2055 break;
2056 default:
2057 pts[0] = pt1;
2058 angle = 360 - angle;
2059 }
2060 angle += dangle;
2061 pts[1].x = pts[0].x + MSin(angle+90)*arrowLen/100*arrowSize/100;
2062 pts[1].y = pts[0].y - MSin(angle)*arrowLen/100*arrowSize/100;
2063 angle -= 2*dangle;
2064 pts[2].x = pts[0].x + MSin(angle+90)*arrowLen/100*arrowSize/100;
2065 pts[2].y = pts[0].y - MSin(angle)*arrowLen/100*arrowSize/100;
2066 }
2067 if ( vis ) DrawLine (pt1, pt2);
2068 if ( pdata->fArrowPoint != 0xF ){
2069 FramePoly (3, pts);
2070 SetPrimAttribute (pdc, SHADING_ATT);
2071 PaintPoly (3, pts);
2072 }
2073 if ( dInfoPtr->highlight != PLAIN_SEGMENT ) {
2074 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
2075 WidePen((Int2)(((DrawInfoPtr)pdc)->primattrib->penwidth + 2));
2076 if ( vis ) DrawLine (pt1, pt2);
2077 if ( pdata->fArrowPoint != 0xF ){
2078 FramePoly (3, pts);
2079 SetPrimAttribute (pdc, SHADING_ATT);
2080 PaintPoly (3, pts);
2081 }
2082 }
2083 }
2084
2085 static Boolean LineHitTestProc ( LinePDataPtr pdata, PrimHitContext phc)
2086 {
2087 register ScalePtr dInfoPtr;
2088 Int4 x1,y1,x2,y2;
2089
2090 dInfoPtr = (ScalePtr)phc;
2091 if ( (pdata->box.left < dInfoPtr->worldWindow.right) &&
2092 (pdata->box.right > dInfoPtr->worldWindow.left) &&
2093 (pdata->box.top > dInfoPtr->worldWindow.bottom) &&
2094 (pdata->box.bottom < dInfoPtr->worldWindow.top) ) {
2095 x1 = pdata->box.left;
2096 x2 = pdata->box.right;
2097 if ( pdata->fPoint == 0 ) {
2098 y1 = pdata->box.bottom;
2099 y2 = pdata->box.top;
2100 } else {
2101 y2 = pdata->box.bottom;
2102 y1 = pdata->box.top;
2103 }
2104 return IsLineInVPort ( x1, y1, x2, y2, &(dInfoPtr->worldWindow) );
2105 }
2106 return FALSE;
2107 }
2108
2109 static Boolean LineOffsetProc ( LinePDataPtr pdata, Int4 deltaX,
2110 Int4 deltaY )
2111 {
2112 pdata->box.left += deltaX;
2113 pdata->box.right += deltaX;
2114 pdata->box.top += deltaY;
2115 pdata->box.bottom += deltaY;
2116 return TRUE;
2117 }
2118
2119 static Boolean LineGetLimitsProc ( LinePDataPtr pdata, Int4 scaleX,
2120 Int4 scaleY, BoxPtr pLimits )
2121 {
2122 *pLimits = pdata->box;
2123 switch ( pdata->fArrowPoint ) {
2124 case 0:
2125 pLimits->right += pdata->arrowSize*scaleX/2;
2126 pLimits->top += pdata->arrowSize*scaleY/2;
2127 break;
2128 case 1:
2129 pLimits->right += pdata->arrowSize*scaleX/2;
2130 pLimits->bottom -= pdata->arrowSize*scaleY/2;
2131 break;
2132 case 2:
2133 pLimits->left -= pdata->arrowSize*scaleX/2;
2134 pLimits->bottom -= pdata->arrowSize*scaleY/2;
2135 break;
2136 case 3:
2137 pLimits->left -= pdata->arrowSize*scaleX/2;
2138 pLimits->top += pdata->arrowSize*scaleY/2;
2139 }
2140 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
2141 return TRUE;
2142 }
2143
2144 static PrimDef linePrimDef = {
2145 (PrimDrawProc) LineDrawProc,
2146 (PrimHitTestProc) LineHitTestProc,
2147 (PrimOffsetProc) LineOffsetProc,
2148 (PrimCleanupProc) NULL,
2149 (PrimGetLimitsProc) LineGetLimitsProc
2150 };
2151
2152 /*****************************************************************************
2153 *
2154 * AddLine (parent, x1, y1, x2, y2, arrow, primID)
2155 *
2156 *****************************************************************************/
2157
2158 PrimitivE Nlm_AddLine ( SegmenT parent, Int4 pnt1X, Int4 pnt1Y, Int4 pnt2X,
2159 Int4 pnt2Y, Boolean arrow, Uint2 primID )
2160 {
2161 LinePData data;
2162 GenPPtr gpp;
2163
2164 if ( pnt1Y == pnt2Y ){
2165 return Nlm_AddHLine ( parent, pnt1X, pnt2X, pnt2Y, arrow, primID );
2166 }
2167 if ( pnt1X == pnt2X ){
2168 return Nlm_AddVLine ( parent, pnt1X, pnt1Y, pnt2Y, arrow, primID );
2169 }
2170 if ( (pnt1X == pnt2X) || (pnt1Y == pnt2Y) ) arrow = FALSE;
2171 if ( pnt2X >= pnt1X ) {
2172 data.box.left = pnt1X;
2173 data.box.right = pnt2X;
2174 data.fArrowPoint = 0;
2175 } else {
2176 data.box.left = pnt2X;
2177 data.box.right = pnt1X;
2178 data.fArrowPoint = 2;
2179 }
2180 if ( pnt2Y >= pnt1Y ) {
2181 data.box.bottom = pnt1Y;
2182 data.box.top = pnt2Y;
2183 if ( data.fArrowPoint ) data.fArrowPoint = 3;
2184 } else {
2185 data.box.bottom = pnt2Y;
2186 data.box.top = pnt1Y;
2187 if ( data.fArrowPoint == 0 ) data.fArrowPoint = 1;
2188 }
2189 data.arrowSize = userArrowSize;
2190 if ( data.fArrowPoint & 0x1 ) data.fPoint = 1;
2191 else data.fPoint = 0;
2192 if ( arrow == FALSE ) data.fArrowPoint = (Int1)0xF;
2193 gpp = (GenPPtr)AddPrimitive (&linePrimDef, parent, primID, (VoidPtr)&data,
2194 sizeof(LinePData));
2195 if ( gpp != NULL ){
2196 gpp->att.shading = SOLID_SHADING;
2197 }
2198 return (PrimitivE)gpp;
2199 }
2200
2201 /*****************************************************************************
2202 *
2203 * BITMAP & SYMBOL
2204 *
2205 *****************************************************************************/
2206
2207 typedef struct bmppdata {
2208 Uint1Ptr bits;
2209 PntInfo pnt;
2210 Int2 width;
2211 Int2 height;
2212 Int2 align;
2213 } BmpPData, PNTR BmpPDataPtr;
2214
2215 static void BmpDrawProc (BmpPDataPtr pdata, PrimDrawContext pdc)
2216 {
2217 register DrawInfoPtr dInfoPtr;
2218 Int4 x, y;
2219 BoxInfo tmpBox;
2220 RecT r;
2221
2222 dInfoPtr = (DrawInfoPtr)pdc;
2223 MakeAlignBox ( pdata->pnt.x, pdata->pnt.y,
2224 (Int4)pdata->width * dInfoPtr->scale.scaleX,
2225 (Int4)pdata->height * dInfoPtr->scale.scaleY,
2226 0, 0, pdata->align, &tmpBox );
2227 if ( (tmpBox.left > dInfoPtr->scale.worldWindow.right) ||
2228 (tmpBox.right < dInfoPtr->scale.worldWindow.left) ||
2229 (tmpBox.top < dInfoPtr->scale.worldWindow.bottom) ||
2230 (tmpBox.bottom > dInfoPtr->scale.worldWindow.top) ) return;
2231 x = (dInfoPtr->scale.offsetX + pdata->pnt.x) / dInfoPtr->scale.scaleX;
2232 y = (dInfoPtr->scale.offsetY - pdata->pnt.y) / dInfoPtr->scale.scaleY;
2233 MakeAlignRect ( (Int2)x, (Int2)y, pdata->width, pdata->height,
2234 0, pdata->align, &r );
2235 SetPrimAttribute (pdc, COLOR_ATT|MODE_ATT);
2236 if (pdata->bits != NULL) CopyBits (&r, pdata->bits);
2237 switch ( dInfoPtr->highlight ) {
2238 case FRAME_PRIMITIVE:
2239 case FILL_PRIMITIVE:
2240 case OUTLINE_PRIMITIVE:
2241 r.right ++; r.bottom ++;
2242 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
2243 FrameRect (&r);
2244 InsetRect (&r, -1, -1);
2245 FrameRect (&r);
2246 }
2247 }
2248
2249 static Boolean BmpHitTestProc ( BmpPDataPtr pdata, PrimHitContext phc)
2250 {
2251 register ScalePtr dInfoPtr;
2252 BoxInfo box;
2253
2254 dInfoPtr = (ScalePtr)phc;
2255 MakeAlignBox ( pdata->pnt.x, pdata->pnt.y,
2256 (Int4)pdata->width * dInfoPtr->scaleX,
2257 (Int4)pdata->height * dInfoPtr->scaleY,
2258 0, 0, pdata->align, &box );
2259 if ( (box.left < dInfoPtr->worldWindow.right) &&
2260 (box.right > dInfoPtr->worldWindow.left) &&
2261 (box.top > dInfoPtr->worldWindow.bottom) &&
2262 (box.bottom < dInfoPtr->worldWindow.top) ) return TRUE;
2263 return FALSE;
2264 }
2265
2266 static Boolean BmpOffsetProc ( BmpPDataPtr pdata, Int4 deltaX,
2267 Int4 deltaY )
2268 {
2269 pdata->pnt.x += deltaX;
2270 pdata->pnt.y += deltaY;
2271 return TRUE;
2272 }
2273
2274 static Boolean BmpGetLimitsProc ( BmpPDataPtr pdata, Int4 scaleX,
2275 Int4 scaleY, BoxPtr pLimits )
2276 {
2277 MakeAlignBox ( pdata->pnt.x, pdata->pnt.y,
2278 (Int4)pdata->width * scaleX,
2279 (Int4)pdata->height * scaleY,
2280 0, 0, pdata->align, pLimits );
2281 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
2282 return TRUE;
2283 }
2284
2285 static PrimDef bmpPrimDef = {
2286 (PrimDrawProc) BmpDrawProc,
2287 (PrimHitTestProc) BmpHitTestProc,
2288 (PrimOffsetProc) BmpOffsetProc,
2289 (PrimCleanupProc) NULL,
2290 (PrimGetLimitsProc) BmpGetLimitsProc
2291 };
2292
2293 /*****************************************************************************
2294 *
2295 * AddBitmap (parent, pntX, pntY, width, height, data, align, primID)
2296 *
2297 *****************************************************************************/
2298
2299 PrimitivE AddBitmap (SegmenT parent, Int4 pntX, Int4 pntY, Int2 width,
2300 Int2 height, Uint1Ptr bits, Int2 align, Uint2 primID)
2301 {
2302 BmpPData data;
2303
2304 data.pnt.x = pntX;
2305 data.pnt.y = pntY;
2306 data.bits = bits;
2307 data.width = width;
2308 data.height = height;
2309 data.align = align;
2310 return AddPrimitive (&bmpPrimDef, parent, primID, (VoidPtr)&data,
2311 sizeof(BmpPData));
2312 }
2313
2314 #define SYMBOL_WIDTH 8
2315 #define SYMBOL_HEIGHT 8
2316
2317 static Uint1 rectSym [] = {
2318 0xFE, 0x82, 0x82, 0x82, 0x82, 0x82, 0xFE, 0x00
2319 };
2320 static Uint1 diamondSym [] = {
2321 0x10, 0x28, 0x44, 0x82, 0x44, 0x28, 0x10, 0x00
2322 };
2323 static Uint1 ovalSym [] = {
2324 0x38, 0x44, 0x82, 0x82, 0x82, 0x44, 0x38, 0x00
2325 };
2326 static Uint1 leftTriSym [] = {
2327 0x06, 0x1A, 0x62, 0x82, 0x62, 0x1A, 0x06, 0x00
2328 };
2329 static Uint1 rightTriSym [] = {
2330 0xC0, 0xB0, 0x8C, 0x82, 0x8C, 0xB0, 0xC0, 0x00
2331 };
2332 static Uint1 upTriSym [] = {
2333 0x10, 0x28, 0x28, 0x44, 0x44, 0x82, 0xFE, 0x00
2334 };
2335 static Uint1 downTriSym [] = {
2336 0xFE, 0x82, 0x44, 0x44, 0x28, 0x28, 0x10, 0x00
2337 };
2338 static Uint1 rectFillSym [] = {
2339 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x00
2340 };
2341 static Uint1 diamondFillSym [] = {
2342 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00
2343 };
2344 static Uint1 ovalFillSym [] = {
2345 0x38, 0x7C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x00
2346 };
2347 static Uint1 leftTriFillSym [] = {
2348 0x06, 0x1E, 0x7E, 0xFE, 0x7E, 0x1E, 0x06, 0x00
2349 };
2350 static Uint1 rightTriFillSym [] = {
2351 0xC0, 0xF0, 0xFC, 0xFE, 0xFC, 0xF0, 0xC0, 0x00
2352 };
2353 static Uint1 upTriFillSym [] = {
2354 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00
2355 };
2356 static Uint1 downTriFillSym [] = {
2357 0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00
2358 };
2359
2360 static Uint1Ptr symbolList [] = {
2361 rectSym, diamondSym, ovalSym, leftTriSym,
2362 rightTriSym, upTriSym, downTriSym,
2363 rectFillSym, diamondFillSym, ovalFillSym, leftTriFillSym,
2364 rightTriFillSym, upTriFillSym, downTriFillSym
2365 };
2366
2367 /*****************************************************************************
2368 *
2369 * AddSymbol (parent, pntX, pntY, symbol, fill, align, primID)
2370 *
2371 *****************************************************************************/
2372
2373 PrimitivE AddSymbol (SegmenT parent, Int4 pntX, Int4 pntY,
2374 Int2 symbol, Boolean fill, Int2 align, Uint2 primID)
2375
2376 {
2377 Int2 index;
2378
2379 if (symbol < RECT_SYMBOL || symbol > DOWN_TRIANGLE_SYMBOL) {
2380 Message (MSG_ERROR, "AddSymbol symbol out of range");
2381 return NULL;
2382 }
2383 index = symbol - (Int2)RECT_SYMBOL;
2384 if (fill) index += 7;
2385 return AddBitmap (parent, pntX, pntY, SYMBOL_WIDTH, SYMBOL_HEIGHT,
2386 symbolList [index], align, primID);
2387 }
2388
2389 /*****************************************************************************
2390 *
2391 * MARKER
2392 *
2393 *****************************************************************************/
2394 typedef struct markpdata {
2395 PntInfo pnt;
2396 Int2 length;
2397 Int2 orient;
2398 } MarkPData, PNTR MarkPDataPtr;
2399
2400 static void MarkDrawProc (MarkPDataPtr pdata, PrimDrawContext pdc)
2401 {
2402 register DrawInfoPtr dInfoPtr;
2403 Int4 x1, y1, x2, y2;
2404 Int4 curScale;
2405 Int4 len;
2406
2407 dInfoPtr = (DrawInfoPtr)pdc;
2408 curScale = dInfoPtr->scale.scaleX;
2409 len = (Int4)pdata->length * curScale;
2410 x1 = (dInfoPtr->scale.offsetX + pdata->pnt.x) / curScale;
2411 if ( ( (pdata->pnt.x+len) < dInfoPtr->scale.worldWindow.left) ||
2412 ( (pdata->pnt.x-len) > dInfoPtr->scale.worldWindow.right) ) return;
2413 curScale = dInfoPtr->scale.scaleY;
2414 len = (Int4)pdata->length * curScale;
2415 y1 = (dInfoPtr->scale.offsetY - pdata->pnt.y) / curScale;
2416 if ( ((pdata->pnt.y+len) < dInfoPtr->scale.worldWindow.bottom) ||
2417 ((pdata->pnt.y-len) > dInfoPtr->scale.worldWindow.top) ) return;
2418 switch (pdata->orient){
2419 case HORIZ_LEFT :
2420 x2 = x1; y2 = y1;
2421 x1 -= (Int4)pdata->length;
2422 break;
2423 case HORIZ_CENTER :
2424 x2 = x1+(Int4)pdata->length / 2; y2 = y1;
2425 x1 = x2 - (Int4)pdata->length;
2426 break;
2427 case HORIZ_RIGHT :
2428 x2 = x1 + (Int4)pdata->length; y2 = y1;
2429 break;
2430 case VERT_ABOVE :
2431 x2 = x1; y2 = y1 - (Int4)pdata->length;
2432 break;
2433 case VERT_MIDDLE :
2434 x2 = x1; y2 = y1 - (Int4)pdata->length / 2;
2435 y1 = y2 + (Int4)pdata->length;
2436 break;
2437 default:
2438 x2 = x1; y2 = y1;
2439 y1 += (Int4)pdata->length;
2440 }
2441 SetPrimAttribute (pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
2442 MoveTo ((Int2)x1, (Int2)y1);
2443 LineTo ((Int2)x2, (Int2)y2);
2444 if ( dInfoPtr->highlight != PLAIN_SEGMENT ) {
2445 WidePen((Int2)(((DrawInfoPtr)pdc)->primattrib->penwidth + 2));
2446 MoveTo ((Int2)x1, (Int2)y1);
2447 LineTo ((Int2)x2, (Int2)y2);
2448 }
2449 }
2450
2451 static Boolean MarkHitTestProc ( MarkPDataPtr pdata, PrimHitContext phc)
2452 {
2453 register ScalePtr dInfoPtr;
2454 Int4 curScale;
2455 Int4 lenXY;
2456
2457 dInfoPtr = (ScalePtr)phc;
2458 switch (pdata->orient){
2459 case HORIZ_LEFT :
2460 case HORIZ_CENTER :
2461 case HORIZ_RIGHT :
2462 lenXY = pdata->pnt.y;
2463 if ( (lenXY < dInfoPtr->worldWindow.bottom) ||
2464 (lenXY > dInfoPtr->worldWindow.top )) return FALSE;
2465 curScale = dInfoPtr->scaleX;
2466 lenXY = (Int4)pdata->length * curScale;
2467 switch (pdata->orient){
2468 case HORIZ_LEFT :
2469 if ( (pdata->pnt.x < dInfoPtr->worldWindow.left) ||
2470 ((pdata->pnt.x - lenXY) > dInfoPtr->worldWindow.right))
2471 return FALSE;
2472 break;
2473 case HORIZ_CENTER :
2474 lenXY /= 2;
2475 if ( ((pdata->pnt.x + lenXY) < dInfoPtr->worldWindow.left) ||
2476 ((pdata->pnt.x - lenXY) > dInfoPtr->worldWindow.right))
2477 return FALSE;
2478 break;
2479 default:
2480 if ( ((pdata->pnt.x + lenXY) < dInfoPtr->worldWindow.left) ||
2481 ( pdata->pnt.x > dInfoPtr->worldWindow.right))
2482 return FALSE;
2483 }
2484 break;
2485 default:
2486 lenXY = pdata->pnt.x;
2487 if ( (lenXY < dInfoPtr->worldWindow.left) ||
2488 (lenXY > dInfoPtr->worldWindow.right )) return FALSE;
2489 curScale = dInfoPtr->scaleY;
2490 lenXY = (Int4)pdata->length * curScale;
2491 switch (pdata->orient){
2492 case VERT_ABOVE :
2493 if ( ((pdata->pnt.y + lenXY) < dInfoPtr->worldWindow.bottom) ||
2494 (pdata->pnt.y > dInfoPtr->worldWindow.top))
2495 return FALSE;
2496 break;
2497 case VERT_MIDDLE :
2498 lenXY /= 2;
2499 if ( ((pdata->pnt.y + lenXY) < dInfoPtr->worldWindow.bottom) ||
2500 ((pdata->pnt.y - lenXY) > dInfoPtr->worldWindow.top))
2501 return FALSE;
2502 break;
2503 default:
2504 if ( (pdata->pnt.y < dInfoPtr->worldWindow.bottom) ||
2505 ((pdata->pnt.y - lenXY) > dInfoPtr->worldWindow.top))
2506 return FALSE;
2507 break;
2508 }
2509 }
2510 return TRUE;
2511 }
2512
2513 static Boolean MarkOffsetProc ( MarkPDataPtr pdata, Int4 deltaX,
2514 Int4 deltaY )
2515 {
2516 pdata->pnt.x += deltaX;
2517 pdata->pnt.y += deltaY;
2518 return TRUE;
2519 }
2520
2521 static Boolean MarkGetLimitsProc ( MarkPDataPtr pdata, Int4 scaleX,
2522 Int4 scaleY, BoxPtr pLimits )
2523 {
2524 LoadBox (pLimits, pdata->pnt.x, pdata->pnt.y, pdata->pnt.x, pdata->pnt.y);
2525 switch (pdata->orient){
2526 case HORIZ_LEFT :
2527 pLimits->left -= (Int4)pdata->length * scaleX;
2528 break;
2529 case HORIZ_CENTER :
2530 pLimits->left -= (Int4)pdata->length * scaleX / 2;
2531 pLimits->right += (Int4)pdata->length * scaleX / 2;
2532 break;
2533 case HORIZ_RIGHT :
2534 pLimits->right += (Int4)pdata->length * scaleX;
2535 break;
2536 case VERT_ABOVE :
2537 pLimits->top += (Int4)pdata->length * scaleY;
2538 break;
2539 case VERT_MIDDLE :
2540 pLimits->top += (Int4)pdata->length * scaleY / 2;
2541 pLimits->bottom -= (Int4)pdata->length * scaleY / 2;
2542 break;
2543 default:
2544 pLimits->bottom -= (Int4)pdata->length * scaleY;
2545 }
2546 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
2547 return TRUE;
2548 }
2549
2550 static PrimDef markPrimDef = {
2551 (PrimDrawProc) MarkDrawProc,
2552 (PrimHitTestProc) MarkHitTestProc,
2553 (PrimOffsetProc) MarkOffsetProc,
2554 (PrimCleanupProc) NULL,
2555 (PrimGetLimitsProc) MarkGetLimitsProc
2556 };
2557
2558 /*****************************************************************************
2559 *
2560 * AddMarker (parent, pntX, pntY, length, orient, primID)
2561 *
2562 *****************************************************************************/
2563
2564 PrimitivE AddMarker (SegmenT parent, Int4 pntX, Int4 pntY,
2565 Int2 length, Int2 orient, Uint2 primID)
2566 {
2567 MarkPData data;
2568
2569 data.pnt.x = pntX;
2570 data.pnt.y = pntY;
2571 data.length = length;
2572 data.orient = orient;
2573 return AddPrimitive (&markPrimDef, parent, primID, (VoidPtr)&data,
2574 sizeof(MarkPData));
2575 }
2576
2577 /*****************************************************************************
2578 *
2579 * TEXT LABEL
2580 *
2581 *****************************************************************************/
2582
2583 typedef struct lblpdata {
2584 PntInfo pnt;
2585 FonT font;
2586 Int2 width;
2587 Int2 height;
2588 Int2 align;
2589 Int2 offset;
2590 Char str;
2591 } LblPData, PNTR LblPDataPtr;
2592
2593
2594 static void LblDrawProc (LblPDataPtr pdata, PrimDrawContext pdc)
2595 {
2596 register DrawInfoPtr dInfoPtr;
2597 BoxInfo tmpBox;
2598 Int4 x, y;
2599 RecT r;
2600
2601 dInfoPtr = (DrawInfoPtr)pdc;
2602 MakeAlignBox ( pdata->pnt.x, pdata->pnt.y,
2603 (Int4)pdata->width * dInfoPtr->scale.scaleX,
2604 (Int4)pdata->height * dInfoPtr->scale.scaleY,
2605 pdata->offset * dInfoPtr->scale.scaleX,
2606 pdata->offset * dInfoPtr->scale.scaleY,
2607 pdata->align, &tmpBox );
2608 if ( (tmpBox.left > dInfoPtr->scale.worldWindow.right) ||
2609 (tmpBox.right < dInfoPtr->scale.worldWindow.left) ||
2610 (tmpBox.top < dInfoPtr->scale.worldWindow.bottom) ||
2611 (tmpBox.bottom > dInfoPtr->scale.worldWindow.top) ) return;
2612 x = (dInfoPtr->scale.offsetX + pdata->pnt.x) / dInfoPtr->scale.scaleX;
2613 y = (dInfoPtr->scale.offsetY - pdata->pnt.y) / dInfoPtr->scale.scaleY;
2614 MakeAlignRect ( (Int2)x, (Int2)y, pdata->width, pdata->height,
2615 pdata->offset, pdata->align, &r );
2616 SelectFont (pdata->font);
2617 SetPrimAttribute (pdc, COLOR_ATT|MODE_ATT);
2618 PaintStringEx(&pdata->str, r.left, (Nlm_Int2)(r.top + Ascent()));
2619 if ( dInfoPtr->highlight == OUTLINE_PRIMITIVE ){
2620 r.right ++; r.bottom ++;
2621 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
2622 FrameRect (&r);
2623 InsetRect (&r, -1, -1);
2624 FrameRect (&r);
2625 }
2626 }
2627
2628 static Boolean LblHitTestProc (LblPDataPtr pdata, PrimHitContext phc )
2629 {
2630 register ScalePtr dInfoPtr;
2631 BoxInfo box;
2632
2633 dInfoPtr = (ScalePtr)phc;
2634 MakeAlignBox ( pdata->pnt.x, pdata->pnt.y,
2635 (Int4)pdata->width * dInfoPtr->scaleX,
2636 (Int4)pdata->height * dInfoPtr->scaleY,
2637 pdata->offset * dInfoPtr->scaleX,
2638 pdata->offset * dInfoPtr->scaleY,
2639 pdata->align, &box );
2640 if ( (box.left < dInfoPtr->worldWindow.right) &&
2641 (box.right > dInfoPtr->worldWindow.left) &&
2642 (box.top > dInfoPtr->worldWindow.bottom) &&
2643 ((box.bottom + (dInfoPtr->scaleY<<1)) < dInfoPtr->worldWindow.top) )
2644 return TRUE;
2645 return FALSE;
2646 }
2647
2648 static void LblCleanupProc (LblPDataPtr pdata)
2649 {
2650 DeleteFont (pdata->font);
2651 }
2652
2653 static Boolean LblOffsetProc (LblPDataPtr pdata, Int4 deltaX, Int4 deltaY)
2654 {
2655 pdata->pnt.x += deltaX;
2656 pdata->pnt.y += deltaY;
2657 return TRUE;
2658 }
2659
2660 static Boolean LblGetLimitsProc ( LblPDataPtr pdata, Int4 scaleX,
2661 Int4 scaleY, BoxPtr pLimits )
2662 {
2663 MakeAlignBox ( pdata->pnt.x, pdata->pnt.y,
2664 (Int4)pdata->width * scaleX,
2665 (Int4)pdata->height * scaleY,
2666 pdata->offset * scaleX,
2667 pdata->offset * scaleY,
2668 pdata->align, pLimits );
2669 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
2670 return TRUE;
2671 }
2672
2673 static PrimDef lblPrimDef = {
2674 (PrimDrawProc) LblDrawProc,
2675 (PrimHitTestProc) LblHitTestProc,
2676 (PrimOffsetProc) LblOffsetProc,
2677 (PrimCleanupProc) LblCleanupProc,
2678 (PrimGetLimitsProc) LblGetLimitsProc
2679 };
2680
2681 /*****************************************************************************
2682 *
2683 * AddTextLabel (parent, pntX, pntY, string, font, offset, align, primID)
2684 *
2685 *****************************************************************************/
2686
2687 PrimitivE Nlm_AddTextLabel (SegmenT parent, Int4 pntX, Int4 pntY,
2688 const Char* string, FonT font, Int2 offset,
2689 Int2 align, Uint2 primID )
2690 {
2691 size_t data_size = sizeof(LblPData) + Nlm_StringLen(string) + 1;
2692 LblPDataPtr dataPtr = (LblPDataPtr)MemNew( data_size );
2693 PrimitivE txtLabel;
2694
2695 dataPtr->pnt.x = pntX;
2696 dataPtr->pnt.y = pntY;
2697 Nlm_StringCpy(&(dataPtr->str), string);
2698 dataPtr->font = CopyFont (font);
2699 SelectFont (font);
2700 dataPtr->width = StringWidth (string) + 2;
2701 dataPtr->height = LineHeight () + 2;
2702 dataPtr->align = align;
2703 dataPtr->offset = offset;
2704 SelectFont (programFont);
2705 txtLabel = AddPrimitive (&lblPrimDef, parent, primID,
2706 (VoidPtr)dataPtr, (Int2)data_size);
2707 MemFree ( dataPtr );
2708 return txtLabel;
2709 }
2710
2711 /*****************************************************************************
2712 *
2713 * AddLabel (parent, pntX, pntY, string, size, offset, align, primID)
2714 *
2715 *****************************************************************************/
2716
2717 PrimitivE AddLabel (SegmenT parent, Int4 pntX, Int4 pntY, const Char* string,
2718 Int2 size, Int2 offset, Int2 align, Uint2 primID)
2719 {
2720 FonT font;
2721 switch (size) {
2722 case SMALL_TEXT:
2723 if (smallFont == NULL) SetSmallFont ();
2724 font = smallFont;
2725 break;
2726 case MEDIUM_TEXT:
2727 if (mediumFont == NULL) SetMediumFont ();
2728 font = mediumFont;
2729 break;
2730 case LARGE_TEXT:
2731 if (largeFont == NULL) SetLargeFont ();
2732 font = largeFont;
2733 break;
2734 default :
2735 font = programFont;
2736 break;
2737 }
2738 return AddTextLabel (parent, pntX, pntY, string, font,
2739 offset, align, primID);
2740 }
2741
2742
2743 /*****************************************************************************
2744 *
2745 * OVAL
2746 *
2747 *****************************************************************************/
2748
2749 typedef struct {
2750 PntInfo pnt;
2751 Int4 radx;
2752 Int4 rady;
2753 Boolean fill;
2754 } OvalPData, PNTR OvalPDataPtr;
2755
2756
2757 static void OvalDrawProc(OvalPDataPtr pdata, PrimDrawContext pdc)
2758 {
2759 DrawInfoPtr dInfoPtr = (DrawInfoPtr)pdc;
2760 Int4 rad;
2761 Int4 tmp4;
2762 Int2 radx, rady;
2763 Int2 cx, cy;
2764 RecT oval_rect;
2765
2766 rad = pdata->radx;
2767 tmp4 = pdata->pnt.x;
2768 if ((tmp4-rad) > dInfoPtr->scale.worldWindow.right ||
2769 (tmp4+rad) < dInfoPtr->scale.worldWindow.left)
2770 return;
2771
2772 rad = pdata->rady;
2773 tmp4 = pdata->pnt.y;
2774 if ((tmp4+rad) < dInfoPtr->scale.worldWindow.bottom ||
2775 (tmp4-rad) > dInfoPtr->scale.worldWindow.top)
2776 return;
2777
2778 radx = (Int2)(pdata->radx / dInfoPtr->scale.scaleX);
2779 rady = (Int2)(pdata->rady / dInfoPtr->scale.scaleY);
2780 cx = (Int2)((dInfoPtr->scale.offsetX + pdata->pnt.x)
2781 / dInfoPtr->scale.scaleX);
2782 cy = (Int2)((dInfoPtr->scale.offsetY - pdata->pnt.y)
2783 / dInfoPtr->scale.scaleY);
2784 LoadRect(&oval_rect,
2785 (Int2)(cx - radx), (Int2)(cy - rady),
2786 (Int2)(cx + radx + 1), (Int2)(cy + rady + 1));
2787
2788 if ( pdata->fill ) {
2789 SetPrimAttribute(pdc, COLOR_ATT|SHADING_ATT|MODE_ATT);
2790 PaintOval(&oval_rect);
2791 }
2792 else {
2793 SetPrimAttribute(pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
2794 FrameOval(&oval_rect);
2795 }
2796
2797 switch ( dInfoPtr->highlight ) {
2798 case PLAIN_SEGMENT:
2799 break;
2800 case FILL_PRIMITIVE:
2801 if ( !pdata->fill ) {
2802 SetPrimAttribute (pdc, SHADING_ATT);
2803 PaintOval(&oval_rect);
2804 }
2805 break;
2806 default :
2807 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
2808 FrameRect(&oval_rect);
2809 InsetRect(&oval_rect, -1, -1);
2810 FrameRect(&oval_rect);
2811 }
2812 }
2813
2814
2815 static Boolean OvalHitTestProc(OvalPDataPtr pdata, PrimHitContext phc)
2816 {
2817 ScalePtr dInfoPtr = (ScalePtr)phc;
2818 Int4 x,y;
2819 Int4 dx,dy;
2820 Int4 deltax, deltay;
2821 Int2 angle;
2822
2823 if ((pdata->pnt.x - pdata->radx) > dInfoPtr->worldWindow.right ||
2824 (pdata->pnt.x + pdata->radx) < dInfoPtr->worldWindow.left ||
2825 (pdata->pnt.y - pdata->rady) > dInfoPtr->worldWindow.top ||
2826 (pdata->pnt.y + pdata->rady) < dInfoPtr->worldWindow.bottom)
2827 return FALSE;
2828
2829 x = (dInfoPtr->worldWindow.right + dInfoPtr->worldWindow.left) / 2;
2830 y = (dInfoPtr->worldWindow.top + dInfoPtr->worldWindow.bottom) / 2;
2831 deltax = dInfoPtr->worldWindow.right - dInfoPtr->worldWindow.left;
2832 deltay = dInfoPtr->worldWindow.top - dInfoPtr->worldWindow.bottom;
2833 dx = x - pdata->pnt.x;
2834 dy = y - pdata->pnt.y;
2835 if (!dx && !dy)
2836 return TRUE;
2837 x = (dx > 0) ? dx : -dx;
2838 y = (dy > 0) ? dy : -dy;
2839 if (x > y)
2840 angle = atan100[y * 100 / x];
2841 else
2842 angle = 90 - atan100[x * 100 / y] ;
2843 dx = (Int4)MSin(90 + angle) * pdata->radx / 100L;
2844 dy = (Int4)MSin( angle) * pdata->rady / 100L;
2845
2846 return (Boolean)(dx + deltax > x && dy + deltay > y);
2847 }
2848
2849 static Boolean OvalOffsetProc(OvalPDataPtr pdata, Int4 deltaX, Int4 deltaY)
2850 {
2851 pdata->pnt.x += deltaX;
2852 pdata->pnt.y += deltaY;
2853 return TRUE;
2854 }
2855
2856 static Boolean OvalGetLimitsProc(OvalPDataPtr pdata,
2857 Int4 scaleX, Int4 scaleY, BoxPtr pLimits)
2858 {
2859 Int4 xy = pdata->pnt.x;
2860 pLimits->left = xy - pdata->radx;
2861 pLimits->right = xy + pdata->radx;
2862 xy = pdata->pnt.y;
2863 pLimits->bottom = xy - pdata->rady;
2864 pLimits->top = xy + pdata->rady;
2865 OutsetBox(pLimits, scaleX<<2, scaleY<<2);
2866 return TRUE;
2867 }
2868
2869 static PrimDef ovalPrimDef = {
2870 (PrimDrawProc ) OvalDrawProc,
2871 (PrimHitTestProc ) OvalHitTestProc,
2872 (PrimOffsetProc ) OvalOffsetProc,
2873 (PrimCleanupProc ) NULL,
2874 (PrimGetLimitsProc) OvalGetLimitsProc
2875 };
2876
2877 /*****************************************************************************
2878 *
2879 * AddOval (parent, pntX, pntY, radius, fill, primID)
2880 *
2881 *****************************************************************************/
2882
2883 PrimitivE AddOval(SegmenT parent, Int4 pntX, Int4 pntY, Int4 radiusX,
2884 Int4 radiusY, Boolean fill, Uint2 primID)
2885 {
2886 OvalPData data;
2887
2888 data.pnt.x = pntX;
2889 data.pnt.y = pntY;
2890 data.radx = radiusX;
2891 data.rady = radiusY;
2892 data.fill = fill;
2893 return AddPrimitive(&ovalPrimDef, parent, primID, (VoidPtr)&data,
2894 sizeof(OvalPData));
2895 }
2896
2897
2898 /*****************************************************************************
2899 *
2900 * ARC
2901 *
2902 *****************************************************************************/
2903
2904 typedef struct arcpdata {
2905 BoxInfo box;
2906 PntInfo pnt;
2907 Int4 radx;
2908 Int4 rady;
2909 Int4 start;
2910 Int4 end;
2911 Boolean fill;
2912 } ArcPData, PNTR ArcPDataPtr;
2913
2914 static void FrameArcProc ( Int2 pNum, PoinT PNTR points )
2915 {
2916 Int2 i;
2917
2918 MoveTo ( points->x, points->y );
2919 points++;
2920 for (i=1; i<pNum; i++ ){
2921 LineTo ( points->x, points->y );
2922 points++;
2923 }
2924 }
2925
2926 static void ArcDrawProc (ArcPDataPtr pdata, PrimDrawContext pdc)
2927 {
2928 register DrawInfoPtr dInfoPtr;
2929 BoxInfo tmpBox;
2930 Int4 curScale;
2931 Int2 radx, rady;
2932 Int2 cx, cy;
2933 Int2 i,j,pNum;
2934 Int2 start, end;
2935 Int2 step;
2936 RecT r;
2937
2938 dInfoPtr = (DrawInfoPtr)pdc;
2939 tmpBox = pdata->box;
2940 if ( (tmpBox.left > dInfoPtr->scale.worldWindow.right) ||
2941 (tmpBox.right < dInfoPtr->scale.worldWindow.left) ||
2942 (tmpBox.top < dInfoPtr->scale.worldWindow.bottom) ||
2943 (tmpBox.bottom > dInfoPtr->scale.worldWindow.top) ) return;
2944 radx = (Int2)(pdata->radx / dInfoPtr->scale.scaleX);
2945 rady = (Int2)(pdata->rady / dInfoPtr->scale.scaleY);
2946 cx = (Int2)((dInfoPtr->scale.offsetX + pdata->pnt.x)
2947 / dInfoPtr->scale.scaleX);
2948 cy = (Int2)((dInfoPtr->scale.offsetY - pdata->pnt.y)
2949 / dInfoPtr->scale.scaleY);
2950 if ( radx < rady ) i = rady;
2951 else i = radx;
2952 if ( i < 10 ) step = 10;
2953 else if ( i < 30 ) step = 5;
2954 else if ( i < 60 ) step = 3;
2955 else step = 1;
2956 start = (Int2) (pdata->start / 1000);
2957 end = (Int2) (pdata->end / 1000);
2958 if ( end < start ) end += 360;
2959 polyPoints[0].x = cx;
2960 polyPoints[0].y = cy;
2961 pNum = 1;
2962 for (j=0; j<2; j++ ) {
2963 for ( i=MAX(0,start); (i<90) && (i<=end); i+= step){
2964 polyPoints[pNum].x = cx +
2965 (Int2)(((Int4)radx * (Int4)sin100[90-i]) / (Int4)100);
2966 polyPoints[pNum++].y = cy -
2967 (Int2)(((Int4)rady * (Int4)sin100[i]) / (Int4)100);
2968 }
2969 start -= 90; end -= 90;
2970 for ( i=MAX(0,start); (i<90) && (i<=end); i+= step){
2971 polyPoints[pNum].x = cx -
2972 (Int2)(((Int4)radx * (Int4)sin100[i]) / (Int4)100);
2973 polyPoints[pNum++].y = cy -
2974 (Int2)(((Int4)rady * (Int4)sin100[90-i]) / (Int4)100);
2975 }
2976 start -= 90; end -= 90;
2977 for ( i=MAX(0,start); (i<90) && (i<=end); i+= step){
2978 polyPoints[pNum].x = cx -
2979 (Int2)(((Int4)radx * (Int4)sin100[90-i]) / (Int4)100);
2980 polyPoints[pNum++].y = cy +
2981 (Int2)(((Int4)rady * (Int4)sin100[i]) / (Int4)100);
2982 }
2983 start -= 90; end -= 90;
2984 for ( i=MAX(0,start); (i<90) && (i<=end); i+= step){
2985 polyPoints[pNum].x = cx +
2986 (Int2)(((Int4)radx * (Int4)sin100[i]) / (Int4)100);
2987 polyPoints[pNum++].y = cy +
2988 (Int2)(((Int4)rady * (Int4)sin100[90-i]) / (Int4)100);
2989 }
2990 start -= 90; end -= 90;
2991 }
2992 if (pdata->fill) {
2993 SetPrimAttribute (pdc, COLOR_ATT|SHADING_ATT|MODE_ATT);
2994 } else {
2995 SetPrimAttribute (pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
2996 }
2997 if ( pdata->fill ) PaintPoly(pNum, polyPoints);
2998 else FrameArcProc ( (Int2)(pNum-1), &(polyPoints[1]));
2999 switch ( dInfoPtr->highlight ) {
3000 case PLAIN_SEGMENT:
3001 break;
3002 case FILL_PRIMITIVE:
3003 if ( pdata->fill == 0 ) {
3004 SetPrimAttribute (pdc, SHADING_ATT);
3005 PaintPoly(pNum, polyPoints);
3006 }
3007 break;
3008 default :
3009 curScale = dInfoPtr->scale.scaleX;
3010 r.left = (Int2)((dInfoPtr->scale.offsetX + tmpBox.left) / curScale);
3011 r.right = (Int2)((dInfoPtr->scale.offsetX + tmpBox.right) / curScale)+1;
3012 curScale = dInfoPtr->scale.scaleY;
3013 r.top = (Int2)((dInfoPtr->scale.offsetY - tmpBox.top) / curScale);
3014 r.bottom = (Int2)((dInfoPtr->scale.offsetY - tmpBox.bottom) / curScale)+1;
3015 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
3016 FrameRect (&r);
3017 InsetRect (&r, -1, -1);
3018 FrameRect (&r);
3019 }
3020 }
3021
3022 static Boolean ArcHitTestProc ( ArcPDataPtr pdata, PrimHitContext phc)
3023 {
3024 register ScalePtr dInfoPtr;
3025
3026 dInfoPtr = (ScalePtr)phc;
3027 if ( (pdata->box.left < dInfoPtr->worldWindow.right) &&
3028 (pdata->box.right > dInfoPtr->worldWindow.left) &&
3029 (pdata->box.top > dInfoPtr->worldWindow.bottom) &&
3030 (pdata->box.bottom < dInfoPtr->worldWindow.top) ) return TRUE;
3031 return FALSE;
3032 }
3033
3034 static Boolean ArcOffsetProc ( ArcPDataPtr pdata, Int4 deltaX,
3035 Int4 deltaY )
3036 {
3037 pdata->pnt.x += deltaX;
3038 pdata->pnt.y += deltaY;
3039 pdata->box.left += deltaX;
3040 pdata->box.right += deltaX;
3041 pdata->box.bottom += deltaY;
3042 pdata->box.top += deltaY;
3043 return TRUE;
3044 }
3045
3046 static Boolean ArcGetLimitsProc ( ArcPDataPtr pdata, Int4 scaleX,
3047 Int4 scaleY, BoxPtr pLimits )
3048 {
3049 *pLimits = pdata->box;
3050 return TRUE;
3051 }
3052
3053 static PrimDef arcPrimDef = {
3054 (PrimDrawProc) ArcDrawProc,
3055 (PrimHitTestProc) ArcHitTestProc,
3056 (PrimOffsetProc) ArcOffsetProc,
3057 (PrimCleanupProc) NULL,
3058 (PrimGetLimitsProc) ArcGetLimitsProc
3059 };
3060
3061 /*****************************************************************************
3062 *
3063 * AddArc (parent, pntX, pntY, radius, start, end, fill, primID)
3064 *
3065 *****************************************************************************/
3066
3067 PrimitivE AddArc (SegmenT parent, Int4 pntX, Int4 pntY, Int4 radiusX,
3068 Int4 radiusY, Int4 start, Int4 end, Boolean fill,
3069 Uint2 primID)
3070 {
3071 ArcPData data;
3072
3073 data.pnt.x = pntX;
3074 data.pnt.y = pntY;
3075 data.radx = radiusX;
3076 data.rady = radiusY;
3077 data.start = start;
3078 data.end = end;
3079 data.fill = fill;
3080 data.box.left = pntX - radiusX;
3081 data.box.right = pntX + radiusX;
3082 data.box.top = pntY + radiusY;
3083 data.box.bottom = pntY - radiusY;
3084 return AddPrimitive (&arcPrimDef, parent, primID, (VoidPtr)&data,
3085 sizeof(ArcPData));
3086 }
3087
3088 /*****************************************************************************
3089 *
3090 * POLYGON
3091 *
3092 *****************************************************************************/
3093 typedef struct polpdata {
3094 BoxInfo box;
3095 Int2 vernum;
3096 Int2 fill;
3097 PntInfo pnt;
3098 } PolyPData, PNTR PolyPDataPtr;
3099
3100 static void PolyDrawProc (PolyPDataPtr pdata, PrimDrawContext pdc)
3101 {
3102 register DrawInfoPtr dInfoPtr;
3103 PntPtr pPtr;
3104 BoxInfo tmpBox;
3105 Int4 curScale;
3106 RecT r;
3107 Int2 vernum;
3108 Int2 i;
3109
3110 dInfoPtr = (DrawInfoPtr)pdc;
3111 tmpBox = pdata->box;
3112 if ( (tmpBox.left > dInfoPtr->scale.worldWindow.right) ||
3113 (tmpBox.right < dInfoPtr->scale.worldWindow.left) ||
3114 (tmpBox.top < dInfoPtr->scale.worldWindow.bottom) ||
3115 (tmpBox.bottom > dInfoPtr->scale.worldWindow.top) ) return;
3116 if (pdata->fill) {
3117 SetPrimAttribute (pdc, COLOR_ATT|SHADING_ATT|MODE_ATT);
3118 } else {
3119 SetPrimAttribute (pdc, COLOR_ATT|STYLE_ATT|WIDTH_ATT|MODE_ATT);
3120 }
3121 vernum = pdata->vernum;
3122 pPtr = &(pdata->pnt);
3123 for ( i=0; i<vernum; i++ ){
3124 polyPoints[i].x = (Int2)((dInfoPtr->scale.offsetX + pPtr->x)
3125 / dInfoPtr->scale.scaleX);
3126 polyPoints[i].y = (Int2)((dInfoPtr->scale.offsetY - pPtr->y)
3127 / dInfoPtr->scale.scaleY);
3128 pPtr++;
3129 }
3130 if ( pdata->fill ) PaintPoly(vernum, polyPoints);
3131 else FramePoly(vernum, polyPoints);
3132 switch ( dInfoPtr->highlight ) {
3133 case PLAIN_SEGMENT:
3134 break;
3135 case FILL_PRIMITIVE:
3136 if ( pdata->fill == 0 ) {
3137 SetPrimAttribute (pdc, SHADING_ATT);
3138 PaintPoly(vernum, polyPoints);
3139 }
3140 break;
3141 default:
3142 curScale = dInfoPtr->scale.scaleX;
3143 r.left = (Int2)((dInfoPtr->scale.offsetX + tmpBox.left) / curScale);
3144 r.right = (Int2)((dInfoPtr->scale.offsetX + tmpBox.right) / curScale)+1;
3145 curScale = dInfoPtr->scale.scaleY;
3146 r.top = (Int2)((dInfoPtr->scale.offsetY - tmpBox.top) / curScale);
3147 r.bottom = (Int2)((dInfoPtr->scale.offsetY - tmpBox.bottom) / curScale)+1;
3148 SetPrimAttribute (pdc, STYLE_ATT|WIDTH_ATT);
3149 FrameRect (&r);
3150 InsetRect (&r, -1, -1);
3151 FrameRect (&r);
3152 }
3153 }
3154
3155 static Boolean PolyHitTestProc ( PolyPDataPtr pdata, PrimHitContext phc)
3156 {
3157 register ScalePtr dInfoPtr;
3158
3159 dInfoPtr = (ScalePtr)phc;
3160 if ( (pdata->box.left < dInfoPtr->worldWindow.right) &&
3161 (pdata->box.right > dInfoPtr->worldWindow.left) &&
3162 (pdata->box.top > dInfoPtr->worldWindow.bottom) &&
3163 (pdata->box.bottom < dInfoPtr->worldWindow.top) ) return TRUE;
3164 return FALSE;
3165 }
3166
3167 static Boolean PolyOffsetProc ( PolyPDataPtr pdata, Int4 deltaX,
3168 Int4 deltaY )
3169 {
3170 PntPtr pPtr;
3171 Int2 vernum;
3172 Int2 i;
3173
3174 pdata->box.left += deltaX;
3175 pdata->box.right += deltaX;
3176 pdata->box.top += deltaY;
3177 pdata->box.bottom += deltaY;
3178 vernum = pdata->vernum;
3179 pPtr = &(pdata->pnt);
3180 for ( i=0; i<vernum; i++ ){
3181 pPtr->x += deltaX;
3182 pPtr->y += deltaY;
3183 pPtr++;
3184 }
3185 return TRUE;
3186 }
3187
3188 static Boolean PolyGetLimitsProc ( PolyPDataPtr pdata, Int4 scaleX,
3189 Int4 scaleY, BoxPtr pLimits )
3190 {
3191 *pLimits = pdata->box;
3192 OutsetBox ( pLimits, scaleX<<2, scaleY<<2 );
3193 return TRUE;
3194 }
3195
3196 static PrimDef polyPrimDef = {
3197 (PrimDrawProc) PolyDrawProc,
3198 (PrimHitTestProc) PolyHitTestProc,
3199 (PrimOffsetProc) PolyOffsetProc,
3200 (PrimCleanupProc) NULL,
3201 (PrimGetLimitsProc) PolyGetLimitsProc
3202 };
3203
3204 /*****************************************************************************
3205 *
3206 * AddPolygon (parent, vernum, points, fill, primID)
3207 *
3208 *****************************************************************************/
3209
3210 PrimitivE AddPolygon (SegmenT parent, Int2 vernum, PntPtr points,
3211 Boolean fill, Uint2 primID)
3212 {
3213 PrimitivE poly = NULL;
3214 PolyPDataPtr dataPtr;
3215 PntPtr pPtr;
3216 Int2 i;
3217
3218 if ( (vernum > 1) && (vernum <= 32) && (points != NULL) ){
3219 dataPtr = (PolyPDataPtr)MemNew(sizeof(PolyPData) + vernum*sizeof(PntInfo));
3220 dataPtr->vernum = vernum;
3221 dataPtr->fill = (Int2)fill;
3222 LoadBox ( &(dataPtr->box), INT4_MAX, INT4_MIN, INT4_MIN, INT4_MAX );
3223 pPtr = &(dataPtr->pnt);
3224 for ( i=0; i<vernum; i++ ){
3225 pPtr->x = points[i].x;
3226 if ( dataPtr->box.left > pPtr->x ) dataPtr->box.left = pPtr->x;
3227 if ( dataPtr->box.right < pPtr->x ) dataPtr->box.right = pPtr->x;
3228 pPtr->y = points[i].y;
3229 if ( dataPtr->box.top < pPtr->y ) dataPtr->box.top = pPtr->y;
3230 if ( dataPtr->box.bottom > pPtr->y ) dataPtr->box.bottom = pPtr->y;
3231 pPtr++;
3232 }
3233 poly = AddPrimitive (&polyPrimDef, parent, primID, (VoidPtr)dataPtr,
3234 (Int2)(sizeof(PolyPData) + vernum*sizeof(PntInfo)));
3235 MemFree ( dataPtr );
3236 }
3237 return poly;
3238 }
3239
3240 /*****************************************************************************
3241 *
3242 * DrawSegment (seg, drawinfo )
3243 * Draws a segment, recursively tracking attributes
3244 *
3245 *****************************************************************************/
3246
3247 extern void Nlm_DrawSegment (SegPPtr seg, Nlm_DrawInfoPtr drawinfoPtr )
3248 {
3249 BasePPtr item;
3250 DrawInfo drawinfo;
3251 RecT r;
3252 Int1 highlight;
3253 Int1 highlightPrim;
3254
3255 if (seg != NULL && drawinfoPtr != NULL) {
3256 drawinfo = *drawinfoPtr;
3257 drawinfo.primattrib = &blackAttPData;
3258 if (seg->base.code == SEGMENT || seg->base.code == PICTURE) {
3259 if (seg->seg.maxscale == 0 ||
3260 seg->seg.maxscale >=
3261 MAX (drawinfo.scale.scaleX, drawinfo.scale.scaleY)) {
3262 if ( (seg->seg.box.left <= drawinfo.scale.worldWindow.right) &&
3263 (seg->seg.box.right >= drawinfo.scale.worldWindow.left) &&
3264 (seg->seg.box.top >= drawinfo.scale.worldWindow.bottom) &&
3265 (seg->seg.box.bottom <= drawinfo.scale.worldWindow.top) ){
3266 if (seg->seg.visible) {
3267 SetPrimAttribute ( (Nlm_PrimDrawContext)&drawinfo, (Uint1)0xFF );
3268 if ( !drawinfo.checked ) {
3269 if ((seg->seg.box.left >= drawinfo.scale.worldWindow16.left) &&
3270 (seg->seg.box.right <= drawinfo.scale.worldWindow16.right) &&
3271 (seg->seg.box.top <= drawinfo.scale.worldWindow16.top) &&
3272 (seg->seg.box.bottom >= drawinfo.scale.worldWindow16.bottom))
3273 drawinfo.checked = TRUE;
3274 }
3275 if ( seg->seg.highlight != PLAIN_SEGMENT ) {
3276 highlight = seg->seg.highlight;
3277 } else {
3278 highlight = drawinfo.highlight;
3279 }
3280 switch ( highlight ) {
3281 case FRAME_CONTENTS:
3282 highlightPrim = FRAME_PRIMITIVE;
3283 break;
3284 case FILL_CONTENTS:
3285 highlightPrim = FILL_PRIMITIVE;
3286 break;
3287 case OUTLINE_CONTENTS:
3288 highlightPrim = OUTLINE_PRIMITIVE;
3289 break;
3290 default:
3291 highlightPrim = PLAIN_PRIMITIVE;
3292 }
3293 item = seg->seg.head;
3294 while (item != NULL) {
3295 switch (item->code) {
3296 case GENERIC :
3297 drawinfo.primattrib = &(((Nlm_GenPPtr)item)->att);
3298 drawinfo.highlight = ((Nlm_GenPPtr)item)->highlight;
3299 if ( drawinfo.highlight == PLAIN_PRIMITIVE ) {
3300 drawinfo.highlight = highlightPrim;
3301 }
3302 DrawPrimitive (item, &drawinfo );
3303 break;
3304 case PICTURE :
3305 Message (MSG_ERROR, "DrawSegment child is a picture");
3306 break;
3307 case SEGMENT :
3308 drawinfo.highlight = highlight;
3309 Nlm_DrawSegment ((SegPPtr)item, &drawinfo);
3310 break;
3311 default :
3312 Message (MSG_ERROR, "DrawSegment child is unknown");
3313 }
3314 item = item->next;
3315 }
3316 if ( seg->seg.highlight != PLAIN_SEGMENT ) {
3317 drawinfo.primattrib = &blackAttPData;
3318 SetPrimAttribute ( (Nlm_PrimDrawContext)&drawinfo, 0xFF );
3319 MapWorldBoxToRect ( &r, &(seg->seg.box), &(drawinfo.scale) );
3320 switch (seg->seg.highlight) {
3321 case FRAME_SEGMENT :
3322 FrameRect (&r);
3323 break;
3324 case FILL_SEGMENT :
3325 PaintRect (&r);
3326 break;
3327 case OUTLINE_SEGMENT :
3328 InsetRect (&r, -4, -4);
3329 FrameRect (&r);
3330 InsetRect (&r, 1, 1);
3331 FrameRect (&r);
3332 InsetRect (&r, 2, 2);
3333 drawinfo.primattrib = &whiteAttPData;
3334 SetPrimAttribute ( (Nlm_PrimDrawContext)&drawinfo, 0xFF );
3335 FrameRect (&r);
3336 }
3337 }
3338 }
3339 }
3340 }
3341 drawinfoPtr->curattrib = drawinfo.curattrib;
3342 } else {
3343 Message (MSG_ERROR, "DrawSegment argument not a segment or picture");
3344 }
3345 }
3346 }
3347
3348
3349 /*****************************************************************************
3350 *
3351 * SENTINEL RECTANGLE
3352 *
3353 *****************************************************************************/
3354
3355 typedef struct sntrecpdata {
3356 BoxInfo box;
3357 SntOnDrawProc callback;
3358 BigScalar calldata;
3359 SntOnCleanupProc cleanup;
3360 } SntRecPData, PNTR SntRecPDataPtr;
3361
3362
3363 static void SntRecDrawProc(SntRecPDataPtr pdata, PrimDrawContext pdc)
3364 {
3365 BoxPtr primBoxPtr = &pdata->box;
3366 BoxPtr drawBoxPtr = &((DrawInfoPtr)pdc)->scale.worldWindow;
3367
3368 if ( (primBoxPtr->left > drawBoxPtr->right ) ||
3369 (primBoxPtr->right < drawBoxPtr->left ) ||
3370 (primBoxPtr->top < drawBoxPtr->bottom) ||
3371 (primBoxPtr->bottom > drawBoxPtr->top ) )
3372 return;
3373
3374 if ( pdata->callback )
3375 (*pdata->callback)( pdata->calldata, pdc );
3376 }
3377
3378 static Boolean SntRecHitTestProc(SntRecPDataPtr pdata, PrimHitContext phc)
3379 {
3380 BoxPtr primBoxPtr = &pdata->box;
3381 BoxPtr drawBoxPtr = &((ScalePtr)phc)->worldWindow;
3382
3383 return (Boolean)((primBoxPtr->left < drawBoxPtr->right ) &&
3384 (primBoxPtr->right > drawBoxPtr->left ) &&
3385 (primBoxPtr->top > drawBoxPtr->bottom) &&
3386 (primBoxPtr->bottom < drawBoxPtr->top ));
3387 }
3388
3389 static void SntRecCleanupProc (SntRecPDataPtr pdata)
3390 {
3391 if ( pdata->cleanup )
3392 (*pdata->cleanup)( pdata->calldata );
3393 }
3394
3395 static Boolean SntRecOffsetProc(SntRecPDataPtr pdata, Int4 deltaX, Int4 deltaY)
3396 {
3397 BoxPtr primBoxPtr = &pdata->box;
3398
3399 primBoxPtr->left += deltaX;
3400 primBoxPtr->right += deltaX;
3401 primBoxPtr->top += deltaY;
3402 primBoxPtr->bottom += deltaY;
3403
3404 return TRUE;
3405 }
3406
3407 static Boolean SntRecGetLimitsProc(SntRecPDataPtr pdata,
3408 Int4 scaleX, Int4 scaleY, BoxPtr pLimits)
3409 {
3410 *pLimits = pdata->box;
3411 OutsetBox(pLimits, scaleX<<2, scaleY<<2);
3412 return TRUE;
3413 }
3414
3415 extern void ChangeSentinelRectangle (PrimitivE prim, Int4 left, Int4 top, Int4 right, Int4 bottom)
3416
3417 {
3418 SntRecPDataPtr pdata;
3419
3420 if (prim == NULL) return;
3421 pdata = (SntRecPDataPtr) &(((GenPPtr) prim)->data);
3422 pdata->box.left = left;
3423 pdata->box.top = top;
3424 pdata->box.right = right;
3425 pdata->box.bottom = bottom;
3426 }
3427
3428 static PrimDef sntrecPrimDef = {
3429 (PrimDrawProc) SntRecDrawProc,
3430 (PrimHitTestProc) SntRecHitTestProc,
3431 (PrimOffsetProc) SntRecOffsetProc,
3432 (PrimCleanupProc) SntRecCleanupProc,
3433 (PrimGetLimitsProc) SntRecGetLimitsProc
3434 };
3435
3436 /*****************************************************************************
3437 *
3438 * AddSntRectangle(parent, left,top,right,bottom, callback,calldata, primID)
3439 *
3440 *****************************************************************************/
3441 extern PrimitivE AddSntRectangle(SegmenT parent,
3442 Int4 left, Int4 top, Int4 right, Int4 bottom,
3443 SntOnDrawProc callback, BigScalar calldata,
3444 SntOnCleanupProc cleanup, Uint2 primID)
3445 {
3446 SntRecPData data;
3447 Int4 swap;
3448
3449 if (left > right) {
3450 swap = left;
3451 left = right;
3452 right = swap;
3453 }
3454 if (bottom > top) {
3455 swap = bottom;
3456 bottom = top;
3457 top = swap;
3458 }
3459 data.box.left = left;
3460 data.box.top = top;
3461 data.box.right = right;
3462 data.box.bottom = bottom;
3463 data.callback = callback;
3464 data.calldata = calldata;
3465 data.cleanup = cleanup;
3466 return AddPrimitive(&sntrecPrimDef, parent, primID, (VoidPtr)&data,
3467 sizeof(SntRecPData));
3468 }
3469
3470 |
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more information. |