home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / ccs / ccs-11tl.lha / lbl / xview / segal / paint.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-24  |  21.0 KB  |  893 lines

  1. /*
  2.  *    paint.c - for use with Segal
  3.  *
  4.  *    By Bryan Skene
  5.  *
  6.  */
  7.  
  8. #include "common.h"
  9.  
  10. #define MAX_PCANV_WIDTH        512
  11. #define MAX_PCANV_HEIGHT    512
  12.  
  13. /*********************************************/
  14. void
  15. paint_setup()
  16. {
  17.     void change_cursor_proc();
  18.     int max_frames();
  19.  
  20.     int canv_w, canv_h, paint_w;
  21.  
  22.     change_cursor_proc();
  23.  
  24.     win[WIN_PAINT].canv_x = (int) xv_get(Paint_win_paint->canvas, XV_X, NULL);
  25.     win[WIN_PAINT].canv_y = (int) xv_get(Paint_win_paint->canvas, XV_Y, NULL);
  26.     win[WIN_PAINT].img_r = win[win[WIN_PAINT].aspect].img_r;
  27.     win[WIN_PAINT].img_c = win[win[WIN_PAINT].aspect].img_c;
  28.     win[WIN_PAINT].img_size = win[win[WIN_PAINT].aspect].img_size;
  29.     RANGE(win[WIN_PAINT].f, 0, max_frames(win[WIN_PAINT].aspect))
  30.  
  31.     win[WIN_PAINT].canv_w = win[WIN_PAINT].img_c * win[WIN_PAINT].zoom_mag;
  32.     win[WIN_PAINT].canv_h = win[WIN_PAINT].img_r * win[WIN_PAINT].zoom_mag;
  33.  
  34.     canv_w = win[WIN_PAINT].canv_w;
  35.     canv_h = win[WIN_PAINT].canv_h;
  36.  
  37.     RANGE(win[WIN_PAINT].canv_w, 0, MAX_PCANV_WIDTH)
  38.     RANGE(win[WIN_PAINT].canv_h, 0, MAX_PCANV_HEIGHT)
  39.  
  40.     /* paint window needs to be showing for these things to occur */
  41.     xv_set(Paint_win_paint->win_paint,
  42.         XV_SHOW, TRUE,
  43.         NULL);
  44.  
  45.     if(canv_w <= MAX_PCANV_WIDTH) xv_destroy_safe(win[WIN_PAINT].h_sbar);
  46.     if(canv_h <= MAX_PCANV_HEIGHT) xv_destroy_safe(win[WIN_PAINT].v_sbar);
  47.  
  48.     xv_set(Paint_win_paint->set_aspect,
  49.         XV_SHOW, TRUE,
  50.         NULL);
  51.     
  52.     xv_set(Paint_win_paint->set_zoom_mag,
  53.         XV_SHOW, TRUE,
  54.         NULL);
  55.  
  56.     if(segal.r3d) {
  57.         xv_set(Paint_win_paint->set_paint_frame,
  58.             XV_SHOW, TRUE,
  59.             XV_X, win[WIN_PAINT].canv_x + win[WIN_PAINT].canv_w - 90,
  60.             PANEL_MAX_VALUE, max_frames(win[WIN_PAINT].aspect),
  61.             PANEL_SLIDER_WIDTH, win[WIN_PAINT].canv_h,
  62.             PANEL_VALUE, win[WIN_PAINT].f,
  63.             NULL);
  64.     }
  65.     else {
  66.         xv_set(Paint_win_paint->set_paint_frame,
  67.             XV_SHOW, FALSE,
  68.             NULL);
  69.     }
  70.  
  71.  
  72.     xv_set(Paint_win_paint->canvas,
  73.         XV_SHOW, TRUE,
  74.         XV_WIDTH, win[WIN_PAINT].canv_w,
  75.         XV_HEIGHT, win[WIN_PAINT].canv_h,
  76.         CANVAS_WIDTH, canv_w,
  77.         CANVAS_HEIGHT, canv_h,
  78.         CANVAS_AUTO_SHRINK, FALSE,
  79.         CANVAS_AUTO_EXPAND, FALSE,
  80.         NULL);
  81.  
  82.     if(canv_w > MAX_PCANV_WIDTH)
  83.     win[WIN_PAINT].h_sbar =
  84.     (Scrollbar) xv_create(Paint_win_paint->canvas, SCROLLBAR,
  85.         SCROLLBAR_DIRECTION, SCROLLBAR_HORIZONTAL,
  86.         SCROLLBAR_PIXELS_PER_UNIT, win[WIN_PAINT].zoom_mag,
  87.         SCROLLBAR_OBJECT_LENGTH, win[WIN_PAINT].img_c,
  88.         SCROLLBAR_PAGE_LENGTH, MAX_PCANV_WIDTH,
  89.         SCROLLBAR_VIEW_LENGTH, MAX_PCANV_WIDTH,
  90.         NULL);
  91.  
  92.     if(canv_h > MAX_PCANV_HEIGHT)
  93.     win[WIN_PAINT].v_sbar =
  94.     (Scrollbar) xv_create(Paint_win_paint->canvas, SCROLLBAR,
  95.         SCROLLBAR_DIRECTION, SCROLLBAR_VERTICAL,
  96.         SCROLLBAR_PIXELS_PER_UNIT, win[WIN_PAINT].zoom_mag,
  97.         SCROLLBAR_OBJECT_LENGTH, win[WIN_PAINT].img_r,
  98.         SCROLLBAR_PAGE_LENGTH, MAX_PCANV_HEIGHT,
  99.         SCROLLBAR_VIEW_LENGTH, MAX_PCANV_HEIGHT,
  100.         NULL);
  101.  
  102.     paint_w = MAX((win[WIN_PAINT].canv_x + win[WIN_PAINT].canv_w + 40),
  103.         (xv_get(Paint_win_paint->but_apply_log, XV_X, NULL) +
  104.         xv_get(Paint_win_paint->but_apply_log, XV_WIDTH, NULL) +
  105.         10));
  106.  
  107.     xv_set(Paint_win_paint->win_paint,
  108.         XV_WIDTH, paint_w,
  109.         XV_HEIGHT, win[WIN_PAINT].canv_y + win[WIN_PAINT].canv_h + 30,
  110.         NULL);
  111. }
  112.  
  113. /*********************************************/
  114. int
  115. max_frames(aspect)
  116. int aspect;
  117. {
  118.     switch(aspect) {
  119.     case ASPECT_X :
  120.         return(segal.c - 1);
  121.         break;
  122.     case ASPECT_Y :
  123.         return(segal.r - 1);
  124.         break;
  125.     case ASPECT_Z :
  126.         return(segal.f - 1);
  127.         break;
  128.     }
  129. }
  130.  
  131. /*********************************************/
  132. void
  133. redisplay_paint()
  134. {
  135.     void map_buffers();
  136.  
  137.     win[WIN_PAINT].repaint = TRUE;
  138.     map_buffers();
  139. }
  140.  
  141. /*********************************************/
  142. void
  143. paint_event(event)
  144. Event *event;
  145. {
  146.     void get_stats();
  147.     void draw_location();
  148.     int gradient();
  149.     void erase_thresh_bounds();
  150.     void draw_thresh_bounds();
  151.     void free_2d_byte_array();
  152.     byte **alloc_2d_byte_array();
  153.     void save_image_frame();
  154.     void save_mask_frame();
  155.     void get_3d_coords();
  156.     void save_mask_undo_2d();
  157.     void save_image_undo();
  158.     void paint();
  159.     u_long standout();
  160.     void paint_cell();
  161.  
  162.     int x, y, x1, y1, f1;
  163.  
  164. /*
  165. mouse events:
  166.         any button: paint
  167.         shift, any button  : show gray value
  168.         ctrl, middle button: sets gradient according to highest gradient
  169.          between any adjacent pixels encountered (from push to release).
  170.         ctrl, left button  : sets the growth lower threshold slider bar.
  171.         ctrl, right button : sets the growth upper threshold slider bar.
  172.     ctrl+shift, left   : begin a new point list.
  173.     ctrl+shift, left   : add to existing point list.
  174.         meta, any button   : show object statistics
  175. */
  176.  
  177.     /* meta events */
  178.     if(event_meta_is_down(event)) {
  179.         if(event_is_down(event)) switch(event_id(event)) {
  180.         case MS_RIGHT:
  181.         case MS_LEFT:
  182.         case MS_MIDDLE:
  183.             x = event_x(event) / win[WIN_PAINT].zoom_mag;
  184.             y = event_y(event) / win[WIN_PAINT].zoom_mag;
  185.             RANGE(x, 0, win[WIN_PAINT].img_c - 1)
  186.             RANGE(y, 0, win[WIN_PAINT].img_r - 1)
  187.             /*
  188.             get_stats(x, y);
  189.             */
  190.             break;
  191.         }
  192.     return;
  193.     }
  194.  
  195.     /* shift events */
  196.     if(event_shift_is_down(event)
  197.     && !event_ctrl_is_down(event)) {
  198.         switch (event_id(event)) {
  199.         case MS_RIGHT:
  200.         case MS_LEFT:
  201.         case MS_MIDDLE:
  202.         case LOC_DRAG:
  203.             x = event_x(event) / win[WIN_PAINT].zoom_mag;
  204.             y = event_y(event) / win[WIN_PAINT].zoom_mag;
  205.             RANGE(x, 0, win[WIN_PAINT].img_c - 1)
  206.             RANGE(y, 0, win[WIN_PAINT].img_r - 1)
  207.             /*
  208.             if (event_is_down(event)) draw_location(x, y, TRUE);
  209.             else draw_location(x, y, FALSE);
  210.             */
  211.             break;
  212.         }
  213.     return;
  214.     }
  215.  
  216.  
  217.     /* ctrl events */
  218.     if(!event_shift_is_down(event)
  219.     && event_ctrl_is_down(event)) {
  220.         int value, g;
  221.  
  222.         x = event_x(event) / win[WIN_PAINT].zoom_mag;
  223.         y = event_y(event) / win[WIN_PAINT].zoom_mag;
  224.         RANGE(x, 0, win[WIN_PAINT].img_c - 1)
  225.         RANGE(y, 0, win[WIN_PAINT].img_r - 1)
  226.         if(segal.color)
  227.             value = MONO(win[WIN_PAINT].i_data[RP][y][x],
  228.                 win[WIN_PAINT].i_data[GP][y][x],
  229.                 win[WIN_PAINT].i_data[BP][y][x]);
  230.         else value = win[WIN_PAINT].i_data[GRAY][y][x];
  231.  
  232.         switch (event_id(event)) {
  233.         static int which_button;
  234.  
  235.         case MS_LEFT:
  236.             which_button = MS_LEFT;
  237.             if(event_is_down(event)) {
  238.                 /* mask grow */
  239.                 xv_set(Mask_grow_pop_mask_grow->set_threshold_min,
  240.                     PANEL_VALUE, value,
  241.                     NULL);
  242.                 grow.threshold_min = value;
  243.  
  244.                 /* threshold */
  245.                 erase_thresh_bounds();
  246.                 threshold.min = value;
  247.                 if(value > threshold.max) threshold.max = value;
  248.                 draw_thresh_bounds();
  249.             }
  250.             break;
  251.  
  252.         case MS_MIDDLE:
  253.             which_button = MS_MIDDLE;
  254.             if(event_is_down(event)) {
  255.                 g = gradient(x, y, win[WIN_PAINT].f);
  256.                 grow.gradient_min = grow.gradient_max = g;
  257.                 xv_set(Mask_grow_pop_mask_grow->set_gradient_max,
  258.                     PANEL_VALUE, grow.gradient_max,
  259.                     NULL);
  260.                 xv_set(Mask_grow_pop_mask_grow->set_gradient_min,
  261.                     PANEL_VALUE, grow.gradient_min,
  262.                     NULL);
  263.             }
  264.             break;
  265.  
  266.         case MS_RIGHT:
  267.             which_button = MS_RIGHT;
  268.             if(event_is_down(event)) {
  269.                 /* mask grow */
  270.                 xv_set(Mask_grow_pop_mask_grow->set_threshold_max,
  271.                     PANEL_VALUE, value,
  272.                     NULL);
  273.                 grow.threshold_max = value;
  274.  
  275.                 /* threshold */
  276.                 erase_thresh_bounds();
  277.                 threshold.max = value;
  278.                 if(value < threshold.min) threshold.min = value;
  279.                 draw_thresh_bounds();
  280.             }
  281.             break;
  282.  
  283.         case LOC_DRAG:
  284.             x = event_x(event) / win[WIN_PAINT].zoom_mag;
  285.             y = event_y(event) / win[WIN_PAINT].zoom_mag;
  286.             RANGE(x, 0, win[WIN_PAINT].img_c - 1)
  287.             RANGE(y, 0, win[WIN_PAINT].img_r - 1)
  288.             if (event_is_down(event)) switch(which_button) {
  289.             case MS_LEFT:
  290.                 if(value < grow.threshold_min) {
  291.                     grow.threshold_min = value;
  292.                     xv_set(Mask_grow_pop_mask_grow->set_threshold_min,
  293.                         PANEL_VALUE, grow.threshold_min,
  294.                         NULL);
  295.                 }
  296.  
  297.                 /* threshold */
  298.                 erase_thresh_bounds();
  299.                 threshold.min = value;
  300.                 if(value > threshold.max) threshold.max = value;
  301.                 draw_thresh_bounds();
  302.  
  303.                 break;
  304.             case MS_MIDDLE:
  305.                 g = gradient(x, y, win[WIN_PAINT].f);
  306.                 if(g > grow.gradient_max) {
  307.                     grow.gradient_max = g;
  308.                     xv_set(Mask_grow_pop_mask_grow->set_gradient_max,
  309.                         PANEL_VALUE, g,
  310.                         NULL);
  311.                 }
  312.                 if(g < grow.gradient_min) {
  313.                     grow.gradient_min = g;
  314.                     xv_set(Mask_grow_pop_mask_grow->set_gradient_min,
  315.                         PANEL_VALUE, g,
  316.                         NULL);
  317.                 }
  318.                 break;
  319.             case MS_RIGHT:
  320.                 if(value > grow.threshold_max) {
  321.                     grow.threshold_max = value;
  322.                     xv_set(Mask_grow_pop_mask_grow->set_threshold_max,
  323.                         PANEL_VALUE, grow.threshold_max,
  324.                         NULL);
  325.                 }
  326.  
  327.                 /* threshold */
  328.                 erase_thresh_bounds();
  329.                 threshold.max = value;
  330.                 if(value < threshold.min) threshold.min = value;
  331.                 draw_thresh_bounds();
  332.  
  333.                 break;
  334.             }
  335.             break;
  336.         }
  337.     return;
  338.     }
  339.  
  340.     /* ctrl + shift events */
  341.     if(event_shift_is_down(event)
  342.     && event_ctrl_is_down(event)) {
  343.         x = event_x(event) / win[WIN_PAINT].zoom_mag;
  344.         y = event_y(event) / win[WIN_PAINT].zoom_mag;
  345.         RANGE(x, 0, win[WIN_PAINT].img_c - 1)
  346.         RANGE(y, 0, win[WIN_PAINT].img_r - 1)
  347.  
  348.         get_3d_coords(win[WIN_PAINT].aspect, ASPECT_Z,
  349.             x, y, win[WIN_PAINT].f, &x1, &y1, &f1);
  350.  
  351.         switch (event_id(event)) {
  352.         case MS_LEFT :
  353.         case MS_MIDDLE :
  354.         case MS_RIGHT :
  355.         case LOC_DRAG:
  356.         default :
  357.             break;
  358.         }
  359.         return;
  360.     }
  361.  
  362.     /* other events */
  363.     switch (event_id(event)) {
  364.     case LOC_WINENTER:
  365.         break;
  366.     case LOC_WINEXIT:
  367.         break;
  368.     case MS_RIGHT:
  369.     case MS_LEFT:
  370.     case MS_MIDDLE:
  371.         if(event_is_down(event)) {
  372.             switch(brush.mode) {
  373.             case BRUSH_IMAGE :
  374.                 save_image_undo(WIN_PAINT);
  375.                 break;
  376.             case BRUSH_MASK : 
  377.             case BRUSH_PTS : 
  378.                 save_mask_undo_2d(WIN_PAINT);
  379.                 break;
  380.             default :
  381.                 break;
  382.             }
  383.  
  384.             x = event_x(event) / win[WIN_PAINT].zoom_mag;
  385.             y = event_y(event) / win[WIN_PAINT].zoom_mag;
  386.             paint(x, y);
  387.         }
  388.         if(event_is_up(event)) {
  389.             switch(brush.mode) {
  390.             case BRUSH_IMAGE :
  391.                 save_image_frame(WIN_PAINT);
  392.                 break;
  393.             case BRUSH_MASK : 
  394.             case BRUSH_PTS : 
  395.                 save_mask_frame(WIN_PAINT);
  396.                 break;
  397.             default :
  398.                 break;
  399.             }
  400.         }
  401.         break;
  402.     case LOC_DRAG:
  403.         if (event_is_down(event)) {
  404.             x = event_x(event) / win[WIN_PAINT].zoom_mag;
  405.             y = event_y(event) / win[WIN_PAINT].zoom_mag;
  406.             paint(x, y);
  407.         }
  408.         break;
  409.     default:
  410.         break;
  411.     }
  412. }
  413.  
  414. /******************************************************/
  415. void
  416. paint(x, y)
  417. int x, y;
  418. {
  419.     void paint_mask();
  420.     void paint_image();
  421.     void paint_pt();
  422.  
  423.     RANGE(x, 0, win[WIN_PAINT].img_c - 1)
  424.     RANGE(y, 0, win[WIN_PAINT].img_r - 1)
  425.  
  426.     switch(brush.mode) {
  427.     case BRUSH_IMAGE :
  428.         img.changed_frame = TRUE;
  429.         paint_image(x, y);
  430.         break;
  431.     case BRUSH_MASK : 
  432.         m[segal.e_m].changed_frame = TRUE;
  433.         paint_mask(x, y);
  434.         break;
  435.     case BRUSH_PTS :
  436.         m[segal.e_m].changed_frame = TRUE;
  437.         paint_pt(x, y);
  438.         break;
  439.     default :
  440.         break;
  441.     }
  442. }
  443.  
  444. /******************************************************/
  445. void
  446. paint_mask(x, y)
  447. int x, y;
  448. {
  449.     void erase_mask_pixel();
  450.     void paint_mask_pixel();
  451.  
  452.     int i, j, bsize, max_i, max_j, cx, cy;
  453.  
  454.     bsize = brush.size + 1;
  455.     if(brush.size == 5) bsize = 10;
  456.     if(brush.size == 6) bsize = 20;
  457.  
  458.     max_i = MIN(x + bsize, win[WIN_PAINT].img_c - 1);
  459.     max_j = MIN(y + bsize, win[WIN_PAINT].img_r - 1);
  460.  
  461.     cx = cy = my_cursor[brush.size][0].corner;
  462.  
  463.     for(i = x; i < max_i; i++)
  464.     for(j = y; j < max_j; j++) {
  465.         if(brush.mask_affect == MASK_ERASE
  466.         && BIT_IS_ON(win[WIN_PAINT].m_data[j][i], m[segal.e_m].bit_key)) {
  467.             if(brush.shape == BRUSH_ROUND
  468.             && my_cursor[brush.size][0].paint_mask_matrix[j-y+cy][i-x+cx])
  469.                 erase_mask_pixel(i, j);
  470.             else if(brush.shape == BRUSH_SQUARE)
  471.                 erase_mask_pixel(i, j);
  472.         }
  473.         else if(brush.mask_affect == MASK_PAINT
  474.         && !BIT_IS_ON(win[WIN_PAINT].m_data[j][i], m[segal.e_m].bit_key)) {
  475.             if(brush.shape == BRUSH_ROUND
  476.             && my_cursor[brush.size][0].paint_mask_matrix[j-y+cy][i-x+cx])
  477.                 paint_mask_pixel(i, j);
  478.             else if(brush.shape == BRUSH_SQUARE)
  479.                 paint_mask_pixel(i, j);
  480.         }
  481.     }
  482. }
  483.  
  484. /******************************************************/
  485. double
  486. dist(x1, y1, x2, y2)
  487. double x1, y1, x2, y2;
  488. {
  489.     return(pow(((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)), .5));
  490.  
  491. /******************************************************/
  492. void
  493. erase_mask_pixel(x, y)
  494. int x, y;
  495. {
  496.     unsigned long standout();
  497.     byte map_rgb_to_xcolor();
  498.     LOGIC turn_bit_off_with_log();
  499.     void paint_view_cells();
  500.     void paint_cell();
  501.  
  502.     unsigned long pval;
  503.     int intensity;
  504.  
  505.     if(segal.color)
  506.         intensity = MONO(win[WIN_PAINT].i_data[RP][y][x],
  507.             win[WIN_PAINT].i_data[GP][y][x],
  508.             win[WIN_PAINT].i_data[BP][y][x]);
  509.     else intensity = win[WIN_PAINT].i_data[GRAY][y][x];
  510.  
  511.  
  512.     if(BIT_IS_ON(win[WIN_PAINT].m_data[y][x], m[BUF_PTS].bit_key)) {
  513.         if(segal.disp_image)
  514.             pval = colors[pt_lut[intensity]];
  515.         else pval = standout(ORANGE);
  516.     }    
  517.     else {
  518.         if(segal.disp_image) {
  519.         if(segal.color)
  520.             pval =  colors[map_rgb_to_xcolor(
  521.                 win[WIN_PAINT].i_data[RP][y][x],
  522.                 win[WIN_PAINT].i_data[GP][y][x],
  523.                 win[WIN_PAINT].i_data[BP][y][x])];
  524.             else pval = colors[gray_lut[intensity]];
  525.  
  526.         }
  527.         else pval = standout(CBLACK);
  528.     }
  529.  
  530.     win[WIN_PAINT].z_data[y][x] = (byte) pval;
  531.  
  532.     /* turn mask bit off */
  533.     if(turn_bit_off_with_log(&win[WIN_PAINT].m_data[y][x])) {
  534.         /* now paint the cell */
  535.         paint_view_cells(win[WIN_PAINT].aspect, x, y,
  536.             win[WIN_PAINT].f, pval);
  537.         paint_cell(WIN_PAINT, x, y, pval);
  538.     }
  539. }
  540.  
  541. /******************************************************/
  542. void
  543. paint_mask_pixel(x, y)
  544. int x, y;
  545. {
  546.     unsigned long standout();
  547.     LOGIC turn_bit_on_with_log();
  548.     void paint_view_cells();
  549.     void paint_cell();
  550.  
  551.     unsigned long pval;
  552.     int intensity;
  553.  
  554.     if(segal.color)
  555.         intensity = MONO(win[WIN_PAINT].i_data[RP][y][x],
  556.             win[WIN_PAINT].i_data[GP][y][x],
  557.             win[WIN_PAINT].i_data[BP][y][x]);
  558.     else intensity = win[WIN_PAINT].i_data[GRAY][y][x];
  559.  
  560.     if(BIT_IS_ON(win[WIN_PAINT].m_data[y][x], m[BUF_PTS].bit_key))
  561.         pval = standout(ORANGE);
  562.     else {
  563.         if(segal.disp_image)
  564.             pval = colors[blend_lut[intensity]];
  565.         else pval = standout(CWHITE);
  566.     }
  567.  
  568.     win[WIN_PAINT].z_data[y][x] = (byte) pval;
  569.  
  570.     /* turn mask bit on */
  571.     if(turn_bit_on_with_log(&win[WIN_PAINT].m_data[y][x])) {
  572.         /* now paint the cell */
  573.         paint_view_cells(win[WIN_PAINT].aspect, x, y,
  574.             win[WIN_PAINT].f, pval);
  575.         paint_cell(WIN_PAINT, x, y, pval);
  576.     }
  577. }
  578.  
  579. /******************************************************/
  580. void
  581. paint_image(x, y)
  582. int x, y;
  583. {
  584.     void paint_image_pixel();
  585.  
  586.     int i, j, bsize, max_i, max_j, cx, cy;
  587.  
  588.     bsize = brush.size + 1;
  589.     if(brush.size == 5) bsize = 10;
  590.     if(brush.size == 6) bsize = 20;
  591.  
  592.     max_i = MIN(x + bsize, win[WIN_PAINT].img_c - 1);
  593.     max_j = MIN(y + bsize, win[WIN_PAINT].img_r - 1);
  594.  
  595.     cx = cy = my_cursor[brush.size][0].corner;
  596.     for(i = x; i < max_i; i++)
  597.     for(j = y; j < max_j; j++) {
  598.         if(brush.shape == BRUSH_ROUND
  599.         && my_cursor[brush.size][0].paint_mask_matrix[j-y+cy][i-x+cx])
  600.             paint_image_pixel(i, j);
  601.         else if(brush.shape == BRUSH_SQUARE)
  602.             paint_image_pixel(i, j);
  603.     }
  604. }
  605.  
  606. /******************************************************/
  607. void
  608. paint_image_pixel(x, y)
  609. int x, y;
  610. {
  611. /* BIND_PVAL sets i_pval to UNDEFINED if nothing changed */
  612. #define BIND_PVAL(p,d) {i_pval=p+d; RANGE(i_pval,0,255) if(p==i_pval) i_pval = UNDEFINED; else p=i_pval;}
  613.  
  614.     byte map_rgb_to_xcolor();
  615.     void paint_view_cells();
  616.     void paint_cell();
  617.  
  618.     int i, i_pval, intensity;
  619.     unsigned long pval;
  620.     LOGIC changed;
  621.  
  622.     /* add delta to image pixel value */
  623.     changed = FALSE;
  624.     if(segal.color) For_rgb {
  625.         BIND_PVAL(win[WIN_PAINT].i_data[i][y][x], brush.image_affect)
  626.         if(i_pval != UNDEFINED) changed = TRUE;
  627.     }
  628.     else {
  629.         BIND_PVAL(win[WIN_PAINT].i_data[GRAY][y][x], brush.image_affect)
  630.         if(i_pval != UNDEFINED) changed = TRUE;
  631.     }
  632.  
  633.     /* nothing changed or both mask and points are painted here */
  634.     if(!changed
  635.     || (BIT_IS_ON(win[WIN_PAINT].m_data[y][x], m[segal.e_m].bit_key)
  636.     && BIT_IS_ON(win[WIN_PAINT].m_data[y][x], m[BUF_PTS].bit_key)))
  637.         return;
  638.  
  639.     /* get appropriate pixel value for the gc */
  640.     if(BIT_IS_ON(win[WIN_PAINT].m_data[y][x], m[segal.e_m].bit_key)
  641.     && segal.disp_mask) {
  642.         if(segal.color)
  643.             intensity = MONO(win[WIN_PAINT].i_data[RP][y][x],
  644.                 win[WIN_PAINT].i_data[GP][y][x],
  645.                 win[WIN_PAINT].i_data[BP][y][x]);
  646.         else intensity = win[WIN_PAINT].i_data[GRAY][y][x];
  647.         pval = colors[blend_lut[intensity]];
  648.     }
  649.     else if(segal.disp_image) {
  650.         if(segal.color)
  651.             pval =  colors[map_rgb_to_xcolor(
  652.                 win[WIN_PAINT].i_data[RP][y][x],
  653.                 win[WIN_PAINT].i_data[GP][y][x],
  654.                 win[WIN_PAINT].i_data[BP][y][x])];
  655.         else pval = colors[gray_lut[win[WIN_PAINT].i_data[GRAY][y][x]]];
  656.     }
  657.     win[WIN_PAINT].z_data[y][x] = (byte) pval;
  658.  
  659.     /* now paint the cell */
  660.     paint_view_cells(win[WIN_PAINT].aspect, x, y, win[WIN_PAINT].f, pval);
  661.     paint_cell(WIN_PAINT, x, y, pval);
  662. }
  663.  
  664. /******************************************************/
  665. void
  666. paint_pt(x, y)
  667. int x, y;
  668. {
  669. /* point list paintbrush */
  670.     void erase_pt_pixel();
  671.     void paint_pt_pixel();
  672.  
  673.     int i, j, bsize, max_i, max_j, cx, cy;
  674.  
  675.     bsize = brush.size + 1;
  676.     if(brush.size == 5) bsize = 10;
  677.     if(brush.size == 6) bsize = 20;
  678.  
  679.     max_i = MIN(x + bsize, win[WIN_PAINT].img_c - 1);
  680.     max_j = MIN(y + bsize, win[WIN_PAINT].img_r - 1);
  681.  
  682.     cx = cy = my_cursor[brush.size][0].corner;
  683.  
  684.     for(i = x; i < max_i; i++)
  685.     for(j = y; j < max_j; j++) {
  686.         if(brush.mask_affect == MASK_ERASE
  687.         && BIT_IS_ON(win[WIN_PAINT].m_data[j][i], m[BUF_PTS].bit_key)) {
  688.             if(brush.shape == BRUSH_ROUND
  689.             && my_cursor[brush.size][0].paint_mask_matrix[j-y+cy][i-x+cx])
  690.                 erase_pt_pixel(i, j);
  691.             else if(brush.shape == BRUSH_SQUARE)
  692.                 erase_pt_pixel(i, j);
  693.         }
  694.         else if(brush.mask_affect == MASK_PAINT
  695.         && !BIT_IS_ON(win[WIN_PAINT].m_data[j][i], m[BUF_PTS].bit_key)) {
  696.             if(brush.shape == BRUSH_ROUND
  697.             && my_cursor[brush.size][0].paint_mask_matrix[j-y+cy][i-x+cx])
  698.                 paint_pt_pixel(i, j);
  699.             else if(brush.shape == BRUSH_SQUARE)
  700.                 paint_pt_pixel(i, j);
  701.         }
  702.     }
  703. }
  704.  
  705. /******************************************************/
  706. void
  707. erase_pt_pixel(x, y)
  708. int x, y;
  709. {
  710.     byte map_rgb_to_xcolor();
  711.     unsigned long standout();
  712.     void paint_view_cells();
  713.     void paint_cell();
  714.  
  715.     unsigned long pval;
  716.     int intensity;
  717.  
  718.     if(segal.color)
  719.         intensity = MONO(win[WIN_PAINT].i_data[RP][y][x],
  720.             win[WIN_PAINT].i_data[GP][y][x],
  721.             win[WIN_PAINT].i_data[BP][y][x]);
  722.     else intensity = win[WIN_PAINT].i_data[GRAY][y][x];
  723.  
  724.     if(BIT_IS_ON(win[WIN_PAINT].m_data[y][x], m[segal.e_m].bit_key)) {
  725.         if(segal.disp_image)
  726.             pval = colors[blend_lut[intensity]];
  727.         else pval = standout(CWHITE);
  728.     }
  729.     else {
  730.         if(segal.disp_image) {
  731.             if(segal.color)
  732.                 pval =  colors[map_rgb_to_xcolor(
  733.                     win[WIN_PAINT].i_data[RP][y][x],
  734.                     win[WIN_PAINT].i_data[GP][y][x],
  735.                     win[WIN_PAINT].i_data[BP][y][x])];
  736.             else pval = colors[gray_lut[intensity]];
  737.  
  738.         }
  739.         else pval = standout(CBLACK);
  740.     }
  741.  
  742.     win[WIN_PAINT].z_data[y][x] = (byte) pval;
  743.  
  744.     /* turn mask bit off */
  745.     TURN_BIT_OFF(win[WIN_PAINT].m_data[y][x], m[BUF_PTS].bit_key)
  746.  
  747.     /* now paint the cell */
  748.     paint_view_cells(win[WIN_PAINT].aspect, x, y,
  749.         win[WIN_PAINT].f, pval);
  750.     paint_cell(WIN_PAINT, x, y, pval);
  751. }
  752.  
  753. /******************************************************/
  754. void
  755. paint_pt_pixel(x, y)
  756. int x, y;
  757. {
  758.     unsigned long standout();
  759.     void paint_view_cells();
  760.     void paint_cell();
  761.  
  762.     unsigned long pval;
  763.     int intensity;
  764.  
  765.     if(segal.color)
  766.         intensity = MONO(win[WIN_PAINT].i_data[RP][y][x],
  767.             win[WIN_PAINT].i_data[GP][y][x],
  768.             win[WIN_PAINT].i_data[BP][y][x]);
  769.     else intensity = win[WIN_PAINT].i_data[GRAY][y][x];
  770.  
  771.     if(BIT_IS_ON(win[WIN_PAINT].m_data[y][x], m[segal.e_m].bit_key))
  772.         pval = standout(ORANGE);
  773.     else {
  774.         if(segal.disp_image)
  775.             pval = colors[pt_lut[intensity]];
  776.         else pval = standout(RED);
  777.     }
  778.  
  779.     win[WIN_PAINT].z_data[y][x] = (byte) pval;
  780.  
  781.     /* turn mask bit on */
  782.     TURN_BIT_ON(win[WIN_PAINT].m_data[y][x], m[BUF_PTS].bit_key)
  783.  
  784.     /* now paint the cell */
  785.     paint_view_cells(win[WIN_PAINT].aspect, x, y,
  786.         win[WIN_PAINT].f, pval);
  787.     paint_cell(WIN_PAINT, x, y, pval);
  788. }
  789.  
  790. /******************************************************/
  791. void
  792. paint_view_cells(asp_in, x, y, f, pval)
  793. int asp_in;
  794. int x, y, f;
  795. unsigned long pval;
  796. {
  797.     void get_3d_coords();
  798.     void paint_cell();
  799.  
  800.     int i, x1, y1, f1;
  801.  
  802.     For_all_view {
  803.         get_3d_coords(asp_in, i, x, y, f,
  804.             &x1, &y1, &f1);
  805.         if(f1 == win[i].f) paint_cell(i, x1, y1, pval);
  806.     }
  807. }
  808.  
  809. /******************************************************/
  810. void
  811. paint_cell(win_id, x, y, pval)
  812. int win_id;
  813. int x, y;
  814. unsigned long pval;
  815. {
  816.     register int x0, y0;
  817.     int x1, x2, y1, y2, npoints;
  818.     XPoint points[MAX_BRUSH_SIZE * MAX_BRUSH_SIZE * MAX_ZOOM_MAG];
  819.  
  820.     npoints = 0;
  821.  
  822.     x1 = x * win[win_id].zoom_mag;
  823.     x2 = x1 + win[win_id].zoom_mag;
  824.     y1 = y * win[win_id].zoom_mag;
  825.     y2 = y1 + win[win_id].zoom_mag;
  826.  
  827.     for(x0 = x1; x0 < x2; x0++)
  828.     for(y0 = y1; y0 < y2; y0++) {
  829.         XPutPixel(win[win_id].ximg, x0, y0, pval);
  830.         points[npoints].x = x0;
  831.         points[npoints++].y = y0;
  832.     }
  833.     XSetForeground(display, gc, pval);
  834.     XDrawPoints(display, win[win_id].xid, gc, points, npoints, CoordModeOrigin);
  835. }
  836.  
  837. /******************************************************/
  838. void
  839. apply_log(roi)
  840. int roi;
  841. {
  842.     LOGIC bit_is_excluded();
  843.     LOGIC bit_is_included();
  844.     void save_mask_frame();
  845.     void redisplay_paint();
  846.     void redisplay_all();
  847.  
  848.     byte *mdata;
  849.     int i, size;
  850.  
  851.     switch(roi) {
  852.     case R2d_WHOLE :
  853.         mdata = win[WIN_PAINT].m_data[0];
  854.         size = win[WIN_PAINT].img_size;
  855.         break;
  856.     case R3d_WHOLE :
  857.         mdata = mbuf[0][0];
  858.         size = segal.r * segal.c * segal.f;
  859.         break;
  860.     default :
  861.         break;
  862.     }
  863.  
  864.     switch(mlog.apply_order) {
  865.     case ORDER_EI :
  866.         for(i = 0; i < size; i++) {
  867.             if(bit_is_excluded(mdata[i]))
  868.                 TURN_BIT_OFF(mdata[i], m[segal.e_m].bit_key)
  869.             if(bit_is_included(mdata[i]))
  870.                 TURN_BIT_ON(mdata[i], m[segal.e_m].bit_key)
  871.         }
  872.         break;
  873.     case ORDER_IE :
  874.         for(i = 0; i < size; i++) {
  875.             if(bit_is_included(mdata[i]))
  876.                 TURN_BIT_ON(mdata[i], m[segal.e_m].bit_key)
  877.             if(bit_is_excluded(mdata[i]))
  878.                 TURN_BIT_OFF(mdata[i], m[segal.e_m].bit_key)
  879.         }
  880.         break;
  881.     default :
  882.         break;
  883.     }
  884.  
  885.     if(roi == R2d_WHOLE) {
  886.         m[segal.e_m].changed_frame = TRUE;
  887.         save_mask_frame(WIN_PAINT);
  888.     }
  889.  
  890.     redisplay_all();
  891. }
  892.