1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10 #include "../base/defines.h"
11
12
13
14 #include <stdio.h>
15
16 #include <math.h>
17 #include "ColorMapEditor.h"
18 #include "ColorMapEditorP.h"
19
20 #ifndef MIN
21 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
22 #endif
23 #ifndef MAX
24 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
25 #endif
26
27
28
29 #define HALF_LEVEL (1/(NUM_LEVELS*2))
30 /*
31 * Declare templates for locally defined and used subroutines
32 */
33 void PrintAllControlPoints(XmColorMapEditorWidget cmew);
34 void PrintControlPoint(ControlMap *map, int point_num);
35 void AddControlPoint(ControlMap* map, double level, double value,
36 Boolean above);
37 void CallActivateCallback(XmColorMapEditorWidget cmew, int reason);
38 void RemoveSelectedControlPoints(XmColorMapEditorWidget cmew);
39 static void DeselectAllPoints(ControlMap *map);
40 static Boolean PointExists(ControlMap *map, double level, double value);
41 static void InsertControlPoint( ControlMap* map, int i,
42 double level, double value );
43 static void SetControlBoxXY( ControlMap* map, XRectangle* box,
44 double level, double value );
45 static void GetControlValues( ControlMap* map, int x, int y,
46 double* level, double* value );
47 static int RemoveControlPoint( ControlMap* map, int index );
48 static int MoveControlPoint( ControlMap* map, int index, int x, int y );
49 static int RepositionControlPoint( ControlMap* map, int index,
50 double level, double value );
51 static int GetControlPoint( ControlMap* map, int x, int y, int grab_mode );
52 static void DrawRubberband(XmDrawingAreaWidget w, ControlMap* map);
53 static void StretchRubberband(XmDrawingAreaWidget w, ControlMap* map);
54 static void DrawMultiPointGrabBoxes( Widget w, ControlMap* map);
55 static void ClearMultiPointGrabs( ControlMap* map);
56 void LoadColormapFromFile(char *filename, XmColorMapEditorWidget cmew,
57 Boolean init);
58 void RecalculateControlPointLevels(XmColorMapEditorWidget cmew);
59
60
61 /* Subroutine: CreateControlMap
62 * Purpose: Create a ControlMap structure and partially initialize it.
63 * Note: Some things, such as the GC, must be initialized at expose time
64 */
CreateControlMap(ControlField * field,ControlLine * line,Pixel color,Boolean clip_value)65 ControlMap* CreateControlMap( ControlField* field, ControlLine* line,
66 Pixel color, Boolean clip_value )
67 {
68 ControlMap* map;
69
70 map = (ControlMap *)XtMalloc(sizeof(struct ControlMapRec));
71 map->rubber_banding = False;
72 map->points = NULL;
73 map->undo_top = -1;
74 map->num_undoable = 0;
75 map->boxes = NULL;
76 map->num_points = 0;
77 map->size_buf = 0;
78 /* map->grabbed is the 'current' control point. The grabbed point is black,
79 the rest are hollow. Button 1 need not be kept depressed for a control
80 point to be grabbed */
81 map->grabbed = -1;
82 map->clip_value = clip_value;
83 map->double_click_interval = 350;
84 map->field = field;
85 map->line = line;
86 map->gc = NULL;
87 map->erase_gc = NULL;
88 map->color = color;
89 map->end_policy = FILL_LEVEL;
90 map->multi_point_grab = False;
91 map->toggle_on = False;
92 return map;
93 }
94
95
96 /* Subroutine: CMEAddControlPoint
97 * Purpose: External interface to add a control point
98 */
CMEAddControlPoint(Widget w,double level,double value,Boolean above)99 void CMEAddControlPoint(Widget w, double level, double value, Boolean above )
100 {
101 XmColorMapEditorWidget cmew = (XmColorMapEditorWidget)w;
102 ControlField *field;
103 int i;
104
105 PushUndoPoints(cmew);
106 /*
107 * Normalize the level to 0.0 - 1.0
108 */
109 level = (level - cmew->color_map_editor.value_minimum)/
110 (cmew->color_map_editor.value_maximum -
111 cmew->color_map_editor.value_minimum);
112 for(i = 0; i < 4; i++)
113 {
114 field = cmew->color_map_editor.g.field[i];
115 if(!field->map[0]->toggle_on) continue;
116
117 DrawControlBoxes(field->map[0], field->map[0]->erase_gc);
118 DrawLine(field->map[0]->line, field->map[0]->line->erase_gc);
119 AddControlPoint(field->map[0], level, value, True);
120 SetArrayValues(field->map[0], field->line[0]);
121 SetLineCoords(field->line[0]);
122 DeselectAllPoints(field->map[0]);
123 DrawControlBoxes(field->map[0], field->map[0]->gc);
124 DrawLine(field->map[0]->line, field->map[0]->line->gc);
125 field->user_callback(field);
126 }
127 PrintAllControlPoints(cmew);
128 if(cmew->color_map_editor.g.field[0]->map[0]->toggle_on ||
129 cmew->color_map_editor.g.field[1]->map[0]->toggle_on ||
130 cmew->color_map_editor.g.field[2]->map[0]->toggle_on ||
131 cmew->color_map_editor.g.field[3]->map[0]->toggle_on)
132 CallActivateCallback(cmew, XmCR_MODIFIED);
133 }
134 /* Subroutine: AddControlPoint
135 * Purpose: Put a new control point in the control point list
136 */
AddControlPoint(ControlMap * map,double level,double value,Boolean above)137 void AddControlPoint(ControlMap* map, double level, double value,
138 Boolean above)
139 {
140 register int i;
141
142 if(PointExists(map, level, value)) return;
143 if (level > 1.0 )
144 {
145 level = 1.0;
146 }
147 if (level < 0.0)
148 {
149 level = 0.0;
150 }
151 /* Position i at the index we want to use */
152 if(above)
153 for(i = 0;
154 (i < map->num_points) && (level >= map->points[i].level);
155 i++ );
156 else
157 for(i = 0;
158 (i < map->num_points) && (level > map->points[i].level);
159 i++ );
160 InsertControlPoint(map, i, level, value);
161 }
162
163
164 /* Subroutine: InsertControlPoint
165 * Purpose: Knowing where the new point is to go, insert it
166 */
InsertControlPoint(ControlMap * map,int index,double level,double value)167 static void InsertControlPoint( ControlMap* map, int index,
168 double level, double value )
169 {
170 register int i;
171
172 if( map->num_points == map->size_buf )
173 {
174 map->size_buf += ADDITION;
175 if( map->points )
176 map->points =
177 (ControlPoint *)XtRealloc((char*)map->points,
178 map->size_buf * sizeof(ControlPoint));
179 else
180 map->points =
181 (ControlPoint *)XtMalloc(map->size_buf * sizeof(ControlPoint));
182 if( map->boxes )
183 map->boxes =
184 (XRectangle *)XtRealloc((char*)map->boxes,
185 map->size_buf * sizeof(XRectangle));
186 else
187 map->boxes =
188 (XRectangle *)XtMalloc(map->size_buf * sizeof(XRectangle));
189 /* Set general stuff that is unchanged by other activity */
190 for( i=map->num_points; i<map->size_buf; i++ )
191 {
192 map->boxes[i].width = HASH_SIZE;
193 map->boxes[i].height = HASH_SIZE;
194 }
195 }
196 /* Move everything above that index up */
197 for( i=map->num_points; i>index; i-- )
198 {
199 (void)memcpy((char *)&map->points[i], (char *)&map->points[i-1],
200 sizeof(ControlPoint));
201 (void)memcpy((char *)&map->boxes[i], (char *)&map->boxes[i-1],
202 sizeof(XRectangle));
203 }
204 ++map->num_points;
205 map->points[index].level = level;
206 map->points[index].value = value;
207 map->points[index].wrap_around = 0;
208 map->points[index].multi_point_grab = False;
209 SetControlBoxXY(map, &map->boxes[index], level, value);
210 map->points[index].x = map->boxes[index].x + HASH_OFFSET;
211 map->points[index].y = map->boxes[index].y + HASH_OFFSET;
212 map->points[index].old_print_x = -999;
213 }
214
215
216 /* Subroutine: SetControlBoxXY
217 * Purpose: Given level and value, set the drawing x and y for the hash box
218 */
SetControlBoxXY(ControlMap * map,XRectangle * box,double level,double value)219 static void SetControlBoxXY( ControlMap* map, XRectangle* box,
220 double level, double value )
221 {
222 /* Roll value over into the range of 0.0 to 1.0 */
223 if( value > 1.0 )
224 value -= (double)((int)value);
225 else if( value < 0.0 )
226 value += 1.0 - (double)((int)value);
227 if( map->field->vertical )
228 {
229 /* Level is on vertical axis from bottom, value on horizontal */
230 box->x = (value * (map->field->width - 1))
231 + map->field->left_margin - HASH_OFFSET;
232 box->y = ((1.0 - level) * (map->field->height - 1))
233 + map->field->top_margin - HASH_OFFSET;
234 }
235 else
236 {
237 box->x = (level * (map->field->width - 1))
238 + map->field->left_margin - HASH_OFFSET;
239 box->y = (value * (map->field->height - 1))
240 + map->field->top_margin - HASH_OFFSET;
241 }
242 }
243
244
245 /* Subroutine: GetControlValues
246 * Purpose: Given window x and y, set correspondong level and value.
247 * Clip value to range of 0-1.
248 */
GetControlValues(ControlMap * map,int x,int y,double * level,double * value)249 static void GetControlValues( ControlMap* map, int x, int y,
250 double* level, double* value )
251 {
252 double max_level;
253
254
255 if( map->field->vertical )
256 {
257 /* Level is on vertical axis (from bottom), value on horizontal */
258 *level = (double)(1 - ((double)(y - map->field->top_margin)/
259 (double)(map->field->height - 1)));
260 *value = (double)((double)(x - map->field->left_margin)/
261 (double)(map->field->width - 1));
262 }
263 else
264 {
265 /* Level is on horizontal axis (from left), value on vertical */
266 *level = (double)(x - map->field->left_margin)
267 / (double)(map->field->width - 1);
268 *value = (double)(y - map->field->top_margin)
269 / (double)(map->field->height - 1);
270 }
271 /* If value is a min-max between 0 and 1, restrict it */
272 if( map->clip_value )
273 {
274 /* Clip value to range of 0-1 */
275 if( *value > 1.0 )
276 *value = 1.0;
277 else if( *value < 0.0 )
278 *value = 0.0;
279 }
280 max_level = 1.0;
281 if( *level > max_level )
282 *level = max_level;
283 else if( *level < 0.0 )
284 *level = 0.0;
285 }
286
287
288 /* Subroutine: RemoveSelectedControlPoints
289 * Purpose: Take all selected control points out of the field
290 */
RemoveSelectedControlPoints(XmColorMapEditorWidget cmew)291 void RemoveSelectedControlPoints(XmColorMapEditorWidget cmew)
292 {
293 int i,j;
294 ControlField *field;
295 ControlMap *map;
296
297 for(i = 0; i < 4; i++)
298 {
299 field = cmew->color_map_editor.g.field[i];
300 map = field->map[0];
301 if(!map->toggle_on) continue;
302
303 DrawControlBoxes(field->map[0], field->map[0]->erase_gc);
304 DrawLine(field->map[0]->line, field->map[0]->line->erase_gc);
305 if (map->grabbed >= 0)
306 {
307 RemoveControlPoint(map,map->grabbed);
308 map->grabbed = -1;
309 }
310 for (j = map->num_points - 1; j >= 0; j--)
311 {
312 if (map->points[j].multi_point_grab)
313 {
314 RemoveControlPoint(map,j);
315 }
316 }
317 SetArrayValues(field->map[0], field->line[0]);
318 SetLineCoords(field->line[0]);
319 DrawControlBoxes(field->map[0], field->map[0]->gc);
320 DrawLine(field->line[0], field->map[0]->line->gc);
321 }
322 field->user_callback(field);
323 PrintAllControlPoints(cmew);
324 }
325 /* Subroutine: RemoveAllControlPoints
326 * Purpose: Take all control points out of the field
327 */
RemoveAllControlPoints(ControlField * field)328 void RemoveAllControlPoints( ControlField *field)
329 {
330 int i, num_pts;
331
332 num_pts = field->map[0]->num_points;
333 for (i=0; i < num_pts; i++)
334 {
335 RemoveControlPoint(field->map[0],0);
336 }
337 PrintAllControlPoints(field->cmew);
338 }
339 /* Subroutine: RemoveControlPoint
340 * Purpose: Take a control point out of the list
341 */
RemoveControlPoint(ControlMap * map,int index)342 static int RemoveControlPoint( ControlMap* map, int index )
343 {
344 int i;
345
346 if( (index < 0) || (index >= map->num_points) )
347 return 0;
348 /* Move everything between there and index down */
349 for( i=index+1; i<map->num_points; i++ )
350 {
351 (void)memcpy((char *)&map->points[i-1], (char *)&map->points[i],
352 sizeof(ControlPoint));
353 (void)memcpy((char *)&map->boxes[i-1], (char *)&map->boxes[i],
354 sizeof(XRectangle));
355 }
356 --map->num_points;
357 return 0;
358 }
359
360
361 /* Subroutine: MoveControlPoint
362 * Purpose: Given window x and y, Reposition the Control Point
363 */
MoveControlPoint(ControlMap * map,int index,int x,int y)364 static int MoveControlPoint( ControlMap* map, int index, int x, int y )
365 {
366 double level, value;
367
368 x = MAX(map->field->left_margin ,x);
369 y = MAX(map->field->top_margin ,y);
370 x = MIN(map->field->width + map->field->left_margin - 1, x);
371 y = MIN(map->field->height+ map->field->top_margin - 1, y);
372 GetControlValues(map, x, y, &level, &value);
373 map->points[index].x = x;
374 map->points[index].y = y;
375 /* Include wrap-around offset if point has a prior wrap-around */
376 if( map->points[index].wrap_around != 0 )
377 value += (double)map->points[index].wrap_around;
378 return RepositionControlPoint(map, index, level, value);
379 }
380
381
382 /* Subroutine: RepositionControlPoint
383 * Purpose: Shift a control point to a new location (maintain good order)
384 * Args: Index of point being moved and its new level and value
385 */
RepositionControlPoint(ControlMap * map,int index,double level,double value)386 static int RepositionControlPoint( ControlMap* map, int index,
387 double level, double value )
388 {
389 Boolean get_new_vals;
390 Boolean use_adjacent_level;
391 double adjacent_level=0;
392 int min_y, max_y;
393
394 /*
395 * use_adjacent_level and adjacent_level were implemented for the case
396 * where a control point "bumps" into another. Since a use can place
397 * a control point at an arbitrary (non-pixel aligned) level, when another
398 * point "bumps" into it, it should get the level of the non-pixel aligned
399 * point.
400 */
401 get_new_vals = False;
402 use_adjacent_level = False;
403 max_y = (map->field->height - 1)
404 + map->field->top_margin;
405 min_y = map->field->top_margin;
406 if (index == 0)
407 {
408 if (map->points[index].y >= max_y)
409 {
410 map->points[index].y = max_y;
411 get_new_vals = True;
412 }
413 if (map->num_points > 1)
414 {
415 if (map->points[index].y <= map->points[index+1].y )
416 {
417 map->points[index].y = map->points[index+1].y;
418 get_new_vals = True;
419 use_adjacent_level = True;
420 adjacent_level = map->points[index+1].level;
421 }
422 }
423 }
424 if (index == map->num_points - 1)
425 {
426 if (map->points[index].y <= min_y)
427 {
428 map->points[index].y = min_y;
429 get_new_vals = True;
430 }
431 if (map->num_points > 1)
432 {
433 if (map->points[index].y >= map->points[index-1].y )
434 {
435 map->points[index].y = map->points[index-1].y;
436 get_new_vals = True;
437 use_adjacent_level = True;
438 adjacent_level = map->points[index-1].level;
439 }
440 }
441 }
442 if ( (index > 0) && (index < map->num_points-1) )
443 {
444 if ( map->points[index].y <= map->points[index+1].y )
445 {
446 map->points[index].y = map->points[index+1].y;
447 get_new_vals = True;
448 use_adjacent_level = True;
449 adjacent_level = map->points[index+1].level;
450 }
451 if ( map->points[index].y >= map->points[index-1].y )
452 {
453 map->points[index].y = map->points[index-1].y;
454 get_new_vals = True;
455 use_adjacent_level = True;
456 adjacent_level = map->points[index-1].level;
457 }
458 }
459 if (get_new_vals)
460 {
461 GetControlValues(map, map->points[index].x, map->points[index].y,
462 &level, &value);
463 }
464 if(use_adjacent_level)
465 map->points[index].level = adjacent_level;
466 else
467 map->points[index].level = level;
468 map->points[index].value = value;
469 SetControlBoxXY(map, &map->boxes[index], level, value);
470 return index;
471 }
472
473
474 /* Subroutine: GetControlPoint
475 * Purpose: Return the index of the point indicated (if the radial
476 * distance is within GRAB_RANGE) or a new point
477 * Note: grab_mode: <0:new | ==0:grab,else new | >0:grab, else nothing
478 */
GetControlPoint(ControlMap * map,int x,int y,int grab_mode)479 static int GetControlPoint( ControlMap* map, int x, int y, int grab_mode )
480 {
481 double value, level;
482 int i;
483 int save_error;
484 int save_i;
485 register int error_i, error_y;
486
487 GetControlValues(map, x, y, &level, &value);
488 /* Position i at the index we want to use */
489 for( i = 0; i < map->num_points; i++ )
490 {
491 if (level < (map->points[i].level -
492 (double)HASH_OFFSET/(double)NUM_LEVELS)) break;
493 }
494 /* If there are two points on the same level, select the one whose x value
495 comes the closest to the x of the button press. Note that GRAB_RANGE
496 is normally compared with the square of the error, so I simply
497 check that the y values are w/in 3 pixels of an existing
498 control point, rather than do the square root computation. */
499 if (i < (map->num_points - 1))
500 {
501 if ( (map->points[i].level == map->points[i+1].level) &&
502 (abs(y - map->points[i].y) < 3) )
503 {
504 if (abs(x - map->points[i+1].x) < abs(x - map->points[i].x) )
505 {
506 i++;
507 }
508 }
509 }
510 if( grab_mode >= 0 )
511 {
512 save_error = GRAB_RANGE + GRAB_RANGE;
513 save_i = -1;
514 for(i = 0; i < map->num_points; i++)
515 {
516 error_i = x - (map->points[i].x);
517 error_i *= error_i;
518 if( error_i <= GRAB_RANGE )
519 {
520 error_y = y - (map->points[i].y);
521 error_y *= error_y;
522 error_i += error_y;
523 if (error_i < save_error)
524 {
525 save_error = error_i;
526 save_i = i;
527 }
528 }
529 }
530 if (save_i >= 0)
531 {
532 return save_i;
533 }
534 else
535 {
536 return -1;
537 }
538 }
539 InsertControlPoint(map, i, level, value);
540 return i;
541 }
542
543
544 /* Subroutine: RedrawControlBoxes
545 * Purpose: Clear the window and draw the control points anew
546 */
RedrawControlBoxes(ControlMap * map)547 void RedrawControlBoxes( ControlMap* map )
548 {
549 XClearWindow(XtDisplay(map->field->w), XtWindow(map->field->w));
550 DrawControlBoxes(map, map->gc);
551 }
552
553
554 /* Subroutine: DrawControlBoxes
555 * Purpose: Draw the visible control point hash boxes in the window
556 */
DrawControlBoxes(ControlMap * map,GC gc)557 void DrawControlBoxes( ControlMap* map, GC gc )
558 {
559 int start, finish, index;
560 int low, high;
561
562 if (gc == NULL) return;
563
564 if( map->field->vertical )
565 {
566 low = map->field->top_margin - HASH_SIZE;
567 high = map->field->top_margin + map->field->height - 1;
568 /* Points are ordered highest y to lowest */
569 for( start=0;
570 (start<map->num_points) && (map->boxes[start].y>=high);
571 start++ );
572 for( finish=start;
573 (finish<map->num_points) && (map->boxes[finish].y>=low);
574 finish++ );
575 }
576 else
577 {
578 low = map->field->left_margin - HASH_SIZE;
579 high = map->field->left_margin + map->field->width - 1;
580 /* Points are ordered lowest x to highest */
581 for( start=0;
582 (start<map->num_points) && (map->boxes[start].x<low);
583 start++ );
584 for( finish=start;
585 (finish<map->num_points) && (map->boxes[finish].x<high);
586 finish++ );
587 }
588 if( finish > start )
589 {
590 XDrawRectangles(XtDisplay(map->field->w), XtWindow(map->field->w),
591 gc, &map->boxes[start], finish - start);
592 if( (map->grabbed >= 0)
593 && (map->grabbed >= start)
594 && (map->grabbed < finish) )
595 {
596 XRectangle* box = &map->boxes[map->grabbed];
597 /* Fill region inside box (fill size is 1 smaller than box) */
598 ++box->x;
599 ++box->y;
600 --box->width;
601 --box->height;
602 XFillRectangles(XtDisplay(map->field->w), XtWindow(map->field->w),
603 gc, box, 1);
604 --box->x;
605 --box->y;
606 ++box->width;
607 ++box->height;
608 }
609 for(index=0; index < map->num_points; index++)
610 {
611 if (map->points[index].multi_point_grab)
612 {
613 XRectangle* box = &map->boxes[index];
614 /* Fill region inside box (fill size is 1 smaller than box) */
615 ++box->x;
616 ++box->y;
617 --box->width;
618 --box->height;
619 XFillRectangles(XtDisplay(map->field->w),
620 XtWindow(map->field->w), gc, box, 1);
621 --box->x;
622 --box->y;
623 ++box->width;
624 ++box->height;
625 }
626 }
627 }
628 XSync(XtDisplay(map->field->w), FALSE);
629 }
630
631
632 /* Subroutine: ResizeControlBoxes
633 * Purpose: Update all box drawing params for the current sizes of things
634 */
ResizeControlBoxes(ControlMap * map)635 void ResizeControlBoxes( ControlMap* map )
636 {
637 int i;
638 for( i = 0; i < map->num_points; i++ )
639 {
640 SetControlBoxXY(map, &map->boxes[i],
641 map->points[i].level, map->points[i].value);
642 map->points[i].x = map->boxes[i].x + HASH_OFFSET;
643 map->points[i].y = map->boxes[i].y + HASH_OFFSET;
644 }
645 }
646
647
648 /* Subroutine: MapInput
649 * Purpose: Handle input of button events
650 * Returns: True if values have been changed
651 */
MapInput(Widget w,ControlMap * map,XmDrawingAreaCallbackStruct * call_data)652 Boolean MapInput( Widget w, ControlMap* map,
653 XmDrawingAreaCallbackStruct* call_data )
654 {
655 ControlField *field;
656 static Time time = 0; /* Time of last button1 press event */
657 int index, dummy_index;
658 int delta_y, delta_x;
659 int old_x=0;
660 int xmax;
661 int xmin;
662 int point;
663 Boolean constrain_horizontal;
664 Boolean constrain_vertical;
665 int i;
666 Boolean set;
667
668 if ( ((call_data->event->type == ButtonPress) ||
669 (call_data->event->type == ButtonRelease)) &&
670 (call_data->event->xbutton.button != Button1) )
671 {
672 return FALSE;
673 }
674
675 if ( (call_data->event->type == MotionNotify) &&
676 !(call_data->event->xmotion.state & Button1Mask) )
677 {
678 return FALSE;
679 }
680 constrain_vertical = map->field->cmew->color_map_editor.constrain_vert &&
681 map->toggle_on;
682 constrain_horizontal = map->field->cmew->color_map_editor.constrain_hor &&
683 map->toggle_on;
684 if( call_data->event->type == ButtonPress )
685 {
686 if( call_data->event->xbutton.button == Button1 )
687 {
688 XtVaGetValues( map->field->toggle_b,
689 XmNset, &set, NULL);
690 if(!set)
691 {
692 for(i = 0; i < 4; i++)
693 {
694 field = map->field->cmew->color_map_editor.g.field[i];
695 XtVaGetValues(field->toggle_b,
696 XmNset, &set, NULL);
697 if((XmDrawingAreaWidget)w == field->w)
698 {
699 XtVaSetValues( field->toggle_b,
700 XmNset, True, NULL);
701 map->toggle_on = True;
702 }
703 else
704 {
705 if(set)
706 {
707 XtVaSetValues( field->toggle_b,
708 XmNset, False, NULL);
709 field->map[0]->toggle_on = False;
710 }
711 }
712 }
713 }
714
715 if(ShiftMask & call_data->event->xbutton.state)
716 {
717 point = GetControlPoint(map, call_data->event->xbutton.x,
718 call_data->event->xbutton.y, 1);
719 if(point >= 0)
720 {
721 DrawControlBoxes(map, map->erase_gc);
722 if(map->grabbed == point)
723 {
724 map->grabbed = -1;
725 }
726 else
727 {
728 map->points[point].multi_point_grab =
729 !map->points[point].multi_point_grab;
730 if(map->grabbed != -1)
731 {
732 map->points[map->grabbed].multi_point_grab = True;
733 map->grabbed = -1;
734 }
735 }
736 DrawControlBoxes(map, map->gc);
737 PrintAllControlPoints(map->field->cmew);
738 }
739 return False;
740 }
741 DrawControlBoxes(map, map->erase_gc);
742 DrawLine(map->line, map->line->erase_gc);
743 if( (call_data->event->xbutton.time - time)
744 < map->double_click_interval )
745 {
746 PushUndoPoints(map->field->cmew);
747 ClearMultiPointGrabs(map);
748 if( map->grabbed >= 0 )
749 {
750 RemoveControlPoint(map, map->grabbed);
751 map->grabbed = -1;
752 SetArrayValues(map, map->line);
753 SetLineCoords(map->line);
754 CallActivateCallback(map->field->cmew, XmCR_MODIFIED);
755 }
756 else
757 {
758 map->grabbed =
759 GetControlPoint(map, call_data->event->xbutton.x,
760 call_data->event->xbutton.y, -1);
761 map->points[map->grabbed].wrap_around = 0;
762 }
763 time = 0;
764 }
765 else /* Not a double click */
766 {
767 map->grabbed =
768 GetControlPoint(map, call_data->event->xbutton.x,
769 call_data->event->xbutton.y, 1);
770 time = call_data->event->xbutton.time;
771 /* Btn not pressed on a control point */
772 if (map->grabbed == -1)
773 {
774 ClearMultiPointGrabs(map);
775 map->multi_point_grab = True;
776 map->rubber_banding = True;
777 map->first_rubber_band = True;
778 map->rubber_band_base_y = call_data->event->xbutton.y;
779 map->rubber_band_current_y = call_data->event->xbutton.y;
780 }
781 else
782 {
783 /* Btn pressed on a control point that is part of a multi
784 point grab */
785 PushUndoPoints(map->field->cmew);
786 if (map->points[map->grabbed].multi_point_grab)
787 {
788 /* set grabbed to -1 so we can distinguish this mode
789 while doing the motion processing */
790 map->grabbed = -1;
791 map->multi_move_base_y = call_data->event->xbutton.y;
792 map->multi_move_base_x = call_data->event->xbutton.x;
793 map->multi_point_move = True;
794 }
795 else
796 {
797 ClearMultiPointGrabs(map);
798 }
799 }
800 }
801 DrawControlBoxes(map, map->gc);
802 DrawLine(map->line, map->line->gc);
803 PrintAllControlPoints(map->field->cmew);
804 if( time == 0 )
805 return TRUE;
806 }
807 }
808 else if( call_data->event->type == MotionNotify )
809 {
810 /*
811 * Shift/Button events are processed in the button press.
812 */
813 if(ShiftMask & call_data->event->xmotion.state) return FALSE;
814
815 if( map->grabbed >= 0 )
816 {
817 DrawControlBoxes(map, map->erase_gc);/* Erase the old boxes */
818 DrawLine(map->line, map->line->erase_gc);/* Erase the old lines */
819 if (constrain_vertical)
820 {
821 call_data->event->xmotion.x = map->points[map->grabbed].x;
822 old_x = call_data->event->xmotion.x;
823 }
824 if (constrain_horizontal)
825 {
826 call_data->event->xmotion.y = map->points[map->grabbed].y;
827 }
828 map->grabbed =
829 MoveControlPoint(map, map->grabbed, call_data->event->xmotion.x,
830 call_data->event->xmotion.y);
831 if (constrain_vertical)
832 {
833 map->points[map->grabbed].x = old_x;
834 }
835 SetArrayValues(map, map->line);
836 SetLineCoords(map->line);
837 DrawControlBoxes(map, map->gc);
838 DrawLine(map->line, map->line->gc);
839 PrintAllControlPoints(map->field->cmew);
840 return TRUE;
841 }
842 else if(map->rubber_banding)
843 {
844 map->rubber_band_current_y = call_data->event->xmotion.y;
845 StretchRubberband((XmDrawingAreaWidget)w, map);
846 DrawMultiPointGrabBoxes(w, map);
847 }
848 else if( map->multi_point_move )
849 {
850 DrawControlBoxes(map, map->erase_gc); /* Erase the old boxes */
851 DrawLine(map->line, map->line->erase_gc); /* Erase the old lines */
852 delta_y = call_data->event->xmotion.y - map->multi_move_base_y;
853 delta_x = call_data->event->xmotion.x - map->multi_move_base_x;
854 if (constrain_vertical)
855 {
856 delta_x = 0;
857 }
858 if (constrain_horizontal)
859 {
860 delta_y = 0;
861 }
862 /* Calculate the y limits of movement for the group */
863 xmax = (map->field->width-1) +
864 map->field->right_margin - HASH_OFFSET;
865 xmin = map->field->left_margin;
866 if (delta_x != 0)
867 {
868 for(index = 0; index < map->num_points; index++)
869 {
870 if (map->points[index].multi_point_grab)
871 {
872 if (delta_x + map->points[index].x < xmin)
873 {
874 delta_x = -(map->points[index].x - xmin);
875 }
876 if ((delta_x + map->points[index].x) > xmax)
877 {
878 delta_x = ((map->field->width-1) +
879 map->field->left_margin) -
880 map->points[index].x;
881 }
882 }
883 }
884 }
885 if (delta_y > 0)
886 {
887 for(index = 0; index < map->num_points; index++)
888 {
889 if (map->points[index].multi_point_grab)
890 {
891 if (index != 0)
892 {
893 if (delta_y > (map->points[index-1].y -
894 map->points[index].y) )
895 {
896 delta_y = map->points[index-1].y -
897 map->points[index].y;
898 }
899 }
900 else
901 {
902 delta_y = MIN(delta_y, (((map->field->height - 1) +
903 map->field->top_margin - HASH_OFFSET) -
904 map->points[0].y));
905 }
906 break;
907 }
908 }
909 }
910 if (delta_y < 0)
911 {
912 for(index = map->num_points - 1; index >= 0; index--)
913 {
914 if (map->points[index].multi_point_grab)
915 {
916 if ((index + 1) != map->num_points)
917 {
918 if (abs(delta_y) > abs(map->points[index+1].y -
919 map->points[index].y))
920 {
921 delta_y = map->points[index+1].y -
922 map->points[index].y;
923 }
924 }
925 else
926 {
927 if ( (map->points[index].y + delta_y) <
928 (HASH_SIZE - 1) )
929 {
930 delta_y = -(map->points[index].y - HASH_SIZE+1);
931 }
932 }
933 break;
934 }
935 }
936 }
937 if (delta_y >= 0)
938 {
939 for (index = 0; index < map->num_points; index++)
940 {
941 if (map->points[index].multi_point_grab)
942 {
943 dummy_index = MoveControlPoint(map, index,
944 map->points[index].x + delta_x,
945 map->points[index].y + delta_y);
946 }
947 }
948 }
949 else
950 {
951 for (index = map->num_points - 1; index >= 0; index--)
952 {
953 if (map->points[index].multi_point_grab)
954 {
955 dummy_index = MoveControlPoint(map, index,
956 map->points[index].x + delta_x,
957 map->points[index].y + delta_y);
958 if (index != dummy_index)
959 {
960 map->points[index].multi_point_grab = True;
961 map->points[index+1].multi_point_grab = False;
962 }
963 }
964 }
965 }
966 map->multi_move_base_y = call_data->event->xmotion.y;
967 map->multi_move_base_x = call_data->event->xmotion.x;
968 SetArrayValues(map, map->line);
969 SetLineCoords(map->line);
970 DrawControlBoxes(map, map->gc);
971 DrawLine(map->line, map->line->gc);
972 PrintAllControlPoints(map->field->cmew);
973 return TRUE;
974 }
975 }
976 else if(call_data->event->type == ButtonRelease)
977 {
978 /*
979 * Shift/Button events are processed in the button press.
980 */
981 if(ShiftMask & call_data->event->xbutton.state)
982 {
983 CallActivateCallback(map->field->cmew, XmCR_SELECT);
984 return FALSE;
985 }
986
987 if (map->rubber_banding)
988 {
989 map->rubber_banding = False;
990 map->multi_point_grab = False;
991 map->rubber_band_current_y = call_data->event->xbutton.y;
992 if(!map->first_rubber_band)
993 {
994 DrawRubberband((XmDrawingAreaWidget)w, map);
995 }
996 DrawMultiPointGrabBoxes(w, map);
997 CallActivateCallback(map->field->cmew, XmCR_SELECT);
998 }
999 else if(map->grabbed >= 0)
1000 {
1001 DrawControlBoxes(map, map->erase_gc);
1002 DrawLine(map->line, map->line->erase_gc);
1003 if (constrain_vertical)
1004 {
1005 call_data->event->xbutton.x = map->points[map->grabbed].x;
1006 }
1007 if (constrain_horizontal)
1008 {
1009 call_data->event->xbutton.y = map->points[map->grabbed].y;
1010 }
1011 map->grabbed =
1012 MoveControlPoint(map, map->grabbed, call_data->event->xbutton.x,
1013 call_data->event->xbutton.y);
1014 if( map->clip_value == FALSE )
1015 /* Record the degree of wrap-around */
1016 map->points[map->grabbed].wrap_around =
1017 (short)floor(map->points[map->grabbed].value);
1018 SetArrayValues(map, map->line);
1019 SetLineCoords(map->line);
1020 CallActivateCallback(map->field->cmew, XmCR_MODIFIED);
1021 DrawControlBoxes(map, map->gc);
1022 DrawLine(map->line, map->line->gc);
1023 return TRUE;
1024 }
1025 else if (map->multi_point_move)
1026 {
1027 map->multi_point_move = False;
1028 CallActivateCallback(map->field->cmew, XmCR_MODIFIED);
1029 }
1030 else
1031 {
1032 CallActivateCallback(map->field->cmew, XmCR_SELECT);
1033 }
1034 PrintAllControlPoints(map->field->cmew);
1035 }
1036 return FALSE;
1037 }
DrawRubberband(XmDrawingAreaWidget w,ControlMap * map)1038 static void DrawRubberband(XmDrawingAreaWidget w, ControlMap* map)
1039 {
1040 XDrawRectangle(XtDisplay(w), XtWindow(w), map->field->rubber_band_gc,
1041 w->manager.shadow_thickness,
1042 MIN(map->rubber_band_base_y, map->rubber_band_current_y),
1043 w->core.width-2*(w->manager.shadow_thickness)-1,
1044 abs(map->rubber_band_base_y - map->rubber_band_current_y));
1045
1046 map->rubber_band_old_y = map->rubber_band_current_y;
1047 }
StretchRubberband(XmDrawingAreaWidget w,ControlMap * map)1048 static void StretchRubberband(XmDrawingAreaWidget w, ControlMap* map)
1049 {
1050 if (!map->first_rubber_band)
1051 XDrawRectangle(XtDisplay(w), XtWindow(w), map->field->rubber_band_gc,
1052 w->manager.shadow_thickness,
1053 MIN(map->rubber_band_base_y, map->rubber_band_old_y),
1054 w->core.width-2*(w->manager.shadow_thickness)-1,
1055 abs(map->rubber_band_base_y - map->rubber_band_old_y));
1056
1057 XDrawRectangle(XtDisplay(w), XtWindow(w), map->field->rubber_band_gc,
1058 w->manager.shadow_thickness,
1059 MIN(map->rubber_band_base_y, map->rubber_band_current_y),
1060 w->core.width-2*(w->manager.shadow_thickness)-1,
1061 abs(map->rubber_band_base_y - map->rubber_band_current_y));
1062
1063 map->first_rubber_band = False;
1064 map->rubber_band_old_y = map->rubber_band_current_y;
1065 }
1066 /* Subroutine: DrawControlBoxes
1067 * Purpose: Draw the visible control point hash boxes in the window
1068 */
DrawMultiPointGrabBoxes(Widget w,ControlMap * map)1069 static void DrawMultiPointGrabBoxes( Widget w, ControlMap* map)
1070 {
1071 int start, finish;
1072 int low, high;
1073 int yupper, ylower, index;
1074
1075 if( map->field->vertical )
1076 {
1077 low = map->field->top_margin - HASH_SIZE;
1078 high = map->field->top_margin + map->field->height - 1;
1079 /* Points are ordered highest y to lowest */
1080 for( start=0;
1081 (start<map->num_points) && (map->boxes[start].y>high);
1082 start++ );
1083 for( finish=start;
1084 (finish<map->num_points) && (map->boxes[finish].y>low);
1085 finish++ );
1086 }
1087 else
1088 {
1089 low = map->field->left_margin - HASH_SIZE;
1090 high = map->field->left_margin + map->field->width - 1;
1091 /* Points are ordered lowest x to highest */
1092 for( start=0;
1093 (start<map->num_points) && (map->boxes[start].x<low);
1094 start++ );
1095 for( finish=start;
1096 (finish<map->num_points) && (map->boxes[finish].x<high);
1097 finish++ );
1098 }
1099 if( finish > start )
1100 {
1101 ylower = MIN(map->rubber_band_current_y,
1102 map->rubber_band_base_y) - 2*HASH_OFFSET;
1103 yupper = MAX(map->rubber_band_current_y,
1104 map->rubber_band_base_y) + HASH_OFFSET;
1105 for( index=0; (index < map->num_points); index++ )
1106 {
1107 /* Is the point between the grab range ? */
1108 if ( (map->boxes[index].y > ylower) &&
1109 (map->boxes[index].y < yupper) )
1110 {
1111 /* If the point is currently not grabbed, fill it in */
1112 if (!map->points[index].multi_point_grab)
1113 {
1114 XRectangle* box = &map->boxes[index];
1115 map->points[index].multi_point_grab = True;
1116 /* Fill region inside box (fill size is 1 smaller than box) */
1117 ++box->x;
1118 ++box->y;
1119 --box->width;
1120 --box->height;
1121 XFillRectangles(XtDisplay(map->field->w),
1122 XtWindow(map->field->w), map->gc, box, 1);
1123 --box->x;
1124 --box->y;
1125 ++box->width;
1126 ++box->height;
1127 }
1128 }
1129 else
1130 {
1131 /* The point is out of the grab range. If it was grabbed,
1132 unfill the rectangle */
1133 if (map->points[index].multi_point_grab)
1134 {
1135 XRectangle* box = &map->boxes[index];
1136 map->points[index].multi_point_grab = False;
1137 /* Fill region inside box (fill size is 1 smaller than box) */
1138 ++box->x;
1139 ++box->y;
1140 --box->width;
1141 --box->height;
1142 XFillRectangles(XtDisplay(map->field->w),
1143 XtWindow(map->field->w), map->erase_gc, box, 1);
1144 --box->x;
1145 --box->y;
1146 ++box->width;
1147 ++box->height;
1148 }
1149 }
1150 }
1151 }
1152 XSync(XtDisplay(map->field->w), FALSE);
1153 }
1154 /* Subroutine: DrawControlBoxes
1155 * Purpose: Draw the visible control point hash boxes in the window
1156 */
ClearMultiPointGrabs(ControlMap * map)1157 static void ClearMultiPointGrabs( ControlMap* map)
1158 {
1159 int index;
1160
1161 for (index = 0; index < map->num_points; index ++)
1162 {
1163 map->points[index].multi_point_grab = False;
1164 }
1165 }
1166 /* Subroutine: CallActivateCallback
1167 * Purpose: Call registered callbacks to report value change
1168 */
CallActivateCallback(XmColorMapEditorWidget cmew,int reason)1169 void CallActivateCallback( XmColorMapEditorWidget cmew, int reason)
1170 {
1171 XmColorMapEditorCallbackStruct call_value;
1172 int i;
1173 ControlField *field;
1174 ControlMap *map;
1175 int index;
1176
1177 call_value.reason = reason;
1178 call_value.op_values = NULL;
1179 call_value.val_values = NULL;
1180 call_value.sat_values = NULL;
1181 call_value.hue_values = NULL;
1182
1183 for(i = 0; i < 4; i++)
1184 {
1185 if (cmew->color_map_editor.g.field[i]->map[0]->toggle_on)
1186 {
1187 /*
1188 * The value MUST match the #defines in ColorMapEditor.h
1189 */
1190 call_value.selected_area = i;
1191 break;
1192 }
1193 }
1194 call_value.min_value = cmew->color_map_editor.value_minimum;
1195 call_value.max_value = cmew->color_map_editor.value_maximum;
1196 field = cmew->color_map_editor.g.field[0];
1197
1198 /*
1199 * Note: If the field toggle is not on, set the number of selected control
1200 * points to zero, so the application can set menu sensitivity correctly.
1201 */
1202 call_value.hue_selected = 0;
1203 call_value.sat_selected = 0;
1204 call_value.val_selected = 0;
1205 call_value.op_selected = 0;
1206 if(!field->map[0]->toggle_on)
1207 {
1208 call_value.hue_selected = 0;
1209 }
1210 else if (field->map[0]->grabbed >=0 )
1211 {
1212 call_value.hue_selected = 1;
1213 }
1214 else
1215 {
1216 for(i = 0; i < field->map[0]->num_points;
1217 i++)
1218 {
1219 if (field->map[0]->points[i].multi_point_grab)
1220 {
1221 call_value.hue_selected++;
1222 }
1223 }
1224 }
1225 field = cmew->color_map_editor.g.field[1];
1226 if(!field->map[0]->toggle_on)
1227 {
1228 call_value.sat_selected = 0;
1229 }
1230 else if (field->map[0]->grabbed >=0 )
1231 {
1232 call_value.sat_selected = 1;
1233 }
1234 else
1235 {
1236 for(i = 0; i < field->map[0]->num_points; i++)
1237 {
1238 if (field->map[0]->points[i].multi_point_grab)
1239 {
1240 call_value.sat_selected++;
1241 }
1242 }
1243 }
1244 field = cmew->color_map_editor.g.field[2];
1245 if(!field->map[0]->toggle_on)
1246 {
1247 call_value.val_selected = 0;
1248 }
1249 else if (field->map[0]->grabbed >=0 )
1250 {
1251 call_value.val_selected = 1;
1252 }
1253 else
1254 {
1255 for(i = 0; i < field->map[0]->num_points;
1256 i++)
1257 {
1258 if (field->map[0]->points[i].multi_point_grab)
1259 {
1260 call_value.val_selected++;
1261 }
1262 }
1263 }
1264 field = cmew->color_map_editor.g.field[3];
1265 if(!field->map[0]->toggle_on)
1266 {
1267 call_value.op_selected = 0;
1268 }
1269 else if (field->map[0]->grabbed >=0 )
1270 {
1271 call_value.op_selected = 1;
1272 }
1273 else
1274 {
1275 for(i = 0; i < field->map[0]->num_points;
1276 i++)
1277 {
1278 if (field->map[0]->points[i].multi_point_grab)
1279 {
1280 call_value.op_selected++;
1281 }
1282 }
1283 }
1284 #ifdef Comment
1285 {
1286 struct
1287 {
1288 Boolean occupied;
1289 int num_hues;
1290 int num_sats;
1291 int num_vals;
1292 int hue_index[2];
1293 int sat_index[2];
1294 int val_index[2];
1295 int wrap_around;
1296 double level;
1297 } flags[NUM_LEVELS];
1298
1299 int num_alloced_pts;
1300
1301 /* Initialize the flags array */
1302 for (i = 0; i < NUM_LEVELS; i++)
1303 {
1304 flags[i].occupied = False;
1305 flags[i].num_hues = 0;
1306 flags[i].num_sats = 0;
1307 flags[i].num_vals = 0;
1308 flags[i].wrap_around = 0;
1309 }
1310 /* Find all the control points and set the corresponding flag in the
1311 flags array. */
1312 for (i = 0; i < 3; i ++)
1313 {
1314 field = cmew->color_map_editor.g.field[i];
1315 for (j = 0; j < field->map[0]->num_points; j++)
1316 {
1317 level = field->map[0]->points[j].level;
1318 index = level*(NUM_LEVELS-1) + 0.5;
1319 flags[index].occupied = True;
1320 flags[index].level = field->map[0]->points[j].level;
1321 switch(i)
1322 {
1323 case 0:
1324 if(flags[index].num_hues == 0)
1325 {
1326 flags[index].num_hues = 1;
1327 flags[index].hue_index[0] = j;
1328 }
1329 else
1330 {
1331 flags[index].num_hues = 2;
1332 flags[index].hue_index[1] = j;
1333 }
1334 break;
1335 case 1:
1336 if(flags[index].num_sats == 0)
1337 {
1338 flags[index].num_sats = 1;
1339 flags[index].sat_index[0] = j;
1340 }
1341 else
1342 {
1343 flags[index].num_sats = 2;
1344 flags[index].sat_index[1] = j;
1345 }
1346 break;
1347 case 2:
1348 if(flags[index].num_vals == 0)
1349 {
1350 flags[index].num_vals = 1;
1351 flags[index].val_index[0] = j;
1352 }
1353 else
1354 {
1355 flags[index].num_vals = 2;
1356 flags[index].val_index[1] = j;
1357 }
1358 break;
1359 }
1360 /* Record hue wrap arounds */
1361 if (i == 0)
1362 {
1363 flags[index].wrap_around =
1364 field->map[0]->points[j].wrap_around;
1365 }
1366 }
1367 }
1368 if (!flags[0].occupied)
1369 {
1370 flags[0].occupied = True;
1371 flags[0].level = 0.0;
1372 }
1373 if (!flags[NUM_LEVELS-1].occupied)
1374 {
1375 flags[NUM_LEVELS-1].occupied = True;
1376 flags[NUM_LEVELS-1].level = 1.0;
1377 }
1378 /* Count the number of control points we have to send */
1379 call_value.num_points = 0;
1380 for (i = 0; i < NUM_LEVELS; i++)
1381 {
1382 if ( flags[i].occupied )
1383 {
1384 call_value.num_points++;
1385 if ( (flags[i].num_hues == 2) ||
1386 (flags[i].num_sats == 2) ||
1387 (flags[i].num_vals == 2) )
1388 {
1389 call_value.num_points++;
1390 }
1391 }
1392 }
1393 call_value.reason = reason;
1394 call_value.data =
1395 (double *)XtMalloc(call_value.num_points*sizeof(double));
1396 call_value.hue_values =
1397 (double *)XtMalloc(call_value.num_points*sizeof(double));
1398 call_value.sat_values =
1399 (double *)XtMalloc(call_value.num_points*sizeof(double));
1400 call_value.val_values =
1401 (double *)XtMalloc(call_value.num_points*sizeof(double));
1402
1403 j = 0;
1404 for (i = 0; i < NUM_LEVELS; i++)
1405 {
1406 if ( flags[i].occupied )
1407 {
1408 if ( (flags[i].num_hues < 2) &&
1409 (flags[i].num_sats < 2) &&
1410 (flags[i].num_vals < 2) )
1411 {
1412 call_value.data[j] = cmew->color_map_editor.value_minimum +
1413 flags[i].level*(cmew->color_map_editor.value_maximum -
1414 cmew->color_map_editor.value_minimum);
1415 call_value.hue_values[j] = flags[i].wrap_around +
1416 cmew->color_map_editor.g.field[0]->line[0]->values[i];
1417 call_value.sat_values[j] =
1418 cmew->color_map_editor.g.field[1]->line[0]->values[i];
1419 call_value.val_values[j] =
1420 cmew->color_map_editor.g.field[2]->line[0]->values[i];
1421 j++;
1422 }
1423 else
1424 {
1425 call_value.data[j] = cmew->color_map_editor.value_minimum +
1426 flags[i].level*(cmew->color_map_editor.value_maximum -
1427 cmew->color_map_editor.value_minimum);
1428 field = cmew->color_map_editor.g.field[0];
1429 if(flags[i].num_hues == 2)
1430 {
1431 call_value.hue_values[j] =
1432 field->map[0]->points[flags[i].hue_index[0]].value;
1433 }
1434 else
1435 {
1436 call_value.hue_values[j] = flags[i].wrap_around +
1437 field->line[0]->values[i];
1438 }
1439
1440 field = cmew->color_map_editor.g.field[1];
1441 if(flags[i].num_sats == 2)
1442 {
1443 call_value.sat_values[j] =
1444 field->map[0]->points[flags[i].sat_index[0]].value;
1445 }
1446 else
1447 {
1448 call_value.sat_values[j] = field->line[0]->values[i];
1449 }
1450
1451 field = cmew->color_map_editor.g.field[2];
1452 if(flags[i].num_vals == 2)
1453 {
1454 call_value.val_values[j] =
1455 field->map[0]->points[flags[i].val_index[0]].value;
1456 }
1457 else
1458 {
1459 call_value.val_values[j] = field->line[0]->values[i];
1460 }
1461 j++;
1462
1463 call_value.data[j] = cmew->color_map_editor.value_minimum +
1464 flags[i].level*(cmew->color_map_editor.value_maximum -
1465 cmew->color_map_editor.value_minimum);
1466 field = cmew->color_map_editor.g.field[0];
1467 if(flags[i].num_hues == 2)
1468 {
1469 call_value.hue_values[j] =
1470 field->map[0]->points[flags[i].hue_index[1]].value;
1471 }
1472 else
1473 {
1474 call_value.hue_values[j] = flags[i].wrap_around +
1475 field->line[0]->values[i];
1476 }
1477
1478 field = cmew->color_map_editor.g.field[1];
1479 if(flags[i].num_sats == 2)
1480 {
1481 call_value.sat_values[j] =
1482 field->map[0]->points[flags[i].sat_index[1]].value;
1483 }
1484 else
1485 {
1486 call_value.sat_values[j] = field->line[0]->values[i];
1487 }
1488
1489 field = cmew->color_map_editor.g.field[2];
1490 if(flags[i].num_vals == 2)
1491 {
1492 call_value.val_values[j] =
1493 field->map[0]->points[flags[i].val_index[1]].value;
1494 }
1495 else
1496 {
1497 call_value.val_values[j] = field->line[0]->values[i];
1498 }
1499 j++;
1500 }
1501 }
1502 }
1503
1504 /* Opacity field */
1505 field = cmew->color_map_editor.g.field[3];
1506 call_value.num_op_points = field->map[0]->num_points;
1507 num_alloced_pts = call_value.num_op_points;
1508 if (field->map[0]->points[0].level != 0.0)
1509 {
1510 num_alloced_pts++;
1511 }
1512 if (field->map[0]->points[call_value.num_op_points-1].level < 1.0)
1513 {
1514 num_alloced_pts++;
1515 }
1516 call_value.op_data =
1517 (double *)XtMalloc(num_alloced_pts*sizeof(double));
1518 call_value.op_values =
1519 (double *)XtMalloc(num_alloced_pts*sizeof(double));
1520 if (field->map[0]->points[0].level != 0.0)
1521 {
1522 call_value.op_data[0] = cmew->color_map_editor.value_minimum;
1523 call_value.op_values[0] = field->map[0]->line[0].values[0];
1524 index = 1;
1525 }
1526 else
1527 {
1528 index = 0;
1529 }
1530 for (i = 0; i < call_value.num_op_points; i++)
1531 {
1532 call_value.op_data[index] = cmew->color_map_editor.value_minimum +
1533 field->map[0]->points[i].level*
1534 (cmew->color_map_editor.value_maximum -
1535 cmew->color_map_editor.value_minimum);
1536 call_value.op_values[index] =
1537 cmew->color_map_editor.g.field[3]->map[0]->points[i].value;
1538 index++;
1539 }
1540 if (field->map[0]->points[call_value.num_op_points-1].level < 1.0)
1541 {
1542 call_value.op_data[index] = cmew->color_map_editor.value_maximum;
1543 call_value.op_values[index] =
1544 field->map[0]->line[0].values[(int)(NUM_LEVELS-1)];
1545 }
1546 call_value.num_op_points = num_alloced_pts;
1547 }
1548 #endif
1549 /*minimum = cmew->color_map_editor.value_minimum;*/
1550 /*range = (cmew->color_map_editor.value_maximum -*/
1551 /* cmew->color_map_editor.value_minimum);*/
1552
1553 /* Hue field */
1554 map = cmew->color_map_editor.g.field[HUE]->map[0];
1555 index = map->num_points;
1556 call_value.num_hue_points = index;
1557 call_value.hue_values = (double *)XtMalloc(2*index*sizeof(double));
1558
1559 for (i = 0; i < index ; i++)
1560 {
1561 #ifdef Comment
1562 call_value.hue_values[i] = minimum + map->points[i].level*range;
1563 #else
1564 call_value.hue_values[i] = map->points[i].level;
1565 #endif
1566 call_value.hue_values[i + index] = map->points[i].value;
1567 }
1568
1569 /* Saturation field */
1570 map = cmew->color_map_editor.g.field[SATURATION]->map[0];
1571 index = map->num_points;
1572 call_value.num_sat_points = index;
1573 call_value.sat_values = (double *)XtMalloc(2*index*sizeof(double));
1574 for (i = 0; i < index ; i++)
1575 {
1576 #ifdef Comment
1577 call_value.sat_values[i] = minimum + map->points[i].level*range;
1578 #else
1579 call_value.sat_values[i] = map->points[i].level;
1580 #endif
1581 call_value.sat_values[index +i] = map->points[i].value;
1582 }
1583
1584 /* Value field */
1585 map = cmew->color_map_editor.g.field[VALUE]->map[0];
1586 index = map->num_points;
1587 call_value.num_val_points = index;
1588 call_value.val_values = (double *)XtMalloc(2*index*sizeof(double));
1589 for (i = 0; i < index ; i++)
1590 {
1591 #ifdef Comment
1592 call_value.val_values[i] = minimum + map->points[i].level*range;
1593 #else
1594 call_value.val_values[i] = map->points[i].level;
1595 #endif
1596 call_value.val_values[index +i] = map->points[i].value;
1597 }
1598
1599 /* Opacity field */
1600 map = cmew->color_map_editor.g.field[OPACITY]->map[0];
1601 index = map->num_points;
1602 call_value.num_op_points = index;
1603 call_value.op_values = (double *)XtMalloc(2*index*sizeof(double));
1604 for (i = 0; i < index ; i++)
1605 {
1606 #ifdef Comment
1607 call_value.op_values[i] = minimum + map->points[i].level*range;
1608 #else
1609 call_value.op_values[i] = map->points[i].level;
1610 #endif
1611 call_value.op_values[i + index ] = map->points[i].value;
1612 }
1613
1614 XtCallCallbacks((Widget)cmew, XmNactivateCallback, &call_value);
1615
1616 if (call_value.op_values)
1617 XtFree((char*)call_value.op_values);
1618 if (call_value.val_values)
1619 XtFree((char*)call_value.val_values);
1620 if (call_value.sat_values)
1621 XtFree((char*)call_value.sat_values);
1622 if (call_value.hue_values)
1623 XtFree((char*)call_value.hue_values);
1624 }
LoadHardCodeDefaults(XmColorMapEditorWidget cmew,Boolean init)1625 void LoadHardCodeDefaults(XmColorMapEditorWidget cmew, Boolean init)
1626 {
1627 int i;
1628 ControlPoint cp_ptr;
1629 int n;
1630 Arg wargs[12];
1631
1632 if (!init)
1633 {
1634 for (i=0; i<4; i++)
1635 {
1636 DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
1637 cmew->color_map_editor.g.field[i]->map[0]->erase_gc);
1638 DrawLine(cmew->color_map_editor.g.field[i]->map[0]->line,
1639 cmew->color_map_editor.g.field[i]->map[0]->line->erase_gc);
1640 RemoveAllControlPoints(cmew->color_map_editor.g.field[i]);
1641 }
1642 }
1643 cmew->color_map_editor.value_minimum = 0.0;
1644 cmew->color_map_editor.value_maximum = 100.0;
1645 if (!init)
1646 {
1647 n=0;
1648 DoubleSetArg(wargs[n], XmNdValue, cmew->color_map_editor.value_minimum);n++;
1649 XtSetValues((Widget)cmew->color_map_editor.min_num, wargs, n);
1650 n=0;
1651 DoubleSetArg(wargs[n], XmNdValue, cmew->color_map_editor.value_maximum);n++;
1652 XtSetValues((Widget)cmew->color_map_editor.max_num, wargs, n);
1653 }
1654
1655 /* Add the 2 Hue Control Points */
1656 cp_ptr.level = 0.0;
1657 cp_ptr.value = 0.6666667;
1658 cp_ptr.wrap_around = 0;
1659 cp_ptr.x = 0;
1660 cp_ptr.y = 0;
1661 AddControlPoint( cmew->color_map_editor.g.field[0]->map[0],
1662 cp_ptr.level, cp_ptr.value, True );
1663
1664 cp_ptr.level = 1.0;
1665 cp_ptr.value = 0.0;
1666 cp_ptr.wrap_around = 0;
1667 cp_ptr.x = 0;
1668 cp_ptr.y = 0;
1669 AddControlPoint( cmew->color_map_editor.g.field[0]->map[0],
1670 cp_ptr.level, cp_ptr.value, True );
1671
1672 SetArrayValues(cmew->color_map_editor.g.field[0]->map[0],
1673 cmew->color_map_editor.g.field[0]->line[0]);
1674 SetLineCoords(cmew->color_map_editor.g.field[0]->line[0]);
1675
1676 /* Add the Saturation ControlPoints */
1677 cp_ptr.level = 0.0;
1678 cp_ptr.value = 1.0;
1679 cp_ptr.wrap_around = 0;
1680 cp_ptr.x = 0;
1681 cp_ptr.y = 0;
1682 AddControlPoint( cmew->color_map_editor.g.field[1]->map[0],
1683 cp_ptr.level, cp_ptr.value, True );
1684
1685 cp_ptr.level = 1.0;
1686 cp_ptr.value = 1.0;
1687 cp_ptr.wrap_around = 0;
1688 cp_ptr.x = 0;
1689 cp_ptr.y = 0;
1690 AddControlPoint( cmew->color_map_editor.g.field[1]->map[0],
1691 cp_ptr.level, cp_ptr.value, True );
1692
1693 SetArrayValues(cmew->color_map_editor.g.field[1]->map[0],
1694 cmew->color_map_editor.g.field[1]->line[0]);
1695 SetLineCoords(cmew->color_map_editor.g.field[1]->line[0]);
1696
1697 /* Add the Value ControlPoints */
1698 cp_ptr.level = 0.0;
1699 cp_ptr.value = 1.0;
1700 cp_ptr.wrap_around = 0;
1701 cp_ptr.x = 0;
1702 cp_ptr.y = 0;
1703 AddControlPoint( cmew->color_map_editor.g.field[2]->map[0],
1704 cp_ptr.level, cp_ptr.value, True );
1705
1706 cp_ptr.level = 1.0;
1707 cp_ptr.value = 1.0;
1708 cp_ptr.wrap_around = 0;
1709 cp_ptr.x = 0;
1710 cp_ptr.y = 0;
1711 AddControlPoint( cmew->color_map_editor.g.field[2]->map[0],
1712 cp_ptr.level, cp_ptr.value, True );
1713
1714 SetArrayValues(cmew->color_map_editor.g.field[2]->map[0],
1715 cmew->color_map_editor.g.field[2]->line[0]);
1716 SetLineCoords(cmew->color_map_editor.g.field[2]->line[0]);
1717
1718
1719 /* Add the Opacity ControlPoints */
1720 cp_ptr.level = 1.0;
1721 cp_ptr.value = 1.0;
1722 cp_ptr.wrap_around = 0;
1723 cp_ptr.x = 0;
1724 cp_ptr.y = 0;
1725 AddControlPoint( cmew->color_map_editor.g.field[3]->map[0],
1726 cp_ptr.level, cp_ptr.value, True );
1727
1728 cp_ptr.level = 0.0;
1729 cp_ptr.value = 1.0;
1730 cp_ptr.wrap_around = 0;
1731 cp_ptr.x = 0;
1732 cp_ptr.y = 0;
1733 AddControlPoint( cmew->color_map_editor.g.field[3]->map[0],
1734 cp_ptr.level, cp_ptr.value, True );
1735
1736 SetArrayValues(cmew->color_map_editor.g.field[3]->map[0],
1737 cmew->color_map_editor.g.field[3]->line[0]);
1738 SetLineCoords(cmew->color_map_editor.g.field[3]->line[0]);
1739
1740 for (i = 0; i < 4; i++)
1741 {
1742 if (!init)
1743 {
1744 DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
1745 cmew->color_map_editor.g.field[i]->map[0]->gc);
1746 DrawLine(cmew->color_map_editor.g.field[i]->line[0],
1747 cmew->color_map_editor.g.field[i]->map[0]->line->gc);
1748 cmew->color_map_editor.g.field[i]->user_callback(cmew->color_map_editor.g.field[i]);
1749 }
1750 }
1751 }
1752
LoadColormapFromFile(char * filename,XmColorMapEditorWidget cmew,Boolean init)1753 void LoadColormapFromFile(char *filename, XmColorMapEditorWidget cmew,
1754 Boolean init)
1755 {
1756 int i,j;
1757 ControlPoint cp_ptr;
1758 FILE *fp;
1759 int num_points, n;
1760 char *message;
1761 Arg wargs[12];
1762 double min, max;
1763
1764 if ( (fp = fopen(filename, "r")) == NULL)
1765 {
1766 message = XtMalloc(strlen(filename) + 64);
1767 strcpy(message, "Cannot open color map file \"");
1768 strcat(message, filename);
1769 strcat(message, "\".");
1770 XtWarning(message);
1771 XtFree(message);
1772
1773 LoadHardCodeDefaults(cmew, init);
1774 return;
1775 }
1776
1777 if (!init)
1778 {
1779 for (i=0; i<4; i++)
1780 {
1781 DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
1782 cmew->color_map_editor.g.field[i]->map[0]->erase_gc);
1783 DrawLine(cmew->color_map_editor.g.field[i]->map[0]->line,
1784 cmew->color_map_editor.g.field[i]->map[0]->line->erase_gc);
1785 RemoveAllControlPoints(cmew->color_map_editor.g.field[i]);
1786 SetArrayValues(cmew->color_map_editor.g.field[i]->map[0],
1787 cmew->color_map_editor.g.field[i]->line[0]);
1788 SetLineCoords(cmew->color_map_editor.g.field[i]->line[0]);
1789 DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
1790 cmew->color_map_editor.g.field[i]->map[0]->gc);
1791 DrawLine(cmew->color_map_editor.g.field[i]->line[0],
1792 cmew->color_map_editor.g.field[i]->map[0]->line->gc);
1793 }
1794 }
1795 if ( fscanf(fp,"%lg",&min) < 0 )
1796 {
1797 message = XtMalloc(strlen(filename) + 64);
1798 strcpy(message, "Error occurred while reading color map file \"");
1799 strcat(message, filename);
1800 strcat(message, "\".");
1801 XtWarning(message);
1802 XtFree(message);
1803
1804 LoadHardCodeDefaults(cmew, init);
1805 return;
1806 }
1807 if ( fscanf(fp,"%lg",&max) < 0 )
1808 {
1809 message = XtMalloc(strlen(filename) + 64);
1810 strcpy(message, "Error occurred while reading color map file \"");
1811 strcat(message, filename);
1812 strcat(message, "\".");
1813 XtWarning(message);
1814 XtFree(message);
1815
1816 LoadHardCodeDefaults(cmew, init);
1817 return;
1818 }
1819 if (!init)
1820 {
1821 if(cmew->color_map_editor.min_editable)
1822 {
1823 cmew->color_map_editor.value_minimum = min;
1824 n=0;
1825 DoubleSetArg(wargs[n], XmNdValue, min);n++;
1826 XtSetValues((Widget)cmew->color_map_editor.min_num, wargs, n);
1827 }
1828 if(cmew->color_map_editor.max_editable)
1829 {
1830 cmew->color_map_editor.value_maximum = max;
1831 n=0;
1832 DoubleSetArg(wargs[n], XmNdValue, max);n++;
1833 XtSetValues((Widget)cmew->color_map_editor.max_num, wargs, n);
1834 }
1835 }
1836
1837 for (i=0; i<3; i++) /* for all three fields */
1838 {
1839 if(!init)
1840 {
1841 DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
1842 cmew->color_map_editor.g.field[i]->map[0]->gc);
1843 DrawLine(cmew->color_map_editor.g.field[i]->map[0]->line,
1844 cmew->color_map_editor.g.field[i]->map[0]->line->gc);
1845 }
1846
1847 if ( fscanf(fp,"%d",&num_points) < 0 )
1848 {
1849 message = XtMalloc(strlen(filename) + 64);
1850 strcpy(message, "Error occurred while reading color map file \"");
1851 strcat(message, filename);
1852 strcat(message, "\".");
1853 XtWarning(message);
1854 XtFree(message);
1855
1856 LoadHardCodeDefaults(cmew, init);
1857 return;
1858 }
1859 for (j=0;j < num_points; j++)
1860 {
1861 if ( fscanf(fp,"%lg",&(cp_ptr.level)) < 0 )
1862 {
1863 message = XtMalloc(strlen(filename) + 64);
1864 strcpy(message, "Error occurred while reading color map file \"");
1865 strcat(message, filename);
1866 strcat(message, "\".");
1867 XtWarning(message);
1868 XtFree(message);
1869
1870 LoadHardCodeDefaults(cmew, init);
1871 return;
1872 }
1873 if ( fscanf(fp,"%lg",&(cp_ptr.value)) < 0 )
1874 {
1875 message = XtMalloc(strlen(filename) + 64);
1876 strcpy(message, "Error occurred while reading color map file \"");
1877 strcat(message, filename);
1878 strcat(message, "\".");
1879 XtWarning(message);
1880 XtFree(message);
1881
1882 LoadHardCodeDefaults(cmew, init);
1883 return;
1884 }
1885 if ( fscanf(fp,"%d",&(cp_ptr.wrap_around)) < 0 )
1886 {
1887 message = XtMalloc(strlen(filename) + 64);
1888 strcpy(message, "Error occurred while reading color map file \"");
1889 strcat(message, filename);
1890 strcat(message, "\".");
1891 XtWarning(message);
1892 XtFree(message);
1893
1894 LoadHardCodeDefaults(cmew, init);
1895 return;
1896 }
1897 if ( fscanf(fp,"%d",&(cp_ptr.x)) < 0 )
1898 {
1899 message = XtMalloc(strlen(filename) + 64);
1900 strcpy(message, "Error occurred while reading color map file \"");
1901 strcat(message, filename);
1902 strcat(message, "\".");
1903 XtWarning(message);
1904 XtFree(message);
1905
1906 LoadHardCodeDefaults(cmew, init);
1907 return;
1908 }
1909 if ( fscanf(fp,"%d",&(cp_ptr.y)) < 0 )
1910 {
1911 message = XtMalloc(strlen(filename) + 64);
1912 strcpy(message, "Error occurred while reading color map file \"");
1913 strcat(message, filename);
1914 strcat(message, "\".");
1915 XtWarning(message);
1916 XtFree(message);
1917
1918 LoadHardCodeDefaults(cmew, init);
1919 return;
1920 }
1921 AddControlPoint( cmew->color_map_editor.g.field[i]->map[0],
1922 cp_ptr.level, cp_ptr.value, True );
1923 SetArrayValues(cmew->color_map_editor.g.field[i]->map[0],
1924 cmew->color_map_editor.g.field[i]->line[0]);
1925 SetLineCoords(cmew->color_map_editor.g.field[i]->line[0]);
1926 }
1927 if (!init)
1928 {
1929 DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
1930 cmew->color_map_editor.g.field[i]->map[0]->gc);
1931 DrawLine(cmew->color_map_editor.g.field[i]->line[0],
1932 cmew->color_map_editor.g.field[i]->map[0]->line->gc);
1933 cmew->color_map_editor.g.field[i]->user_callback(cmew->color_map_editor.g.field[i]);
1934 }
1935 }
1936
1937 /* Handle Opacity separately for backwards comaptabilty with old
1938 colormap files */
1939 i = 3;
1940 if(!init)
1941 {
1942 DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
1943 cmew->color_map_editor.g.field[i]->map[0]->gc);
1944 DrawLine(cmew->color_map_editor.g.field[i]->map[0]->line,
1945 cmew->color_map_editor.g.field[i]->map[0]->line->gc);
1946 }
1947
1948 if ( fscanf(fp,"%d",&num_points) < 0 )
1949 {
1950 num_points = 1;
1951 cp_ptr.level = 1.0;
1952 cp_ptr.value = 1.0;
1953 AddControlPoint( cmew->color_map_editor.g.field[i]->map[0],
1954 cp_ptr.level, cp_ptr.value, True );
1955 SetArrayValues(cmew->color_map_editor.g.field[i]->map[0],
1956 cmew->color_map_editor.g.field[i]->line[0]);
1957 SetLineCoords(cmew->color_map_editor.g.field[i]->line[0]);
1958 }
1959 else
1960 {
1961 for (j=0;j < num_points; j++)
1962 {
1963 if ( fscanf(fp,"%lg",&(cp_ptr.level)) < 0 )
1964 {
1965 message = XtMalloc(strlen(filename) + 64);
1966 strcpy(message,
1967 "Error occurred while reading color map file \"");
1968 strcat(message, filename);
1969 strcat(message, "\".");
1970 XtWarning(message);
1971 XtFree(message);
1972
1973 LoadHardCodeDefaults(cmew, init);
1974 return;
1975 }
1976 if ( fscanf(fp,"%lg",&(cp_ptr.value)) < 0 )
1977 {
1978 message = XtMalloc(strlen(filename) + 64);
1979 strcpy(message,
1980 "Error occurred while reading color map file \"");
1981 strcat(message, filename);
1982 strcat(message, "\".");
1983 XtWarning(message);
1984 XtFree(message);
1985
1986 LoadHardCodeDefaults(cmew, init);
1987 return;
1988 }
1989 if ( fscanf(fp,"%d",&(cp_ptr.wrap_around)) < 0 )
1990 {
1991 message = XtMalloc(strlen(filename) + 64);
1992 strcpy(message,
1993 "Error occurred while reading color map file \"");
1994 strcat(message, filename);
1995 strcat(message, "\".");
1996 XtWarning(message);
1997 XtFree(message);
1998
1999 LoadHardCodeDefaults(cmew, init);
2000 return;
2001 }
2002 if ( fscanf(fp,"%d",&(cp_ptr.x)) < 0 )
2003 {
2004 message = XtMalloc(strlen(filename) + 64);
2005 strcpy(message,
2006 "Error occurred while reading color map file \"");
2007 strcat(message, filename);
2008 strcat(message, "\".");
2009 XtWarning(message);
2010 XtFree(message);
2011
2012 LoadHardCodeDefaults(cmew, init);
2013 return;
2014 }
2015 if ( fscanf(fp,"%d",&(cp_ptr.y)) < 0 )
2016 {
2017 message = XtMalloc(strlen(filename) + 64);
2018 strcpy(message,
2019 "Error occurred while reading color map file \"");
2020 strcat(message, filename);
2021 strcat(message, "\".");
2022 XtWarning(message);
2023 XtFree(message);
2024
2025 LoadHardCodeDefaults(cmew, init);
2026 return;
2027 }
2028 AddControlPoint( cmew->color_map_editor.g.field[i]->map[0],
2029 cp_ptr.level, cp_ptr.value, True );
2030 SetArrayValues(cmew->color_map_editor.g.field[i]->map[0],
2031 cmew->color_map_editor.g.field[i]->line[0]);
2032 SetLineCoords(cmew->color_map_editor.g.field[i]->line[0]);
2033 }
2034 }
2035 if (!init)
2036 {
2037 DrawControlBoxes(cmew->color_map_editor.g.field[i]->map[0],
2038 cmew->color_map_editor.g.field[i]->map[0]->gc);
2039 DrawLine(cmew->color_map_editor.g.field[i]->line[0],
2040 cmew->color_map_editor.g.field[i]->map[0]->line->gc);
2041 cmew->color_map_editor.g.field[i]->user_callback(cmew->color_map_editor.g.field[i]);
2042 }
2043 if (fclose(fp) != 0)
2044 {
2045 message = XtMalloc(strlen(filename) + 64);
2046 strcpy(message,
2047 "Cannot close color map file \"");
2048 strcat(message, filename);
2049 strcat(message, "\".");
2050 XtWarning(message);
2051 XtFree(message);
2052
2053 LoadHardCodeDefaults(cmew, init);
2054 return;
2055 }
2056 }
XmColorMapEditorLoad(Widget cmew,double min,double max,int nhues,double * hues,int nsats,double * sats,int nvals,double * vals,int nopat,double * opat)2057 void XmColorMapEditorLoad(Widget cmew, double min, double max,
2058 int nhues, double *hues,
2059 int nsats, double *sats,
2060 int nvals, double *vals,
2061 int nopat, double *opat)
2062 {
2063 int i;
2064 double norm, range=0;
2065 Boolean skip_normalize;
2066 #ifdef PASSDOUBLEVALUE
2067 XtArgVal dx_l;
2068 #endif
2069
2070 XmColorMapEditorWidget w = (XmColorMapEditorWidget)cmew;
2071
2072 /* Erase the old Control points */
2073 if (XtIsRealized((Widget)w))
2074 {
2075 for (i=0; i<4; i++)
2076 {
2077 DrawControlBoxes(w->color_map_editor.g.field[i]->map[0],
2078 w->color_map_editor.g.field[i]->map[0]->erase_gc);
2079 DrawLine(w->color_map_editor.g.field[i]->map[0]->line,
2080 w->color_map_editor.g.field[i]->map[0]->line->erase_gc);
2081 RemoveAllControlPoints(w->color_map_editor.g.field[i]);
2082 SetArrayValues(w->color_map_editor.g.field[i]->map[0],
2083 w->color_map_editor.g.field[i]->line[0]);
2084 SetLineCoords(w->color_map_editor.g.field[i]->line[0]);
2085 DrawControlBoxes(w->color_map_editor.g.field[i]->map[0],
2086 w->color_map_editor.g.field[i]->map[0]->gc);
2087 DrawLine(w->color_map_editor.g.field[i]->line[0],
2088 w->color_map_editor.g.field[i]->map[0]->line->gc);
2089 }
2090 }
2091
2092 if(w->color_map_editor.min_editable)
2093 {
2094 w->color_map_editor.value_minimum = min;
2095 XtVaSetValues((Widget)w->color_map_editor.min_num,
2096 XmNdValue, DoubleVal(min, dx_l), NULL);
2097 }
2098 if(w->color_map_editor.max_editable)
2099 {
2100 w->color_map_editor.value_maximum = max;
2101 XtVaSetValues((Widget)w->color_map_editor.max_num,
2102 XmNdValue, DoubleVal(max, dx_l), NULL);
2103 }
2104
2105 if(XtIsRealized((Widget)w))
2106 for(i = 0; i < 4; i++)
2107 RemoveAllControlPoints(w->color_map_editor.g.field[i]);
2108
2109 #if Comment
2110 if (min == max) {
2111 skip_normalize = True;
2112 } else {
2113 skip_normalize = False;
2114 range = max - min;
2115 }
2116 #else
2117 skip_normalize = True;
2118 #endif
2119
2120 for(i = 0; i < nhues; i++)
2121 {
2122 norm = (skip_normalize ? *hues : (*hues - min) / range) ;
2123 hues++;
2124 AddControlPoint(w->color_map_editor.g.field[HUE]->map[0],
2125 norm,
2126 *(hues++),
2127 True );
2128 }
2129 for(i = 0; i < nsats; i++)
2130 {
2131 norm = (skip_normalize ? *sats : (*sats - min) / range) ;
2132 sats++;
2133 AddControlPoint(w->color_map_editor.g.field[SATURATION]->map[0],
2134 norm,
2135 *(sats++),
2136 True );
2137 }
2138 for(i = 0; i < nvals; i++)
2139 {
2140 norm = (skip_normalize ? *vals : (*vals - min) / range) ;
2141 vals++;
2142 AddControlPoint(w->color_map_editor.g.field[VALUE]->map[0],
2143 norm,
2144 *(vals++),
2145 True );
2146 }
2147 for(i = 0; i < nopat; i++)
2148 {
2149 norm = (skip_normalize ? *opat : (*opat - min) / range) ;
2150 opat++;
2151 AddControlPoint(w->color_map_editor.g.field[OPACITY]->map[0],
2152 norm,
2153 *(opat++),
2154 True );
2155 }
2156
2157 if(XtIsRealized((Widget)w))
2158 {
2159 for(i = 0; i < 4; i++)
2160 {
2161 SetArrayValues(w->color_map_editor.g.field[i]->map[0],
2162 w->color_map_editor.g.field[i]->line[0]);
2163 SetLineCoords(w->color_map_editor.g.field[i]->line[0]);
2164
2165 DrawControlBoxes(w->color_map_editor.g.field[i]->map[0],
2166 w->color_map_editor.g.field[i]->map[0]->gc);
2167 DrawLine(w->color_map_editor.g.field[i]->line[0],
2168 w->color_map_editor.g.field[i]->map[0]->line->gc);
2169 }
2170 w->color_map_editor.g.field[0]->user_callback(w->color_map_editor.g.field[0]);
2171 }
2172 }
2173
RecalculateControlPointLevels(XmColorMapEditorWidget cmew)2174 void RecalculateControlPointLevels(XmColorMapEditorWidget cmew)
2175 {
2176 int i, j;
2177
2178 for(i = 0; i < 4; i++)
2179 {
2180 for (j = 0; j < cmew->color_map_editor.g.field[i]->map[0]->num_points;
2181 j++)
2182 {
2183 MoveControlPoint(
2184 cmew->color_map_editor.g.field[i]->map[0],
2185 j,
2186 cmew->color_map_editor.g.field[i]->map[0]->points[j].x,
2187 cmew->color_map_editor.g.field[i]->map[0]->points[j].y);
2188 }
2189 }
2190 }
CMESawToothWave(Widget w,int nsteps,Boolean start_on_left,Boolean use_selected)2191 void CMESawToothWave(Widget w, int nsteps, Boolean start_on_left,
2192 Boolean use_selected)
2193 {
2194 int i;
2195 double level;
2196 double value;
2197 double tmp_value;
2198 double level_inc;
2199 XmColorMapEditorWidget cmew = (XmColorMapEditorWidget)w;
2200 ControlMap *map;
2201 double real_min_level;
2202 double real_max_level;
2203 int num_selected;
2204 int pt_index1=0;
2205 int pt_index2=0;
2206 int field;
2207 double min_value;
2208 double max_value;
2209 double min_level;
2210 double max_level;
2211
2212 PushUndoPoints(cmew);
2213 for(field = 0; field < 4; field++)
2214 {
2215 if(!cmew->color_map_editor.g.field[field]->map[0]->toggle_on) continue;
2216 map = cmew->color_map_editor.g.field[field]->map[0];
2217 num_selected = 0;
2218 for (i = 0; i < map->num_points; i++)
2219 if(map->points[i].multi_point_grab)
2220 {
2221 num_selected++;
2222 if(num_selected == 1)
2223 pt_index1 = i;
2224 else if(num_selected > 1)
2225 pt_index2 = i;
2226 }
2227 if(use_selected && (num_selected < 2) )
2228 {
2229 XtWarning("There must be at least 2 selected Control Points");
2230 return;
2231 }
2232
2233 /*
2234 * Erase the control points and lines
2235 */
2236 DrawControlBoxes(cmew->color_map_editor.g.field[field]->map[0],
2237 cmew->color_map_editor.g.field[field]->map[0]->erase_gc);
2238 DrawLine(cmew->color_map_editor.g.field[field]->map[0]->line,
2239 cmew->color_map_editor.g.field[field]->map[0]->line->erase_gc);
2240
2241 if(use_selected)
2242 {
2243 min_level = map->points[pt_index1].level;
2244 min_value = map->points[pt_index1].value;
2245 max_level = map->points[pt_index2].level;
2246 max_value = map->points[pt_index2].value;
2247 }
2248 else
2249 {
2250 min_level = 0.0;
2251 max_level = 1.0;
2252 min_value = 0.0;
2253 if(field == 0)
2254 max_value = 0.66666;
2255 else
2256 max_value = 1.0;
2257 }
2258 real_min_level = MIN(min_level, max_level);
2259 real_max_level = MAX(min_level, max_level);
2260 if(!use_selected)
2261 {
2262 RemoveAllControlPoints(map->field);
2263 }
2264 else
2265 {
2266 for (i = map->num_points - 1; i >= 0 ; i--)
2267 {
2268 if ((map->points[i].level <= real_max_level) &&
2269 (map->points[i].level >= real_min_level) )
2270 {
2271 if( (i >= pt_index1) && (i <= pt_index2) )
2272 RemoveControlPoint(map, i);
2273 }
2274 }
2275 }
2276
2277 level_inc = (max_level - min_level)/(nsteps-1);
2278
2279 /*
2280 * Insure that the min_value < max_value
2281 */
2282 if(min_value > max_value)
2283 {
2284 tmp_value = min_value;
2285 min_value = max_value;
2286 max_value = tmp_value;
2287 }
2288
2289 for(i = 0; i < nsteps; i++)
2290 {
2291 level = min_level + (i * level_inc);
2292 if(start_on_left)
2293 value = min_value;
2294 else
2295 value = max_value;
2296 AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2297 level, value, True );
2298 if(start_on_left)
2299 value = max_value;
2300 else
2301 value = min_value;
2302 AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2303 level, value, True );
2304 }
2305 SetArrayValues(cmew->color_map_editor.g.field[field]->map[0],
2306 cmew->color_map_editor.g.field[field]->line[0]);
2307 SetLineCoords(cmew->color_map_editor.g.field[field]->line[0]);
2308 DeselectAllPoints(cmew->color_map_editor.g.field[field]->map[0]);
2309 DrawControlBoxes(cmew->color_map_editor.g.field[field]->map[0],
2310 cmew->color_map_editor.g.field[field]->map[0]->gc);
2311 DrawLine(cmew->color_map_editor.g.field[field]->line[0],
2312 cmew->color_map_editor.g.field[field]->map[0]->line->gc);
2313 cmew->color_map_editor.g.field[field]->user_callback(cmew->color_map_editor.g.field[field]);
2314 }
2315 if(cmew->color_map_editor.g.field[0]->map[0]->toggle_on ||
2316 cmew->color_map_editor.g.field[1]->map[0]->toggle_on ||
2317 cmew->color_map_editor.g.field[2]->map[0]->toggle_on ||
2318 cmew->color_map_editor.g.field[3]->map[0]->toggle_on)
2319 CallActivateCallback(cmew, XmCR_MODIFIED);
2320 PrintAllControlPoints(cmew);
2321 }
2322
CMESquareWave(Widget w,int nsteps,Boolean start_on_left,Boolean use_selected)2323 void CMESquareWave(Widget w, int nsteps, Boolean start_on_left,
2324 Boolean use_selected)
2325 {
2326 int i;
2327 double level;
2328 double value;
2329 double tmp_value;
2330 double level_inc;
2331 XmColorMapEditorWidget cmew = (XmColorMapEditorWidget)w;
2332 ControlMap *map=NULL;
2333 double real_min_level=0;
2334 double real_max_level=0;
2335 int num_selected;
2336 int pt_index1=0;
2337 int pt_index2=0;
2338 int field;
2339 double min_value=0;
2340 double max_value=0;
2341 double min_level=0;
2342 double max_level=0;
2343
2344 PushUndoPoints(cmew);
2345 for(field = 0; field < 4; field++)
2346 {
2347 if(!cmew->color_map_editor.g.field[field]->map[0]->toggle_on) continue;
2348 map = cmew->color_map_editor.g.field[field]->map[0];
2349 num_selected = 0;
2350 for (i = 0; i < map->num_points; i++)
2351 if(map->points[i].multi_point_grab)
2352 {
2353 num_selected++;
2354 if(num_selected == 1)
2355 pt_index1 = i;
2356 else if(num_selected > 1)
2357 pt_index2 = i;
2358 }
2359 if(use_selected && (num_selected < 2) )
2360 {
2361 XtWarning("There must be at least 2 selected Control Points");
2362 return;
2363 }
2364
2365 if(use_selected)
2366 {
2367 min_level = map->points[pt_index1].level;
2368 min_value = map->points[pt_index1].value;
2369 max_level = map->points[pt_index2].level;
2370 max_value = map->points[pt_index2].value;
2371 }
2372 else
2373 {
2374 min_level = 0.0;
2375 max_level = 1.0;
2376 min_value = 0.0;
2377 if(field == 0)
2378 max_value = 0.66666;
2379 else
2380 max_value = 1.0;
2381 }
2382 real_min_level = MIN(min_level, max_level);
2383 real_max_level = MAX(min_level, max_level);
2384 break;
2385 }
2386 /*
2387 * Erase the control points and lines
2388 */
2389 DrawControlBoxes(cmew->color_map_editor.g.field[field]->map[0],
2390 cmew->color_map_editor.g.field[field]->map[0]->erase_gc);
2391 DrawLine(cmew->color_map_editor.g.field[field]->map[0]->line,
2392 cmew->color_map_editor.g.field[field]->map[0]->line->erase_gc);
2393
2394 if(!use_selected)
2395 {
2396 RemoveAllControlPoints(map->field);
2397 }
2398 else
2399 {
2400 for (i = map->num_points - 1; i >= 0 ; i--)
2401 {
2402 if ((map->points[i].level <= real_max_level) &&
2403 (map->points[i].level >= real_min_level) )
2404 {
2405 if( (i >= pt_index1) && (i <= pt_index2) )
2406 RemoveControlPoint(map, i);
2407 }
2408 }
2409 }
2410 level_inc = (max_level - min_level)/(nsteps-1);
2411
2412 /*
2413 * Insure that the min_value < max_value
2414 */
2415 if(min_value > max_value)
2416 {
2417 tmp_value = min_value;
2418 min_value = max_value;
2419 max_value = tmp_value;
2420 }
2421 if(start_on_left)
2422 value = min_value;
2423 else
2424 value = max_value;
2425 for(i = 0; i < nsteps; i++)
2426 {
2427 level = min_level + (i * level_inc);
2428 AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2429 level, value, True );
2430 if(value == min_value)
2431 {
2432 value = max_value;
2433 }
2434 else
2435 {
2436 value = min_value;
2437 }
2438 AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2439 level, value, True );
2440 }
2441 SetArrayValues(cmew->color_map_editor.g.field[field]->map[0],
2442 cmew->color_map_editor.g.field[field]->line[0]);
2443 SetLineCoords(cmew->color_map_editor.g.field[field]->line[0]);
2444 DeselectAllPoints(cmew->color_map_editor.g.field[field]->map[0]);
2445 DrawControlBoxes(cmew->color_map_editor.g.field[field]->map[0],
2446 cmew->color_map_editor.g.field[field]->map[0]->gc);
2447 DrawLine(cmew->color_map_editor.g.field[field]->line[0],
2448 cmew->color_map_editor.g.field[field]->map[0]->line->gc);
2449 cmew->color_map_editor.g.field[field]->user_callback(cmew->color_map_editor.g.field[field]);
2450 if(cmew->color_map_editor.g.field[0]->map[0]->toggle_on ||
2451 cmew->color_map_editor.g.field[1]->map[0]->toggle_on ||
2452 cmew->color_map_editor.g.field[2]->map[0]->toggle_on ||
2453 cmew->color_map_editor.g.field[3]->map[0]->toggle_on)
2454 CallActivateCallback(cmew, XmCR_MODIFIED);
2455 PrintAllControlPoints(cmew);
2456 }
2457
CMEStep(Widget w,int nsteps,Boolean use_selected)2458 void CMEStep(Widget w, int nsteps, Boolean use_selected)
2459 {
2460 int i;
2461 double level;
2462 double value;
2463 double inc_level;
2464 double inc_value;
2465 XmColorMapEditorWidget cmew = (XmColorMapEditorWidget)w;
2466 ControlMap *map;
2467 double real_min_level;
2468 double real_max_level;
2469 double real_min_value;
2470 double real_max_value;
2471 int num_selected;
2472 int pt_index1=0;
2473 int pt_index2=0;
2474 int field;
2475 double min_value;
2476 double max_value;
2477 double min_level;
2478 double max_level;
2479
2480 PushUndoPoints(cmew);
2481 for(field = 0; field < 4; field++)
2482 {
2483 if(!cmew->color_map_editor.g.field[field]->map[0]->toggle_on) continue;
2484 map = cmew->color_map_editor.g.field[field]->map[0];
2485 num_selected = 0;
2486 for (i = 0; i < map->num_points; i++)
2487 if(map->points[i].multi_point_grab)
2488 {
2489 num_selected++;
2490 if(num_selected == 1)
2491 pt_index1 = i;
2492 else if(num_selected > 1)
2493 pt_index2 = i;
2494 }
2495
2496 if( use_selected && (num_selected < 2) )
2497 {
2498 XtWarning("There must be at least 2 selected Control Points");
2499 return;
2500 }
2501
2502 /*
2503 * Erase the control points and lines
2504 */
2505 DrawControlBoxes(cmew->color_map_editor.g.field[field]->map[0],
2506 cmew->color_map_editor.g.field[field]->map[0]->erase_gc);
2507 DrawLine(cmew->color_map_editor.g.field[field]->map[0]->line,
2508 cmew->color_map_editor.g.field[field]->map[0]->line->erase_gc);
2509
2510 if(use_selected)
2511 {
2512 min_level = map->points[pt_index1].level;
2513 min_value = map->points[pt_index1].value;
2514 max_level = map->points[pt_index2].level;
2515 max_value = map->points[pt_index2].value;
2516 }
2517 else
2518 {
2519 min_level = 0.0;
2520 max_level = 1.0;
2521 if(field == 0)
2522 {
2523 min_value = 0.66666;
2524 max_value = 0.0;
2525 }
2526 else
2527 {
2528 min_value = 0.0;
2529 max_value = 1.0;
2530 }
2531 }
2532 real_min_level = MIN(min_level, max_level);
2533 real_max_level = MAX(min_level, max_level);
2534 real_min_value = MIN(min_value, max_value);
2535 real_max_value = MAX(min_value, max_value);
2536 if(!use_selected)
2537 {
2538 RemoveAllControlPoints(map->field);
2539 }
2540 else
2541 {
2542 for (i = map->num_points - 1; i >= 0 ; i--)
2543 {
2544 if ((map->points[i].level <= real_max_level) &&
2545 (map->points[i].level >= real_min_level) )
2546 {
2547 if( (i >= pt_index1) && (i <= pt_index2) )
2548 RemoveControlPoint(map, i);
2549 }
2550 }
2551 }
2552
2553 level = min_level;
2554 value = min_value;
2555 inc_level = (max_level - min_level)/(nsteps+1);
2556 inc_value = (max_value - min_value)/nsteps;
2557
2558 /*
2559 * Add the first point
2560 */
2561 AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2562 level, value, True );
2563 level += inc_level;
2564
2565 for(i = 0; i < nsteps; i++)
2566 {
2567 /*
2568 * Deal with rounding errors.
2569 */
2570 if(level > real_max_level) level = real_max_level;
2571 if(level < real_min_level) level = real_min_level;
2572 /*
2573 * If max_level < min_level, we have to reverse the order we add
2574 * the points in at each level, since a point is considered to be
2575 * "below" when added at the same level.
2576 */
2577 if(max_level < min_level)
2578 value += inc_value;
2579 AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2580 level, value, True );
2581 if(max_level < min_level)
2582 value -= inc_value;
2583 else
2584 value += inc_value;
2585 if(value > real_max_value) value = real_max_value;
2586 if(value < real_min_value) value = real_min_value;
2587 AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2588 level, value, True );
2589 if(max_level < min_level)
2590 value += inc_value;
2591 level += inc_level;
2592 }
2593 /*
2594 * Add the last point
2595 */
2596 AddControlPoint( cmew->color_map_editor.g.field[field]->map[0],
2597 max_level, value, False );
2598
2599 SetArrayValues(cmew->color_map_editor.g.field[field]->map[0],
2600 cmew->color_map_editor.g.field[field]->line[0]);
2601 SetLineCoords(cmew->color_map_editor.g.field[field]->line[0]);
2602 DeselectAllPoints(cmew->color_map_editor.g.field[field]->map[0]);
2603 DrawControlBoxes(cmew->color_map_editor.g.field[field]->map[0],
2604 cmew->color_map_editor.g.field[field]->map[0]->gc);
2605 DrawLine(cmew->color_map_editor.g.field[field]->line[0],
2606 cmew->color_map_editor.g.field[field]->map[0]->line->gc);
2607 cmew->color_map_editor.g.field[field]->user_callback(cmew->color_map_editor.g.field[field]);
2608 }
2609 if(cmew->color_map_editor.g.field[0]->map[0]->toggle_on ||
2610 cmew->color_map_editor.g.field[1]->map[0]->toggle_on ||
2611 cmew->color_map_editor.g.field[2]->map[0]->toggle_on ||
2612 cmew->color_map_editor.g.field[3]->map[0]->toggle_on)
2613 CallActivateCallback(cmew, XmCR_MODIFIED);
2614 PrintAllControlPoints(cmew);
2615 }
PrintAllControlPoints(XmColorMapEditorWidget cmew)2616 void PrintAllControlPoints(XmColorMapEditorWidget cmew)
2617 {
2618 ControlMap *map;
2619 int i;
2620 int j;
2621 Dimension width;
2622 Dimension height;
2623
2624
2625 XtVaGetValues(cmew->color_map_editor.grid_w,
2626 XmNwidth, &width,
2627 XmNheight, &height,
2628 NULL);
2629
2630 XClearArea(XtDisplay(cmew),
2631 XtWindow(cmew->color_map_editor.grid_w),
2632 0, 0, width, height, False);
2633
2634 if(cmew->color_map_editor.print_points == XmPRINT_NONE) return;
2635
2636 for(i = 0; i < 4; i++)
2637 {
2638 map = cmew->color_map_editor.g.field[i]->map[0];
2639 if(!map->toggle_on) continue;
2640 for(j = 0; j < map->num_points; j++)
2641 {
2642 if(cmew->color_map_editor.print_points == XmPRINT_SELECTED)
2643 {
2644 if( (map->points[j].multi_point_grab) ||
2645 (j == map->grabbed) )
2646 {
2647 PrintControlPoint(map, j);
2648 }
2649 }
2650 else if(cmew->color_map_editor.print_points == XmPRINT_ALL)
2651 {
2652 PrintControlPoint(map, j);
2653 }
2654 }
2655 }
2656 }
2657
PrintControlPoint(ControlMap * map,int point_num)2658 void PrintControlPoint(ControlMap *map, int point_num)
2659 {
2660 int direction;
2661 int ascent;
2662 int descent;
2663 XCharStruct overall;
2664 char string[256];
2665 XmColorMapEditorWidget cmew;
2666 Dimension width;
2667 Position x;
2668 Position y;
2669
2670 cmew = map->field->cmew;
2671 XtVaGetValues(cmew->color_map_editor.grid_w,
2672 XmNwidth, &width,
2673 NULL);
2674
2675 sprintf(string, "%g", cmew->color_map_editor.value_minimum +
2676 (cmew->color_map_editor.value_maximum -
2677 cmew->color_map_editor.value_minimum) *
2678 map->points[point_num].level);
2679
2680 XTextExtents(cmew->color_map_editor.font, string, strlen(string),
2681 &direction, &ascent, &descent, &overall);
2682 x = (width - overall.width) - 5;
2683 y = map->points[point_num].y;
2684 if( (y - (ascent + descent)) < 0)
2685 {
2686 y = ascent + descent;
2687 }
2688 XDrawString(XtDisplay(cmew),
2689 XtWindow(cmew->color_map_editor.grid_w),
2690 cmew->color_map_editor.fontgc,
2691 x,
2692 y,
2693 string, strlen(string));
2694
2695 }
2696
PointExists(ControlMap * map,double level,double value)2697 static Boolean PointExists(ControlMap *map, double level, double value)
2698 {
2699 int i;
2700
2701 for(i = 0; i < map->num_points; i++)
2702 {
2703 if( (map->points[i].level == level) &&
2704 (map->points[i].value == value) )
2705 return True;
2706 }
2707 return False;
2708 }
DeselectAllPoints(ControlMap * map)2709 static void DeselectAllPoints(ControlMap *map)
2710 {
2711 int i;
2712 for(i = 0; i < map->num_points; i++)
2713 {
2714 map->points[i].multi_point_grab = False;
2715 }
2716 map->grabbed = -1;
2717 }
2718