Subversion Repositories wimsdev

Rev

Rev 9907 | Rev 10972 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. #include "canvasdraw.h"
  2.  
  3. /* not used ?? */
  4. /*
  5. char *data2js_array(int data[],int len);
  6. char *xy2js_array(int xy[],int len);
  7. */
  8. void add_js_multidraw(FILE *js_include_file,int canvas_root_id,char *draw_types,char *button_style){
  9. /*
  10.  
  11. just for the javascript switches():
  12. point = 0       points =1
  13. circle = 2      circles = 3
  14. line =4         lines = 5
  15. segment = 6     segments = 7
  16. arrow = 8       arrows = 9
  17. triangle = 10   triangles = 11
  18. polygon = 12
  19. text = 13
  20. rect = 14
  21. rects =15
  22. 28/6/2015:
  23. the next js-code block (parsing/scanning the multidraw objects array) is -for now- generic,
  24. e.g. not responsive to the actual draw_types used.
  25.  
  26. TODO: examine/parse the *draw_Types and make the js-code accordingly (e.g. specific and not generic)
  27. */
  28.  
  29. fprintf(js_include_file,"\n<!-- begin multidraw  -->\n\
  30. var canvas_userdraw = create_canvas%d(999,xsize,ysize);\
  31. var context_userdraw = canvas_userdraw.getContext(\"2d\");\
  32. var click_cnt = 0;\
  33. if(wims_status != \"done\"){\
  34. canvas_div.addEventListener(\"mousedown\",user_draw,false);\
  35. canvas_div.addEventListener(\"mousemove\",user_drag,false);\
  36. canvas_div.addEventListener(\"touchstart\",user_draw,false);\
  37. canvas_div.addEventListener(\"touchmove\",user_drag,false);\
  38. };\
  39. clear_draw_area%d = function(type,name){\
  40. if(confirm(\"delete \"+multilabel[name]+\" ?\")){\
  41.  switch(type){\
  42.   case 0: context_points.clearRect(0,0,xsize,ysize);points_x = [];points_y = [];break;\
  43.   case 1: points_x.pop();points_y.pop();draw_points();break;\
  44.   case 2: context_circles.clearRect(0,0,xsize,ysize);circles_x = [];circles_y = []; multi_radius = [];break;\
  45.   case 3: circles_x.pop();circles_y.pop(); multi_radius.pop();draw_circles();break;\
  46.   case 4: context_lines.clearRect(0,0,xsize,ysize);lines_x = [];lines_y = [];break;\
  47.   case 5: lines_x.pop();lines_y.pop();lines_x.pop();lines_y.pop();draw_lines();break;\
  48.   case 6: context_segments.clearRect(0,0,xsize,ysize);segments_x = [];segments_y = [];break;\
  49.   case 7: segments_x.pop();segments_y.pop();segments_x.pop();segments_y.pop();draw_segments();break;\
  50.   case 8: context_arrows.clearRect(0,0,xsize,ysize);arrows_x = [];arrows_y = [];break;\
  51.   case 9: arrows_x.pop();arrows_y.pop();arrows_x.pop();arrows_y.pop();draw_arrows();break;\
  52.   case 10:context_triangles.clearRect(0,0,xsize,ysize); triangles_x = [];triangles_y = [];break;\
  53.   case 11:for(var p=0;p<poly_num;p++){triangles_x.pop();triangles_y.pop();};draw_triangles();break;\
  54.   case 12:context_closedpoly.clearRect(0,0,xsize,ysize);closedpoly_x = [];closedpoly_y = [];break;\
  55.   case 13:context_text.clearRect(0,0,xsize,ysize);text_x.pop();text_y.pop();text_abc.pop();draw_text();break;\
  56.   case 14:context_rects.clearRect(0,0,xsize,ysize);rects_x = [];rects_y = [];break;\
  57.   case 15: rects_x.pop();rects_y.pop();rects_x.pop();rects_y.pop();draw_rects();break;\
  58.   default:break;\
  59.  };\
  60. };\
  61. };\
  62. function user_draw(evt){\
  63. var canvas_rect = canvas_userdraw.getBoundingClientRect();\
  64. var y = evt.clientY - canvas_rect.top;\
  65. var x = evt.clientX - canvas_rect.left;\
  66. switch(userdraw_primitive){\
  67.  case 0: points(x,y,0,0);break;\
  68.  case 1: points(x,y,0,1);break;\
  69.  case 2: circles(x,y,0,0);break;\
  70.  case 3: circles(x,y,0,1);break;\
  71.  case 4: lines(x,y,0,0);break;\
  72.  case 5: lines(x,y,0,1);break;\
  73.  case 6: segments(x,y,0,0);break;\
  74.  case 7: segments(x,y,0,1);break;\
  75.  case 8: arrows(x,y,0,0);break;\
  76.  case 9: arrows(x,y,0,1);break;\
  77.  case 10: triangles(x,y,0,0);break;\
  78.  case 11: triangles(x,y,0,1);break;\
  79.  case 12: closedpoly(x,y,0,0);break;\
  80.  case 13: text(x,y,0,1);break;\
  81.  case 14: rects(x,y,0,0);break;\
  82.  case 15: rects(x,y,0,1);break;\
  83.  default:break;\
  84. };\
  85. };\
  86. function user_drag(evt){\
  87. var canvas_rect = canvas_userdraw.getBoundingClientRect();\
  88. var y = evt.clientY - canvas_rect.top;\
  89. var x = evt.clientX - canvas_rect.left;\
  90. switch(userdraw_primitive){\
  91.  case 0: break;\
  92.  case 1: break;\
  93.  case 2: circles(x,y,1,0);break;\
  94.  case 3: circles(x,y,1,1);break;\
  95.  case 4: lines(x,y,1,0);break;\
  96.  case 5: lines(x,y,1,1);break;\
  97.  case 6: segments(x,y,1,0);break;\
  98.  case 7: segments(x,y,1,1);break;\
  99.  case 8: arrows(x,y,1,0);break;\
  100.  case 9: arrows(x,y,1,1);break;\
  101.  case 10: triangles(x,y,1,0);break;\
  102.  case 11: triangles(x,y,1,1);break;\
  103.  case 12: closedpoly(x,y,1,0);break;\
  104.  case 13: break;\
  105.  case 14: rects(x,y,1,0);break;\
  106.  case 15: rects(x,y,1,1);break;\
  107.  default:break;\
  108. };\
  109. };\
  110. var draw_things = [\"%s\"];\
  111. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  112. var inner_html=\"\";\
  113. var button_style = \"%s\";\
  114. var id_x;\
  115. var id_y;\
  116. var id_r;\
  117. if( typeof multilabel[multilabel.length - 1 ] === 'undefined' ){multilabel[multilabel.length - 1] = 'stop drawing';};\
  118. for(var p = 0;p < draw_things.length;p++){\
  119. var desc;\
  120. id_r = 0;\
  121. if( multistrokeopacity[p] > 1 ){ multistrokeopacity[p] = (0.0039215*multistrokeopacity[p]).toFixed(2); };\
  122. if( multifillopacity[p] > 1 ){ multifillopacity[p] =  (0.0039215*multifillopacity[p]).toFixed(2); };\
  123. if( draw_things[p] == 'point' || draw_things[p] == 'points' ){\
  124.  var canvas_points = create_canvas%d(1000,xsize,ysize);\
  125.  var context_points = canvas_points.getContext(\"2d\");\
  126.  context_points.strokeStyle = \"rgba(\"+multistrokecolors[p]+\",\"+multistrokeopacity[p]+\")\";\
  127.  context_points.fillStyle = context_points.strokeStyle;\
  128.  context_points.lineWidth = multilinewidth[p];\
  129.  if(multilinewidth[p]%%2 == 1){ context_points.translate(0.5,0.5);};\
  130.  var points_x = new Array();var points_y = new Array();\
  131.  var points_snap = multisnaptogrid[p];\
  132.  if(draw_things[p] == 'point' ){desc = 0;}else{desc = 1;};\
  133.  id_x = 'input_points_x';id_y = 'input_points_y';\
  134. }\
  135. else\
  136. {\
  137.  if( draw_things[p] == 'circle' || draw_things[p] == 'circles' ){\
  138.   var canvas_circles = create_canvas%d(1001,xsize,ysize);\
  139.   var context_circles = canvas_circles.getContext(\"2d\");\
  140.   context_circles.lineWidth = multilinewidth[p];\
  141.   if(multilinewidth[p]%%2 == 1){ context_circles.translate(0.5,0.5);};\
  142.   context_circles.strokeStyle = \"rgba(\"+multistrokecolors[p]+\",\"+multistrokeopacity[p]+\")\";\
  143.   if(multifill[p] == '1' ){ context_circles.fillStyle = \"rgba(\"+multifillcolors[p]+\",\"+multifillopacity[p]+\")\";}else{context_circles.fillStyle = \"rgba( 255,255,255,0)\"; };\
  144.   if(multidash[p] == '1' ){ if( context_circles.setLineDash ){context_circles.setLineDash([2,4]);}else{if(context_circles.mozDash){context_circles.mozDash = [2,4]};};};\
  145.   var circles_x = new Array();var circles_y = new Array();var multi_radius = new Array();\
  146.   var circles_snap = multisnaptogrid[p];\
  147.   if( draw_things[p] == 'circle' ){desc = 2;}else{desc = 3;};\
  148.   id_x = 'input_circles_x';id_y = 'input_circles_y';id_r = 'input_circles_r';\
  149.  }\
  150.  else\
  151.  {\
  152.   if( draw_things[p] == 'line' || draw_things[p] == 'lines' ){\
  153.    var canvas_lines = create_canvas%d(1002,xsize,ysize);\
  154.    var context_lines = canvas_lines.getContext(\"2d\");\
  155.    context_lines.lineWidth = multilinewidth[p];\
  156.    if(multilinewidth[p]%%2 == 1){ context_lines.translate(0.5,0.5);};\
  157.    context_lines.strokeStyle = \"rgba(\"+multistrokecolors[p]+\",\"+multistrokeopacity[p]+\")\";\
  158.    if(multidash[p] == '1' ){ if( context_lines.setLineDash ){context_lines.setLineDash([2,4]);}else{if(context_lines.mozDash){context_lines.mozDash = [2,4]};};};\
  159.    var lines_x = new Array();var lines_y = new Array();\
  160.    var lines_snap = multisnaptogrid[p];\
  161.    if(draw_things[p] == 'line' ){desc = 4;}else{desc = 5;};\
  162.    id_x = 'input_lines_x';id_y = 'input_lines_y';\
  163.   }\
  164.   else\
  165.   {\
  166.    if( draw_things[p] == 'segment' || draw_things[p] == 'segments' ){\
  167.     var canvas_segments = create_canvas%d(1003,xsize,ysize);\
  168.     var context_segments = canvas_segments.getContext(\"2d\");\
  169.     context_segments.lineWidth = multilinewidth[p];\
  170.     if(multilinewidth[p]%%2 == 1){ context_segments.translate(0.5,0.5);};\
  171.     context_segments.strokeStyle = \"rgba(\"+multistrokecolors[p]+\",\"+multistrokeopacity[p]+\")\";\
  172.     if(multidash[p] == '1' ){ if( context_segments.setLineDash ){context_segments.setLineDash([2,4]);}else{if(context_segments.mozDash){context_segments.mozDash = [2,4]};};};\
  173.     var segments_x = new Array();var segments_y = new Array();\
  174.     var segments_snap = multisnaptogrid[p];\
  175.     if( draw_things[p] == 'segment' ){desc = 6;}else{ desc = 7;};\
  176.     id_x = 'input_segments_x';id_y = 'input_segments_y';\
  177.    }\
  178.    else\
  179.    {\
  180.     if( draw_things[p] == 'arrow' || draw_things[p] == 'arrows' ){\
  181.      var canvas_arrows = create_canvas%d(1004,xsize,ysize);\
  182.      var context_arrows =  canvas_arrows.getContext(\"2d\");\
  183.      context_arrows.lineWidth = multilinewidth[p];\
  184.      if(multilinewidth[p]%%2 == 1){ context_arrows.translate(0.5,0.5);};\
  185.      context_arrows.lineCap = \"round\";\
  186.      context_arrows.strokeStyle = \"rgba(\"+multistrokecolors[p]+\",\"+multistrokeopacity[p]+\")\";\
  187.      context_arrows.fillStyle = context_arrows.strokeStyle;\
  188.      if(multidash[p] == '1' ){ if( context_arrows.setLineDash ){context_arrows.setLineDash([2,4]);}else{if(context_arrows.mozDash){context_arrows.mozDash = [2,4]};};};\
  189.      var arrows_x = new Array();var arrows_y = new Array();\
  190.      var arrows_snap = multisnaptogrid[p];\
  191.      if( draw_things[p] == 'arrow' ){desc = 8;}else{desc = 9;};\
  192.      id_x = 'input_arrows_x';id_y = 'input_arrows_y';\
  193.     }\
  194.     else\
  195.     {\
  196.      if( draw_things[p] == 'rect' || draw_things[p] == 'rects' ){\
  197.       var canvas_rects = create_canvas%d(1008,xsize,ysize);\
  198.       var context_rects = canvas_rects.getContext(\"2d\");\
  199.       context_rects.lineWidth = multilinewidth[p];\
  200.       if(multilinewidth[p]%%2 == 1){ context_rects.translate(0.5,0.5);};\
  201.       context_rects.strokeStyle = \"rgba(\"+multistrokecolors[p]+\",\"+multistrokeopacity[p]+\")\";\
  202.       if(multidash[p] == '1' ){ if( context_rects.setlineDash ){context_rects.setlineDash([2,4]);}else{if(context_rects.mozDash){context_rects.mozDash = [2,4]};};};\
  203.       if(multifill[p] == '1' ){ context_rects.fillStyle = \"rgba(\"+multifillcolors[p]+\",\"+multifillopacity[p]+\")\";}else{context_rects.fillStyle = \"rgba( 255,255,255,0)\"; };\
  204.       var rects_x = new Array();var rects_y = new Array();\
  205.       var rects_snap = multisnaptogrid[p];\
  206.       if(draw_things[p] == 'rect' ){desc = 14;}else{desc = 15;};\
  207.       id_x = 'input_rects_x';id_y = 'input_rects_y';\
  208.      }\
  209.      else\
  210.      {\
  211.       if( draw_things[p] == 'closedpoly'){\
  212.        var canvas_closedpoly = create_canvas%d(1006,xsize,ysize);\
  213.        var context_closedpoly =  canvas_closedpoly.getContext(\"2d\");\
  214.        context_closedpoly.lineCap = \"round\";\
  215.        context_closedpoly.lineWidth = multilinewidth[p];\
  216.        if(multilinewidth[p]%%2 == 1){ context_closedpoly.translate(0.5,0.5);};\
  217.        context_closedpoly.lineCap = \"round\";\
  218.        context_closedpoly.strokeStyle = \"rgba(\"+multistrokecolors[p]+\",\"+multistrokeopacity[p]+\")\";\
  219.        if(multifill[p] == '1' ){ context_closedpoly.fillStyle = \"rgba(\"+multifillcolors[p]+\",\"+multifillopacity[p]+\")\";}else{context_closedpoly.fillStyle = \"rgba( 255,255,255,0)\"; };\
  220.        if(multidash[p] == '1' ){ if( context_closedpoly.setLineDash ){context_closedpoly.setLineDash([2,4]);}else{if(context_closedpoly.mozDash){context_closedpoly.mozDash = [2,4]};};};\
  221.        var closedpoly_x = new Array();var closedpoly_y = new Array();\
  222.        var closedpoly_snap = multisnaptogrid[p];\
  223.        desc = 12;\
  224.        id_x = 'input_closedpoly_x';id_y = 'input_closedpoly_y';\
  225.       }\
  226.       else\
  227.       {\
  228.        if( draw_things[p] == 'triangle' || draw_things[p] == 'triangles' || draw_things[p].indexOf('poly') != -1  || draw_things[p].indexOf('para') != -1 ){\
  229.         var canvas_triangles = create_canvas%d(1005,xsize,ysize);\
  230.         var context_triangles = canvas_triangles.getContext(\"2d\");\
  231.         context_triangles.lineCap = \"round\";\
  232.         context_triangles.lineWidth = multilinewidth[p];\
  233.         if(multilinewidth[p]%%2 == 1){ context_triangles.translate(0.5,0.5);};\
  234.         context_triangles.strokeStyle = \"rgba(\"+multistrokecolors[p]+\",\"+multistrokeopacity[p]+\")\";\
  235.         if(multifill[p] == '1' ){ context_triangles.fillStyle = \"rgba(\"+multifillcolors[p]+\",\"+multifillopacity[p]+\")\";}else{context_triangles.fillStyle = \"rgba( 255,255,255,0)\"; };\
  236.         if(multidash[p] == '1' ){ if( context_triangles.setLineDash ){context_triangles.setLineDash([2,4]);}else{if(context_triangles.mozDash){context_triangles.mozDash = [2,4]};};};\
  237.         var triangles_x = new Array();var triangles_y = new Array();\
  238.         var triangles_snap = multisnaptogrid[p];\
  239.         if( draw_things[p] == 'triangle'){desc = 10;}else{if( draw_things[p] == 'triangles'){desc = 11;}else{if( draw_things[p].indexOf('poly') != -1 ){ if( draw_things[p].indexOf('polys') != -1 ){ desc = 11;}else{desc = 10;};}else{if( draw_things[p] == 'parallelogram'){multiuserinput[p] = 0;desc = 10;}else{if( draw_things[p] == 'parallelograms'){multiuserinput[p] =  0;desc = 11;};};};};};\
  240.         id_x = 'input_triangles_x';id_y = 'input_triangles_y';id_r = 'input_triangles_r';\
  241.        }\
  242.        else\
  243.        {\
  244.         if( draw_things[p] == 'text' ){\
  245.          var canvas_text = create_canvas%d(1007,xsize,ysize);\
  246.          var context_text = canvas_text.getContext(\"2d\");\
  247.          context_text.font = multifont_family;\
  248.          context_text.fillStyle = \"rgba(\"+multifont_color+\",\"+multistrokeopacity[p]+\")\";\
  249.          var text_snap = multisnaptogrid[p];\
  250.          var text_x = new Array;var text_y = new Array; var text_abc = new Array();\
  251.          multiuserinput[p] = 1;\
  252.          id_x = 'input_text_x';id_y = 'input_text_y';id_r = 'input_text_r';\
  253.          desc = 13;\
  254.         };\
  255.        };\
  256.       };\
  257.      };\
  258.     };\
  259.    };\
  260.   };\
  261.  };\
  262. };\
  263. inner_html+=\"<tr style='background-color:rgba(\"+multistrokecolors[p]+\",0.4)'><td><input type='button' id='canvasdraw_\"+draw_things[p]+\"' style=\"+button_style+\" onclick='javascript:userdraw_primitive=\"+desc+\";click_cnt = 0;' value='\"+multilabel[p]+\"' /></td><td><input type='button' style='\"+button_style+\"' onclick='javascript:clear_draw_area%d(\"+desc+\",\"+p+\");' value='delete' /></td>\";\
  264. if(multiuserinput[p] == '1'){ \
  265.  if(desc == 0 || desc == 1 ){\
  266.   inner_html+=\"<td><b>(</b><input type='text' size='5' value='' id='\"+id_x+\"' style='\"+button_style+\"' /><b>:</b> <input type='text' size='5' value='' id='\"+id_y+\"' style='\"+button_style+\"' /> <b>)</b></td>\";\
  267.  }\
  268.  else\
  269.  {\
  270.   if(desc == 2 || desc == 3){\
  271.    inner_html+=\"<td><b>M&nbsp;:&nbsp;(<input type='text' size='5' value='' id='\"+id_x+\"' style='\"+button_style+\"' /> : <input type='text' size='5' value='' id='\"+id_y+\"' style='\"+button_style+\"' />)&nbsp;&nbsp;R</b>&nbsp;:&nbsp;<input type='text' size='3' value='' id='\"+id_r+\"' style='\"+button_style+\"' /></b></td>\";\
  272.   }\
  273.   else\
  274.   {\
  275.    if(desc >3 && desc <10 || desc == 14 || desc == 15){\
  276.     inner_html+=\"<td><b>(</b><input type='text' size='5' value='x1 : y1' id='\"+id_x+\"' style='\"+button_style+\";text-align:center;' /><b>) --- (</b> <input type='text' size='5' value='x2 : y2' id='\"+id_y+\"' style='\"+button_style+\";text-align:center;' /> <b>)</b></td>\";\
  277.    }\
  278.    else\
  279.    {\
  280.     if( desc == 10 || desc == 11 ){\
  281.      inner_html+=\"<td><b>(<input type='text' size='5' value='x1 : y1' id='\"+id_x+\"' style='\"+button_style+\"' />) -- (<input type='text' size='5' value='x2 : y2' id='\"+id_y+\"' style='\"+button_style+\"' />) -- (<input type='text' size='5' value='x3 : y3' id='\"+id_r+\"' style='\"+button_style+\"' />)</b></td>\";\
  282.     }\
  283.     else\
  284.     {\
  285.      if( desc == 12 ){\
  286.       inner_html+=\"<td><b>(<input type='text' size='8' value='x1,x2...x_n' id='\"+id_x+\"' style='\"+button_style+\"' /> ---- <input type='text' size='8' value='y1,y2...y_n' id='\"+id_y+\"' style='\"+button_style+\"' />)</b></td>\";\
  287.      }\
  288.      else\
  289.      {\
  290.       if( desc == 13 ){\
  291.        inner_html+=\"<td><b>(<input type='text' size='4' value='x' id='\"+id_x+\"' style='\"+button_style+\"' /> - <input type='text' size='4' value='y' id='\"+id_y+\"' style='\"+button_style+\"' />)</b><input type='text' size='4' value='' id='\"+id_r+\"' style='\"+button_style+\"' /></td>\";\
  292.       };\
  293.      };\
  294.     };\
  295.    };\
  296.   };\
  297.  };\
  298.  inner_html+=\"<td><input type='button' id='canvasdraw_ok_button'  style='\"+button_style+\"' onclick='javascript:update_draw_area%d(\"+desc+\",\"+id_x+\",\"+id_y+\",\"+id_r+\")' value='OK'/ ></td></tr>\";\
  299. }\
  300. else\
  301. {\
  302.  inner_html+\"<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>\";\
  303. };\
  304. };\
  305. if( wims_status != 'done' ){\
  306. tooltip_div.innerHTML = \"<table style=''>\"+inner_html+\"<tr><td>&nbsp;</td><td><input type='button' id='canvasdraw_stop_drawing' style='\"+button_style+\"' value='\"+multilabel[multilabel.length - 1]+\"' onclick='javascript:userdraw_primitive=null;' /></td><td>&nbsp;</td></tr></table>\";\
  307. };\
  308. function x_snap_check(x,snap){\
  309. if( snap == 1 || snap == 2 ){\
  310.  return snap_to_x(x);\
  311. };\
  312. return x;\
  313. };\
  314. function y_snap_check(y,snap){\
  315. if( snap == 1 || snap == 3 ){\
  316.  return snap_to_y(y);\
  317. };\
  318. return y;\
  319. };\
  320. function coord_split(coord){if(coord.indexOf(':') > 0 ){return coord.split(':');}else{if(coord.indexOf(';') > 0 ){return coord.split(';');}else{if(coord.indexOf(',') > 0 ){return coord.split(',');}else{alert(coord+'--> X : Y ');return;};};};};\
  321. function scale_xy(type,xy){var tmp_xmin = xmin;var tmp_xmax = xmax;var tmp_ymin = ymin;var tmp_ymax = ymax;xmin=zoom_xy[0];xmax=zoom_xy[1];ymin=zoom_xy[2];ymax=zoom_xy[3];if(type == 1 ){for(var p=0;p<xy.length;p++){xy[p] = px2x(xy[p]);};}else{for(var p=0;p<xy.length;p++){xy[p] = px2y(xy[p]);};};xmin = tmp_xmin;ymin = tmp_ymin;xmax = tmp_xmax;ymax = tmp_ymax;if(type == 1){for(var p=0;p<xy.length;p++){xy[p] = x2px(xy[p]);}}else{for(var p=0;p<xy.length;p++){xy[p] = y2px(xy[p]);};};return xy;};\
  322. function scale_multi_radius(r){for(var p = 0 ; p < r.length;p++ ){r[p] = zoom_xy[0]/xmin*r[p];};return r;};\
  323. redraw_all%d = function(){\
  324. if( points_x && points_x.length > 0 ){points_x = scale_xy(1,points_x);points_y = scale_xy(1,points_y);draw_points();};\
  325. if( circles_x && circles_x.length > 0 ){circles_x = scale_xy(1,circles_x);circles_y = scale_xy(1,circles_y);multi_radius = scale_multi_radius(multi_radius);draw_circles();};\n\
  326. if( segments_x && segments_x.length > 0 ){segments_x = scale_xy(1,segments_x);segments_y = scale_xy(1,segments_y);draw_segments();};\
  327. if( arrows_x && arrows_x.length > 0 ){arrows_x = scale_xy(1,arrows_x);arrows_y = scale_xy(2,arrows_y);draw_arrows();};\
  328. if( lines_x && lines_x.length > 0 ){lines_x = scale_xy(1,lines_x);lines_y = scale_xy(2,lines_y);draw_lines();};\
  329. if( triangles_x && triangles_x.length > 0 ){triangles_x = scale_xy(1,triangles_x);triangles_y = scale_xy(2,triangles_y);draw_triangles();};\
  330. if( rects_x && rects_x.length > 0 ){rects_x = scale_xy(1,rects_x);rects_y = scale_xy(2,rects_y);draw_rects();};\
  331. if( closedpoly_x && closedpoly_x.length > 0 ){closedpoly_x = scale_xy(1,closedpoly_x);closedpoly_y = scale_xy(2,closedpoly_y);draw_closedpoly();};\
  332. if( text_x && text_x.length > 0 ){text_x = scale_xy(1,text_x);text_y = scale_xy(2,text_y);draw_text();};\
  333. return;\
  334. };\
  335. update_draw_area%d = function(desc,id_x,id_y,id_r){\
  336. var x1,x2,x3,y1,y2,y3,r,A,B;\
  337. x1 = document.getElementById(id_x.id).value;\
  338. y1 = document.getElementById(id_y.id).value;\
  339. if(desc > 3 && desc < 12 || desc == 14 || desc == 15){\
  340.  A = coord_split(x1);B = coord_split(y1);\
  341.  if(A.length != 2 || B.length != 2){alert(' X : Y ');return;};\
  342.  x1 = x2px(safe_eval(A[0]));y1 = y2px(safe_eval(A[1]));\
  343.  x2 = x2px(safe_eval(B[0]));y2 = y2px(safe_eval(B[1]));\
  344.  if(desc == 10 || desc == 11 ){\
  345.   r = document.getElementById(id_r.id).value;\
  346.   A = coord_split(r);\
  347.   x3 = x2px(safe_eval(A[0]));y3 = y2px(safe_eval(A[1]));\
  348.  };\
  349. }\
  350. else\
  351. {\
  352.  if( desc < 4 ){\
  353.   x1 = x2px(safe_eval(x1));y1 = y2px( safe_eval(y1));\
  354.  };\
  355. };\
  356. switch(desc){\
  357.  case 0: points(x1,y1,0,0);break;\
  358.  case 1: points(x1,y1,0,1);break;\
  359.  case 2: r = scale_x_radius(safe_eval(document.getElementById(id_r.id).value));multi_radius[0] = r;circles_x[0] = x1;circles_y[0] = y1;draw_circles();break;\
  360.  case 3: r = scale_x_radius(safe_eval(document.getElementById(id_r.id).value));multi_radius.push(r);circles_x.push(x1);circles_y.push(y1);draw_circles();break;\
  361.  case 4: lines_x[0] = x1;lines_x[1] = x2;lines_y[0] = y1;lines_y[1] = y2;calc_lines();draw_lines();break;\
  362.  case 5: lines_x.push(x1);lines_x.push(x2);lines_y.push(y1);lines_y.push(y2);calc_lines();draw_lines();break;\
  363.  case 6: segments_x[0] = x1;segments_x[1] = x2;segments_y[0] = y1;segments_y[1] = y2;draw_segments();break;\
  364.  case 7: segments_x.push(x1);segments_x.push(x2);segments_y.push(y1);segments_y.push(y2);draw_segments();break;\
  365.  case 8: arrows_x[0] = x1;arrows_x[1] = x2;arrows_y[0] = y1;arrows_y[1] = y2;draw_arrows();break;\
  366.  case 9: arrows_x.push(x1);arrows_x.push(x2);arrows_y.push(y1);arrows_y.push(y2);draw_arrows();break;\
  367.  case 10: triangles_x[0] = x1;triangles_x[1] = x2;triangles_x[2] = x3;triangles_y[0] = y1;triangles_y[1] = y2;triangles_y[2] = y3;draw_triangles();break;\
  368.  case 11: triangles_x.push(x1);triangles_x.push(x2);triangles_x.push(x3);triangles_y.push(y1);triangles_y.push(y2);triangles_y.push(y3);draw_triangles();break;\
  369.  case 12:\
  370.  A = coord_split(x1);B = coord_split(y1);\
  371.  var plus_len = A.length;if( plus_len != B.length){alert('mismatch between the number of x-values and  y-values');return;};\
  372.  for(var p = 0 ; p < plus_len ; p++){\
  373.   x1 = x2px(safe_eval(A[p]));\
  374.   y1 = y2px(safe_eval(B[p]));\
  375.   closedpoly_x.push(x1);\
  376.   closedpoly_y.push(y1);\
  377.  };\
  378.   x1 = x2px(safe_eval(A[0]));\
  379.   y1 = y2px(safe_eval(B[0]));\
  380.   closedpoly_x.push(x1);\
  381.   closedpoly_y.push(y1);\
  382.  draw_closedpoly();break;\
  383.  case 13:text_abc.push( document.getElementById(id_r.id).value);text(x2px(safe_eval(x1)),y2px(safe_eval(y1)),0,1);draw_text();break;\
  384.  default:break;\
  385.  case 14: rects_x[0] = x1;rects_x[1] = x2;rects_y[0] = y1;rects_y[1] = y2;draw_rects();break;\
  386.  case 15: rects_x.push(x1);rects_x.push(x2);rects_y.push(y1);rects_y.push(y2);draw_rects();break;\
  387. };\
  388. };\
  389. <!-- end multidraw -->\n",canvas_root_id,canvas_root_id,draw_types,canvas_root_id,button_style,
  390.  canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,
  391.  canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id );
  392.  
  393. /*
  394.  now add specific draw functions according to draw_types
  395.  these will be somewhat simpler and less fancy-full than for the 'single object' userdraw command...
  396.  the 'switch function' in the mouselisteners will probably eat more CPU...so the rest needs to be faster:
  397.  we don't want to imitate these horribly slow js-libraries like JSXgraph
  398.  
  399. 28/6/2015
  400. TODO: add a selection of the 'generic js-code' from above into these C-code selector parts !
  401. */
  402.  if( strstr(draw_types,"text") != 0){
  403.   fprintf(js_include_file,"function text(x,y,event_which,num){\
  404.   if(event_which == 1){ return; };\
  405.   if( num == 0 ){\
  406.    text_x[0] = x_snap_check(x,text_snap);\
  407.     text_y[0] = y_snap_check(y,text_snap);\
  408.   }else{\
  409.    text_x.push(x_snap_check(x,text_snap));\
  410.    text_y.push(y_snap_check(y,text_snap));\
  411.   };\
  412.   text_abc.push(document.getElementById('input_text_r').value);\
  413.   draw_text();\
  414.  };\
  415.  function draw_text(){\
  416.   context_text.clearRect(0,0,xsize,ysize);\
  417.   for(var p = 0 ; p < text_x.length ; p++ ){\
  418.    context_text.fillText(text_abc[p],text_x[p],text_y[p]);\
  419.   };\
  420.  };");
  421.  }
  422.  
  423.  if( strstr(draw_types,"point") != 0){
  424.   fprintf(js_include_file,"function points(x,y,event_which,num){\
  425.   if(event_which == 1){ return; };\
  426.   if( num == 0 ){\
  427.     points_x[0] = x_snap_check(x,points_snap);\
  428.     points_y[0] = y_snap_check(y,points_snap);\
  429.   }else{\
  430.    points_x.push(x_snap_check(x,points_snap));\
  431.    points_y.push(y_snap_check(y,points_snap));\
  432.   };\
  433.   draw_points();\
  434.  };\
  435.  function draw_points(){\
  436.   var radius = 2*(context_points.lineWidth);\
  437.   context_points.clearRect(0,0,xsize,ysize);\
  438.   for(var p = 0 ; p < points_x.length ; p++ ){\
  439.    context_points.beginPath();\
  440.    context_points.arc(points_x[p],points_y[p],radius,0,2*Math.PI,false);\
  441.    context_points.closePath();\
  442.    context_points.fill();\
  443.   };\
  444.  };");
  445.  }
  446.  if( strstr(draw_types,"circle") != 0){
  447.   fprintf(js_include_file,"function circles(x,y,event_which,num){\
  448.   var last = circles_x.length - 1;\
  449.   var xc = circles_x[last];\
  450.   var yc = circles_y[last];\
  451.   if(event_which == 0){\
  452.    circles_x.push(x_snap_check(x,circles_snap));circles_y.push(y_snap_check(y,circles_snap));multi_radius.push(4);\
  453.    click_cnt++;\
  454.   }\
  455.   else\
  456.   {\
  457.    if( click_cnt == 1 ){\
  458.     multi_radius[last] = parseInt(Math.sqrt( (x - xc)*(x - xc) + (y - yc)*(y - yc) ));\
  459.    };\
  460.   };\
  461.   if( click_cnt == 2 ){\
  462.    click_cnt = 0;\
  463.    circles_x.pop();circles_y.pop();multi_radius.pop();\
  464.    if( num == 0 ){\
  465.     last = circles_x.length - 1;xc = circles_x[last];yc = circles_y[last];var r = multi_radius[last];\
  466.     circles_x = new Array();circles_y = new Array();multi_radius = new Array();\
  467.     circles_x[0] = x_snap_check(xc,circles_snap);circles_y[0] = y_snap_check(yc,circles_snap);multi_radius[0] = r;\
  468.    }\
  469.   };\
  470.   draw_circles();\
  471. };\
  472. function draw_circles(){\
  473.   context_circles.clearRect(0,0,xsize,ysize);\
  474.   for(var p = 0 ; p < circles_x.length ; p++ ){\
  475.    context_circles.beginPath();\
  476.    context_circles.arc(circles_x[p],circles_y[p],multi_radius[p],0,2*Math.PI,false);\
  477.    context_circles.closePath();\
  478.    context_circles.fill();\
  479.    context_circles.stroke();\
  480.   };\
  481.   return;\
  482. };");
  483.  }
  484.  
  485.  if( strstr(draw_types,"segment") != 0){
  486.   fprintf(js_include_file,"function segments(x,y,event_which,num){\
  487.   var last = segments_x.length - 1;\
  488.   if(event_which == 0){\
  489.    if(num == 0){\
  490.     segments_x[0] = x_snap_check(x,segments_snap);segments_y[0] = y_snap_check(y,segments_snap);\
  491.    }\
  492.    else\
  493.    {\
  494.     segments_x.push(x_snap_check(x,segments_snap));segments_y.push(y_snap_check(y,segments_snap));\
  495.    };\
  496.    click_cnt++;\
  497.   }\
  498.   else\
  499.   {\
  500.    if( click_cnt == 1 ){\
  501.     segments_x.push(x_snap_check(x,segments_snap));segments_y.push(y_snap_check(y,segments_snap));\
  502.     draw_segments();\
  503.     segments_x.pop();segments_y.pop();\
  504.    };\
  505.   };\
  506.   if( click_cnt == 2 ){\
  507.    segments_x[last+num] = x_snap_check(x,segments_snap);segments_y[last+num] = y_snap_check(y,segments_snap);\
  508.    click_cnt = 0;\
  509.    draw_segments();\
  510.   };\
  511.  };\
  512.  function draw_segments(){\
  513.   var len = segments_x.length;\
  514.   if( len%%2 == 0 ){\
  515.    context_segments.clearRect(0,0,xsize,ysize);\
  516.    for(var p = 0 ; p < len ; p = p+2 ){\
  517.     context_segments.beginPath();\
  518.     context_segments.moveTo(segments_x[p],segments_y[p]);\
  519.     context_segments.lineTo(segments_x[p+1],segments_y[p+1]);\
  520.     context_segments.closePath();\
  521.     context_segments.stroke();\
  522.    };\
  523.   };\
  524.   return;\
  525.  };");
  526.  }
  527.  if( strstr(draw_types,"arrow") != 0){
  528.   fprintf(js_include_file,"function arrows(x,y,event_which,num){\
  529.   var last = arrows_x.length - 1;\
  530.   if(event_which == 0){\
  531.    if(num == 0){\
  532.     arrows_x[0] =  x_snap_check(x,arrows_snap);arrows_y[0] = y_snap_check(y,arrows_snap);\
  533.    }\
  534.    else\
  535.    {\
  536.     arrows_x.push(x_snap_check(x,arrows_snap));arrows_y.push(y_snap_check(y,arrows_snap));\
  537.    };\
  538.    click_cnt++;\
  539.   }\
  540.   else\
  541.   {\
  542.    if( click_cnt == 1 ){\
  543.     arrows_x.push(x_snap_check(x,arrows_snap));arrows_y.push(y_snap_check(y,arrows_snap));\
  544.     draw_arrows();\
  545.     arrows_x.pop();arrows_y.pop();\
  546.    };\
  547.   };\
  548.   if( click_cnt == 2 ){\
  549.    arrows_x[last+num] = x_snap_check(x,arrows_snap);arrows_y[last+num] = y_snap_check(y,arrows_snap);\
  550.    click_cnt = 0;\
  551.    draw_arrows();\
  552.   };\
  553.  };\
  554.  function draw_arrows(){\
  555.   var len = arrows_x.length;\
  556.   var x1,y1,x2,y2,dx,dy,h;\
  557.   if( len%%2 == 0 ){\
  558.    context_arrows.clearRect(0,0,xsize,ysize);\
  559.    for(var p = 0 ; p < len ; p = p+2 ){\
  560.     context_arrows.save();\
  561.     x1 = arrows_x[p];y1 = arrows_y[p];x2 = arrows_x[p+1];y2 = arrows_y[p+1];dx = x2 - x1;dy = y2 - y1;\
  562.     h = Math.sqrt(dx*dx+dy*dy);\
  563.     context_arrows.beginPath();\
  564.     context_arrows.moveTo(x1,y1);\
  565.     context_arrows.lineTo(x2,y2);\
  566.     context_arrows.closePath();\
  567.     context_arrows.stroke();\
  568.     context_arrows.translate(x2,y2);\
  569.     context_arrows.rotate(Math.atan2(dy,dx));\
  570.     context_arrows.beginPath();\
  571.     context_arrows.moveTo(0,0);\
  572.     context_arrows.lineTo(-1*arrow_head,-0.5*arrow_head);\
  573.     context_arrows.lineTo(-1*arrow_head, 0.5*arrow_head);\
  574.     context_arrows.closePath();\
  575.     context_arrows.fill();\
  576.     context_arrows.stroke();\
  577.     context_arrows.restore();\
  578.    };\
  579.   };\
  580.  return;\
  581. };");
  582.  }
  583.  
  584.  
  585.  if( strstr(draw_types,"line") != 0){
  586.   fprintf(js_include_file,"function calc_lines(){\
  587.   var marge = 2;var len = lines_x.length;\
  588.   var x = lines_x;var y = lines_y;\
  589.   lines_x = new Array(len);\
  590.   lines_y = new Array(len);\
  591.   var pp;\
  592.   for(var p = 0 ; p< len ;p = p+2){\
  593.    pp = p+1;\
  594.    if(x[p] < x[pp]+marge && x[p] > x[pp]-marge){\
  595.     lines_x[p] = x[p];lines_x[pp] = x[pp];\
  596.     lines_y[p] = 0;lines_y[pp] = ysize;\
  597.    }\
  598.    else\
  599.    {\
  600.     if(y[p] < y[pp]+marge && y[p] > y[pp]-marge){\
  601.      lines_x[p] = 0;lines_x[pp] = xsize;\
  602.      lines_y[p] = y[p];lines_y[pp] = y[pp];\
  603.     }\
  604.     else\
  605.     {\
  606.      lines_x[p] = 0;lines_x[pp] = xsize;\
  607.      lines_y[p] = y[p] - (x[p])*(y[pp] - y[p])/(x[pp] - x[p]);\
  608.      lines_y[pp] = y[p] + (xsize - x[p])*(y[pp] - y[p])/(x[pp] - x[p]);\
  609.     };\
  610.    };\
  611.   };\
  612.   return;\
  613.  }\
  614.  function lines(x,y,event_which,num){\
  615.   if(event_which == 0){\
  616.    if( num == 0 && click_cnt == 0 ){lines_x = [];lines_y = [];};\
  617.    lines_x.push(x_snap_check(x,lines_snap));lines_y.push(y_snap_check(y,lines_snap));\
  618.    click_cnt++;\
  619.   }\
  620.   else\
  621.   {\
  622.    if( click_cnt == 1 ){\
  623.     lines_x.push(x_snap_check(x,lines_snap));lines_y.push(y_snap_check(y,lines_snap));\
  624.     draw_lines();\
  625.     lines_x.pop();lines_y.pop();\
  626.    };\
  627.   };\
  628.   if( click_cnt == 2 ){\
  629.    click_cnt = 0;\
  630.    calc_lines();\
  631.    draw_lines();\
  632.   };\
  633.  };\
  634.  function draw_lines(){\
  635.   var len = lines_x.length;\
  636.   if( len %%2 == 0 ){\
  637.    context_lines.clearRect(0,0,xsize,ysize);\
  638.    for(var p = 0 ; p < len ; p = p+2 ){\
  639.     context_lines.beginPath();\
  640.     context_lines.moveTo(lines_x[p],lines_y[p]);\
  641.     context_lines.lineTo(lines_x[p+1],lines_y[p+1]);\
  642.     context_lines.closePath();\
  643.     context_lines.stroke();\
  644.    };\
  645.   };\
  646.   return;\
  647.  };");
  648.  }
  649.  
  650.  if( strstr(draw_types,"rect") != 0){
  651.   fprintf(js_include_file,"\
  652.  function rects(x,y,event_which,num){\
  653.   if(event_which == 0){\
  654.    if( num == 0 && click_cnt == 0 ){rects_x = [];rects_y = [];};\
  655.    rects_x.push(x_snap_check(x,rects_snap));rects_y.push(y_snap_check(y,rects_snap));\
  656.    click_cnt++;\
  657.   }\
  658.   else\
  659.   {\
  660.    if( click_cnt == 1 ){\
  661.     rects_x.push(x_snap_check(x,rects_snap));rects_y.push(y_snap_check(y,rects_snap));\
  662.     draw_rects();\
  663.     rects_x.pop();rects_y.pop();\
  664.    };\
  665.   };\
  666.   if( click_cnt == 2 ){\
  667.    click_cnt = 0;\
  668.    draw_rects();\
  669.   };\
  670.  };\
  671.  function draw_rects(){\
  672.   var len = rects_x.length;\
  673.   if( len %%2 == 0 ){\
  674.    context_rects.clearRect(0,0,xsize,ysize);\
  675.    for(var p = 0 ; p < len ; p = p+2 ){\
  676.     context_rects.beginPath();\
  677.     context_rects.rect(rects_x[p],rects_y[p],rects_x[p+1]-rects_x[p],rects_y[p+1]-rects_y[p]);\
  678.     context_rects.closePath();\
  679.     context_rects.fill();\
  680.     context_rects.stroke();\
  681.    };\
  682.   };\
  683.   return;\
  684.  };");
  685.  }
  686.  
  687.  if( strstr(draw_types,"closedpoly") != 0 ){
  688.   fprintf(js_include_file,"\
  689.  function check_closed(x1,y1,X,Y){\
  690.   var marge=10;\
  691.   var len = X.length-1;\
  692.   for(var p = 0 ; p < len ; p++){\
  693.    if(x1 < X[p] + marge && x1 > X[p] - marge ){\
  694.     if(y1 < Y[p] + marge && y1 > Y[p] - marge ){\
  695.      return 1;\
  696.     };\
  697.    };\
  698.   };\
  699.   return 0;\
  700.  };\
  701.  function closedpoly(x,y,event_which,num){\
  702.   if(event_which == 0){\
  703.    if(click_cnt == 0){\
  704.     closedpoly_x = [];closedpoly_y = [];\
  705.     closedpoly_x[0] = x_snap_check(x,closedpoly_snap);closedpoly_y[0] = y_snap_check(y,closedpoly_snap);\
  706.    }\
  707.    else\
  708.    {\
  709.     closedpoly_x.push(x_snap_check(x,closedpoly_snap));closedpoly_y.push(y_snap_check(y,closedpoly_snap));\
  710.    };\
  711.    click_cnt++;\
  712.    if( click_cnt > 2 ){\
  713.     if( check_closed(x,y,closedpoly_x,closedpoly_y) == 1){\
  714.      draw_closedpoly();\
  715.      click_cnt = 0;\
  716.     };\
  717.    }\
  718.   }\
  719.   else\
  720.   {\
  721.    if( click_cnt > 0 ){\
  722.     closedpoly_x.push(x_snap_check(x,closedpoly_snap));closedpoly_y.push(y_snap_check(y,closedpoly_snap));\
  723.     draw_closedpoly();\
  724.     closedpoly_x.pop();closedpoly_y.pop();\
  725.    };\
  726.   };\
  727.  };\
  728.  function draw_closedpoly(){\
  729.   var len = closedpoly_x.length;\
  730.   context_closedpoly.clearRect(0,0,xsize,ysize);\
  731.   var p = 0;\
  732.   context_closedpoly.beginPath();\
  733.   context_closedpoly.moveTo(closedpoly_x[0],closedpoly_y[0]);\
  734.   for(var p = 1 ; p < len ; p++){\
  735.    context_closedpoly.lineTo(closedpoly_x[p],closedpoly_y[p]);\
  736.   };\
  737.   context_closedpoly.lineTo(closedpoly_x[0],closedpoly_y[0]);\
  738.   context_closedpoly.closePath();\
  739.   context_closedpoly.fill();\
  740.   context_closedpoly.stroke();\
  741.   return;\
  742.  };");
  743.  }
  744. /* the next : just one type allowed triangel;.poly[3-9],parallelogram */
  745.  if( strstr(draw_types,"triangle") != 0 ){
  746.    fprintf(js_include_file,"\
  747.   function triangles(x,y,event_which,num){\
  748.    var last = triangles_x.length - 1;\
  749.    if(event_which == 0){\
  750.     if(num == 0 && click_cnt == 0){\
  751.      triangles_x = [];triangles_y = [];\
  752.      triangles_x[0] = x_snap_check(x,triangles_snap);triangles_y[0] = y_snap_check(y,triangles_snap);\
  753.     }\
  754.     else\
  755.     {\
  756.      triangles_x.push(x_snap_check(x,triangles_snap));triangles_y.push(y_snap_check(y,triangles_snap));\
  757.     };\
  758.     click_cnt++;\
  759.    }\
  760.    else\
  761.    {\
  762.     if( click_cnt < 3 ){\
  763.      triangles_x.push(x_snap_check(x,triangles_snap));triangles_y.push(y_snap_check(y,triangles_snap));\
  764.      draw_triangles();\
  765.      triangles_x.pop();triangles_y.pop();\
  766.     };\
  767.    };\
  768.    if( click_cnt == 3 ){\
  769.     triangles_x.pop();triangles_y.pop();\
  770.     triangles_x.push(x_snap_check(x,triangles_snap));triangles_y.push(y_snap_check(y,triangles_snap));\
  771.     click_cnt = 0;\
  772.     draw_triangles();\
  773.    };\
  774.   };\
  775.   function draw_triangles(){\
  776.    var len = triangles_x.length - 1;\
  777.    context_triangles.clearRect(0,0,xsize,ysize);\
  778.    for(var p = 0 ; p < len ; p = p+3){\
  779.     context_triangles.beginPath();\
  780.     context_triangles.moveTo(triangles_x[p],triangles_y[p]);\
  781.     for( var m = p+1 ;m < p+3 ; m++){\
  782.      context_triangles.lineTo(triangles_x[m],triangles_y[m]);\
  783.     };\
  784.     context_triangles.lineTo(triangles_x[p],triangles_y[p]);\
  785.     context_triangles.closePath();\
  786.     context_triangles.fill();\
  787.     context_triangles.stroke();\
  788.    };\
  789.    return;\
  790.   };");
  791.  }
  792.  else
  793.  {
  794.    /* need to rethink the parallelogram !!! 26/6/2015 */
  795.  if(strstr( draw_types,"parallel") != 0){
  796.   fprintf(js_include_file,"\
  797.    function triangles(x,y,event_which,num){\
  798.     var l2 = triangles_x.length;\
  799.     var l1 = l2 - 1;\
  800.     var l0 = l2 - 2;\
  801.    if(event_which == 0){\
  802.     if(click_cnt == 0){\
  803.      if(num==0){triangles_x = [];triangles_y = [];};\
  804.      triangles_x.push(x_snap_check(x,triangles_snap));triangles_y.push(y_snap_check(y,triangles_snap));\
  805.     }\
  806.     else\
  807.     {\
  808.      triangles_x.push(x_snap_check(x,triangles_snap));triangles_y.push(y_snap_check(y,triangles_snap));\
  809.      if(click_cnt == 2){\
  810.       triangles_x.push(x_snap_check(triangles_x[l2]-triangles_x[l1] + triangles_x[l0]));\
  811.       triangles_y.push(y_snap_check(triangles_y[l2]-triangles_y[l1] + triangles_y[l0]));\
  812.      };\
  813.     };\
  814.     click_cnt++;\
  815.    }\
  816.    else\
  817.    {\
  818.      if(click_cnt > 0 && click_cnt < 3){\
  819.       triangles_x.push(x_snap_check(x,triangles_snap));triangles_y.push(y_snap_check(y,triangles_snap));\
  820.       triangles_x.push(x_snap_check(triangles_x[l2]-triangles_x[l1] + triangles_x[l0]));\
  821.       triangles_y.push(y_snap_check(triangles_y[l2]-triangles_y[l1] + triangles_y[l0]));\
  822.       draw_triangles();\
  823.       triangles_x.pop();triangles_y.pop();\
  824.       triangles_x.pop();triangles_y.pop();\
  825.      };\
  826.    };\
  827.    if( click_cnt == 3 ){\
  828.     triangles_x.pop();triangles_y.pop();\
  829.     triangles_x.push(x_snap_check(triangles_x[l2]-triangles_x[l1] + triangles_x[l0]));\
  830.     triangles_y.push(y_snap_check(triangles_y[l2]-triangles_y[l1] + triangles_y[l0]));\
  831.     triangles_x.push(x_snap_check(x,triangles_snap));triangles_y.push(y_snap_check(y,triangles_snap));\
  832.     triangles_x.pop();triangles_y.pop();\
  833.     click_cnt = 0;\
  834.     draw_triangles();\
  835.    };\
  836.   };\
  837.   function draw_triangles(){\
  838.    var len = triangles_x.length - 1;\
  839.    context_triangles.clearRect(0,0,xsize,ysize);\
  840.    for(var p = 0 ; p < len ; p = p+4){\
  841.     context_triangles.beginPath();\
  842.     context_triangles.moveTo(triangles_x[p],triangles_y[p]);\
  843.     for( var m = p+1 ;m < p+4 ; m++){\
  844.      context_triangles.lineTo(triangles_x[m],triangles_y[m]);\
  845.     };\
  846.     context_triangles.lineTo(triangles_x[p],triangles_y[p]);\
  847.     context_triangles.closePath();\
  848.     context_triangles.fill();\
  849.     context_triangles.stroke();\
  850.    };\
  851.    return;\
  852.   };");
  853.   }
  854.   else
  855.   {
  856.   if( strstr( draw_types,("poly")) != 0 ){
  857.    char *p = draw_types;
  858.    int polynum=-1;
  859.    while( *p ){
  860.     if( isdigit(*p) ){
  861.         polynum = atoi(p);
  862.         break;
  863.     }
  864.     else
  865.     {
  866.         p++;
  867.     }
  868.    }
  869.    if(polynum != -1 ){
  870.     fprintf(js_include_file,"var polynum = %d;\
  871.    function triangles(x,y,event_which,num){\
  872.     var last = triangles_x.length - 1;\
  873.     if(event_which == 0){\
  874.      if(num == 0 && click_cnt == 0){\
  875.       triangles_x = [];triangles_y = [];\
  876.       triangles_x[0] = x_snap_check(x,triangles_snap);triangles_y[0] = y_snap_check(y,triangles_snap);\
  877.      }\
  878.      else\
  879.      {\
  880.       triangles_x.push(x_snap_check(x,triangles_snap));triangles_y.push(y_snap_check(y,triangles_snap));\
  881.      };\
  882.      click_cnt++;\
  883.     }\
  884.     else\
  885.     {\
  886.      if( click_cnt < polynum ){\
  887.       triangles_x.push(x_snap_check(x,triangles_snap));triangles_y.push(y_snap_check(y,triangles_snap));\
  888.       draw_triangles();\
  889.       triangles_x.pop();triangles_y.pop();\
  890.      };\
  891.     };\
  892.     if( click_cnt == polynum ){\
  893.      triangles_x.pop();triangles_y.pop();\
  894.      triangles_x.push(x_snap_check(x,triangles_snap));triangles_y.push(y_snap_check(y,triangles_snap));\
  895.      click_cnt = 0;\
  896.      draw_triangles();\
  897.     };\
  898.    };\
  899.    function draw_triangles(){\
  900.     var len = triangles_x.length - 1;\
  901.     context_triangles.clearRect(0,0,xsize,ysize);\
  902.     for(var p = 0 ; p < len ; p = p+polynum){\
  903.      context_triangles.beginPath();\
  904.      context_triangles.moveTo(triangles_x[p],triangles_y[p]);\
  905.      for( var m = p+1 ;m < p+polynum ; m++){\
  906.       context_triangles.lineTo(triangles_x[m],triangles_y[m]);\
  907.      };\
  908.      context_triangles.lineTo(triangles_x[p],triangles_y[p]);\
  909.      context_triangles.closePath();\
  910.      context_triangles.fill();\
  911.      context_triangles.stroke();\
  912.     };\
  913.     return;\
  914.    };",polynum);
  915.     }
  916.    }
  917.   }
  918.  }
  919. } /* end 'void add_js_multidraw()' */
  920.  
  921. void add_js_circles(FILE *js_include_file,int num,char *draw_type,int line_width, int radius ,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  922. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  923. var num = %d;\
  924. userdraw_radius[0] = %d;\
  925. var line_width = %d;\
  926. var stroke_color = \"%s\";\
  927. var stroke_opacity = %f;\
  928. var use_filled = %d;\
  929. var fill_color = \"%s\";\
  930. var fill_opacity = %f;\
  931. var use_dashed = %d;\
  932. var dashtype1 = %d;\
  933. var dashtype0 = %d;\
  934. var click_cnt = 0;\
  935. var x0,y0,x1,y1;\
  936. var canvas_rect;\
  937. function user_draw(evt){\
  938. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  939. y0 = evt.clientY - canvas_rect.top;\
  940. if(y0 < ysize + 1){\
  941.  x0 = evt.clientX - canvas_rect.left;\
  942.  if( use_snap_to_points != 0 ){\
  943.   var xy = new Array(2);\
  944.   if( use_snap_to_points == 1 ){\
  945.    xy = snap_to_points(x0,y0);\
  946.   }\
  947.   else\
  948.   {\
  949.    xy = snap_to_fun(x0,y0);\
  950.   };\
  951.   x0 = xy[0];y0 = xy[1];\
  952.  }\
  953.  else\
  954.  {\
  955.   if( x_use_snap_to_grid == 1 ){\
  956.    x0 = snap_to_x(x0);\
  957.   };\
  958.   if( y_use_snap_to_grid == 1 ){\
  959.    y0 = snap_to_y(y0);\
  960.   };\
  961.  };\
  962.  if(evt.which == 1){\
  963.   if( click_cnt == 0 ){\
  964.    userdraw_x[xy_cnt] = x0;\
  965.    userdraw_y[xy_cnt] = y0;\
  966.    userdraw_radius[xy_cnt] = line_width;\
  967.    click_cnt = 1;\
  968.    draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  969.   }\
  970.   else\
  971.   {\
  972.    click_cnt = 0;\
  973.    if( num != 1 ){ xy_cnt++; }\
  974.   }\
  975.  }\
  976.  else\
  977.  {\
  978.    canvas_remove(x0,y0);\
  979.  }\
  980. }\
  981. };\
  982. function user_drag(evt){\
  983. if( click_cnt == 1 ){\
  984.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  985.  y1 = evt.clientY - canvas_rect.top;\
  986.  x1 = evt.clientX - canvas_rect.left;\
  987.  if( use_snap_to_points != 0 ){\
  988.   var xy = new Array(2);\
  989.   if( use_snap_to_points == 1 ){\
  990.    xy = snap_to_points(x1,y1);\
  991.   }\
  992.   else\
  993.   {\
  994.    xy = snap_to_fun(x1,y1);\
  995.   };\
  996.   x1 = xy[0];y1 = xy[1];\
  997.  }\
  998.  else\
  999.  {\
  1000.   if( x_use_snap_to_grid == 1 ){\
  1001.     x1 = snap_to_x(x1);\
  1002.   };\
  1003.   if( y_use_snap_to_grid == 1 ){\
  1004.    y1 = snap_to_y(y1);\
  1005.   };\
  1006.  };\
  1007.  userdraw_radius[xy_cnt] = parseInt(Math.sqrt( (x1-x0)*(x1-x0) + (y1-y0)*(y1-y0) ));\
  1008.  userdraw_x[xy_cnt] = x0;\
  1009.  userdraw_y[xy_cnt] = y0;\
  1010.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1011.  draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  1012. };\
  1013. };\
  1014. function canvas_remove(x,y){\
  1015. var marge = 10*line_width;\
  1016. var diff1;var diff2;\
  1017. for(var p = 0;p < userdraw_x.length ; p++){\
  1018.  diff1 = (x-userdraw_x[p])*(x - userdraw_x[p]) + (y - userdraw_y[p])*(y - userdraw_y[p]) - userdraw_radius[p]*userdraw_radius[p];\
  1019.  diff2 = (x-userdraw_x[p])*(x - userdraw_x[p]) + (y - userdraw_y[p])*(y - userdraw_y[p]) - (userdraw_radius[p] - marge)*(userdraw_radius[p] - marge);\
  1020.  if( diff1 < 0 && diff2 > 0 ){\
  1021.   if(confirm(\"remove circle ?\")){\
  1022.    if( num == 1 ){ userdraw_x = [];userdraw_y = []; userdraw_radius = [];xy_cnt = 0;context_userdraw.clearRect(0,0,xsize,ysize); return;}\
  1023.    else\
  1024.    {\
  1025.     userdraw_x.splice(p,1);\
  1026.     userdraw_y.splice(p,1);\
  1027.     userdraw_radius.splice(p,1);\
  1028.     xy_cnt--;\
  1029.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  1030.     draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  1031.    };\
  1032.   };\
  1033.   return;\
  1034.  }\
  1035. }\
  1036. };",draw_type,num,radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);
  1037. }
  1038.  
  1039.  
  1040. /*  function draw_circles(ctx,x_points,y_points,radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);*/
  1041. void add_js_points(FILE *js_include_file,int num,char *draw_type,int line_width, int radius ,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  1042. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  1043. var num = %d;\
  1044. userdraw_radius[0] = %d;\
  1045. var line_width = %d;\
  1046. var stroke_color = \"%s\";\
  1047. var stroke_opacity = %f;\
  1048. var use_filled = %d;\
  1049. var fill_color = \"%s\";\
  1050. var fill_opacity = %f;\
  1051. var use_dashed = %d;\
  1052. var dashtype1 = %d;\
  1053. var dashtype0 = %d;\
  1054. var x0,y0,x1,y1;\
  1055. var canvas_rect;\
  1056. function user_draw(evt){\
  1057. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1058. y0 = evt.clientY - canvas_rect.top;\
  1059. if(y0 < ysize + 1){\
  1060.  x0 = evt.clientX - canvas_rect.left;\
  1061.  if( use_snap_to_points != 0 ){\
  1062.   var xy = new Array(2);\
  1063.   if( use_snap_to_points == 1 ){\
  1064.    xy = snap_to_points(x0,y0);\
  1065.   }\
  1066.   else\
  1067.   {\
  1068.    xy = snap_to_fun(x0,y0);\
  1069.   };\
  1070.   x0 = xy[0];y0 = xy[1];\
  1071.  }\
  1072.  else\
  1073.  {\
  1074.   if( x_use_snap_to_grid == 1 ){\
  1075.    x0 = snap_to_x(x0);\
  1076.   };\
  1077.   if( y_use_snap_to_grid == 1 ){\
  1078.    y0 = snap_to_y(y0);\
  1079.   };\
  1080.  };\
  1081.  if(evt.which == 1){\
  1082.    userdraw_x[xy_cnt] = x0;\
  1083.    userdraw_y[xy_cnt] = y0;\
  1084.    userdraw_radius[xy_cnt] = line_width;\
  1085.    if( num != 1 ){ xy_cnt++; }else{context_userdraw.clearRect(0,0,xsize,ysize);};\
  1086.    draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  1087.  }\
  1088.  else\
  1089.  {\
  1090.    canvas_remove(x0,y0);\
  1091.  };\
  1092. };\
  1093. };\
  1094. function user_drag(evt){ return;};\
  1095. function canvas_remove(x,y){\
  1096. var marge = 4*line_width;\
  1097. for(var p = 0;p < userdraw_x.length ; p++){\
  1098.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  1099.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  1100.    userdraw_x.splice(p,1);userdraw_y.splice(p,1);\
  1101.    context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  1102.    draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  1103.    return;\
  1104.   };\
  1105.  };\
  1106. };\
  1107. };",draw_type,num,radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);
  1108. }
  1109.  
  1110. void add_js_inputs(FILE *js_include_file,int canvas_root_id,int num,int input_cnt,char *input_style,int line_width){
  1111. fprintf(js_include_file,"\n<!-- user draw inputfields -->\n\
  1112. var canvas_rect;\
  1113. var input_cnt = %d;\
  1114. var start_input_cnt = input_cnt;\
  1115. function user_drag(evt){return;}\
  1116. function user_draw(evt){\
  1117. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1118. var x = evt.clientX - canvas_rect.left;\
  1119. var y = evt.clientY - canvas_rect.top;\
  1120. if( use_snap_to_points != 0 ){\
  1121.  var xy = new Array(2);\
  1122.  if( use_snap_to_points == 1 ){\
  1123.   xy = snap_to_points(x,y);\
  1124.  }\
  1125.  else\
  1126.  {\
  1127.   xy = snap_to_fun(x,y);\
  1128.  };\
  1129.  x = xy[0];y = xy[1];\
  1130. }\
  1131. else\
  1132. {\
  1133.  if( x_use_snap_to_grid == 1 ){\
  1134.   x = snap_to_x(x);\
  1135.  };\
  1136.  if( y_use_snap_to_grid == 1 ){\
  1137.   y = snap_to_y(y);\
  1138.  };\
  1139. };\
  1140. var num = %d;var inputs;\
  1141. if(evt.which == 1){\
  1142.  var inputs;var xi;var yi;var wi;var hi;\
  1143.  var found = 0;\
  1144.  if( start_input_cnt < input_cnt){\
  1145.   for(var p = start_input_cnt ; p < input_cnt ; p++ ){\
  1146.    inputs = document.getElementById(\"canvas_input\"+p);\
  1147.    xi = findPosX(inputs) - canvas_rect.left;\
  1148.    yi = findPosY(inputs) - canvas_rect.top;\
  1149.    wi = 4 + inputs.clientWidth;\
  1150.    hi = 4 + inputs.clientHeight;\
  1151.    if( x > xi - wi && x < xi + wi && y > yi - hi && y < yi + hi ){\
  1152.     found = 1;\
  1153.    };\
  1154.   };\
  1155.  };\
  1156.  if( found == 0 ){\
  1157.   if( num == 1 ){\
  1158.    inputs = document.getElementById(\"canvas_input\"+start_input_cnt);\
  1159.    try{canvas_div.removeChild(inputs);}catch(e){};\
  1160.    input_cnt = 0;\
  1161.   };\
  1162.   userdraw_x.push(x);userdraw_y.push(y);\
  1163.   draw_inputs(%d,input_cnt,x,y,%d,1,\"%s\",\"?\");\
  1164.   input_cnt++;\
  1165.  };\
  1166. }\
  1167. else\
  1168. {\
  1169.  for(var p = start_input_cnt ; p < input_cnt; p++){\
  1170.   inputs = document.getElementById(\"canvas_input\"+p);\
  1171.   try{canvas_div.removeChild(inputs);}catch(e){};\
  1172.  };\
  1173.  userdraw_x = [];userdraw_y = [];\
  1174.  input_cnt = start_input_cnt;\
  1175. };\
  1176. };",input_cnt,num,canvas_root_id,line_width,input_style);
  1177. }
  1178.  
  1179. void add_zoom_buttons(FILE *js_include_file,int canvas_root_id,char *stroke_color,double stroke_opacity){
  1180. fprintf(js_include_file,"\n<!-- draw zoom buttons -->\n\
  1181. var draw_zoom_buttons = function(){\
  1182. var obj;var canvas_type =%d;\
  1183. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){\
  1184.  obj = document.getElementById(\"wims_canvas%d\"+canvas_type);\
  1185. }\
  1186. else\
  1187. {\
  1188.  obj = create_canvas%d(canvas_type,xsize,ysize);\
  1189. };\
  1190. var ctx = obj.getContext(\"2d\");\
  1191. ctx.font =\"18px Ariel\";\
  1192. ctx.textAlign = \"right\";\
  1193. ctx.fillStyle=\"rgba(%s,%f)\";\
  1194. ctx.fillText(\"+\",xsize,ysize);\
  1195. ctx.fillText(\"\\u2212\",xsize - 15,ysize);\
  1196. ctx.fillText(\"\\u2192\",xsize - 30,ysize-2);\
  1197. ctx.fillText(\"\\u2190\",xsize - 45,ysize-2);\
  1198. ctx.fillText(\"\\u2191\",xsize - 60,ysize-2);\
  1199. ctx.fillText(\"\\u2193\",xsize - 75,ysize-2);\
  1200. ctx.fillText(\"\\u00D7\",xsize - 90,ysize-2);\
  1201. ctx.stroke();\
  1202. };\ndraw_zoom_buttons();",BG_CANVAS,canvas_root_id,canvas_root_id,canvas_root_id,stroke_color,stroke_opacity);
  1203. }
  1204.  
  1205.  
  1206. void add_js_crosshairs(FILE *js_include_file,int num,char *draw_type,int line_width, int crosshair_size ,char *stroke_color,double stroke_opacity){
  1207. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on currect active canvas -->\n\
  1208. var num = %d;\
  1209. var crosshair_size = %d;\
  1210. var canvas_rect;\
  1211. var line_width = %d;\
  1212. var stroke_color = \"%s\";\
  1213. var stroke_opacity = %f;\
  1214. context_userdraw.lineWidth = line_width;\
  1215. context_userdraw.strokeStyle=\"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  1216. function user_drag(evt){return;}\
  1217. function user_draw(evt){\
  1218. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1219. var x = evt.clientX - canvas_rect.left;\
  1220. var y = evt.clientY - canvas_rect.top;\
  1221. if( use_snap_to_points != 0 ){\
  1222.  var xy = new Array(2);\
  1223.  if( use_snap_to_points == 1 ){\
  1224.   xy = snap_to_points(x,y);\
  1225.  }\
  1226.  else\
  1227.  {\
  1228.   xy = snap_to_fun(x,y);\
  1229.  };\
  1230.  x = xy[0];y = xy[1];\
  1231. }\
  1232. else\
  1233. {\
  1234.  if( x_use_snap_to_grid == 1 ){\
  1235.   x = snap_to_x(x);\
  1236.  };\
  1237.  if( y_use_snap_to_grid == 1 ){\
  1238.   y = snap_to_y(y);\
  1239.  };\
  1240. };\
  1241. var x1,y1,x2,y2;\
  1242. if(evt.which == 1){\
  1243.   userdraw_x[xy_cnt] = x;\
  1244.   userdraw_y[xy_cnt] = y;\
  1245.   x1 = x - crosshair_size;\
  1246.   x2 = x + crosshair_size;\
  1247.   y1 = y - crosshair_size;\
  1248.   y2 = y + crosshair_size;\
  1249.   if( num != 1 ){ xy_cnt++;\
  1250.    for(var p = 0; p < xy_cnt - 1 ;p++){\
  1251.     if(x1 < userdraw_x[p] && x2 > userdraw_x[p]){\
  1252.      if(y1 < userdraw_y[p] && y2 > userdraw_y[p]){\
  1253.       canvas_remove(x,y);\
  1254.       context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");\
  1255.      }\
  1256.     }\
  1257.    }\
  1258.   };\
  1259.   context_userdraw.beginPath();\
  1260.   context_userdraw.moveTo(x1,y1);\
  1261.   context_userdraw.lineTo(x2,y2);\
  1262.   context_userdraw.closePath();\
  1263.   context_userdraw.stroke();\
  1264.   context_userdraw.beginPath();\
  1265.   context_userdraw.moveTo(x2,y1);\
  1266.   context_userdraw.lineTo(x1,y2);\
  1267.   context_userdraw.closePath();\
  1268.   context_userdraw.stroke();\
  1269.   context_userdraw.clearRect(0,0,xsize,ysize);\
  1270.   draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  1271. }\
  1272. else\
  1273. {\
  1274. canvas_remove(x,y);\
  1275. }\
  1276. }\
  1277. function canvas_remove(x,y){\
  1278. var marge = 2*crosshair_size;\
  1279. for(var p = 0;p < userdraw_x.length ; p++){\
  1280.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  1281.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  1282.    userdraw_x.splice(p,1);userdraw_y.splice(p,1);\
  1283.    context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);xy_cnt--;\
  1284.    draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  1285.    return;\
  1286.   }\
  1287.  }\
  1288. }\
  1289. };",draw_type,num,crosshair_size,line_width,stroke_color,stroke_opacity);
  1290. }
  1291.  
  1292. void add_js_rect(FILE *js_include_file,int num,int roundrect,char *draw_type,int line_width,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  1293. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on currect active canvas -->\n\
  1294. var canvas_rect;\
  1295. var roundrect = %d;\
  1296. var line_width = %d;\
  1297. var stroke_color = \"%s\";\
  1298. var stroke_opacity = %f;\
  1299. var use_filled = %d;\
  1300. var fill_color = \"%s\";\
  1301. var fill_opacity = %f;\
  1302. var use_dashed = %d;\
  1303. var dashtype0 = %d;\
  1304. var dashtype1 = %d;\
  1305. var num = %d;\
  1306. var use_rotate = 0;\
  1307. var angle = 0;\
  1308. var closed_path = 1;\
  1309. var clickcnt = 0;\
  1310. xy_cnt = 0;\
  1311. var x0,y0,x1,y1;\
  1312. var marge = 10*line_width;\
  1313. function user_draw(evt){\
  1314. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1315. y0 = evt.clientY - canvas_rect.top;\
  1316. if( y0  < ysize + 1 ){\
  1317.  x0 = evt.clientX - canvas_rect.left;\
  1318.  if( use_snap_to_points != 0 ){\
  1319.   var xy = new Array(2);\
  1320.   if( use_snap_to_points == 1 ){\
  1321.    xy = snap_to_points(x0,y0);\
  1322.   }\
  1323.   else\
  1324.   {\
  1325.    xy = snap_to_fun(x0,y0);\
  1326.   };\
  1327.   x0 = xy[0];y0 = xy[1];\
  1328.  }\
  1329.  else\
  1330.  {\
  1331.   if( x_use_snap_to_grid == 1 ){\
  1332.    x0 = snap_to_x(x0);\
  1333.   };\
  1334.   if( y_use_snap_to_grid == 1 ){\
  1335.    y0 = snap_to_y(y0);\
  1336.   };\
  1337.  };\
  1338.  if( evt.which == 1 ){\
  1339.   if(clickcnt == 0 ){\
  1340.    clickcnt = 1;\
  1341.    userdraw_x[xy_cnt] = x0;userdraw_y[xy_cnt] = y0;xy_cnt++;\
  1342.   }\
  1343.   else\
  1344.   {\
  1345.    clickcnt = 0;\
  1346.    if(roundrect == 0 ){\
  1347.     draw_rects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  1348.    }\
  1349.    else\
  1350.    {\
  1351.     draw_roundrects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  1352.    }\
  1353.    if( num != 1 ){ xy_cnt++; }else{xy_cnt--;}\
  1354.   }\
  1355.  }\
  1356.  else\
  1357.  {\
  1358.   canvas_remove(x0,y0);\
  1359.  };\
  1360. };\
  1361. };\
  1362. function user_drag(evt){\
  1363. if( clickcnt == 1 ){\
  1364.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1365.  y1 = evt.clientY - canvas_rect.top;\
  1366.  x1 = evt.clientX - canvas_rect.left;\
  1367.  var xy = new Array(2);\
  1368.  if( use_snap_to_points != 0 ){\
  1369.   if( use_snap_to_points == 1 ){\
  1370.    xy = snap_to_points(x1,y1);\
  1371.   }\
  1372.   else\
  1373.   {\
  1374.    xy = snap_to_fun(x1,y1);\
  1375.   };\
  1376.   x1 = xy[0];y1 = xy[1];\
  1377.  }\
  1378.  else\
  1379.  {\
  1380.   if( x_use_snap_to_grid == 1 ){\
  1381.    x1 = snap_to_x(x1);\
  1382.   };\
  1383.   if( y_use_snap_to_grid == 1 ){\
  1384.   y1 = snap_to_y(y1);\
  1385.   };\
  1386.  };\
  1387.  userdraw_x[xy_cnt] = x1;\
  1388.  userdraw_y[xy_cnt] = y1;\
  1389.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1390.  if( roundrect == 0 ){\
  1391.   draw_rects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  1392.  }\
  1393.  else\
  1394.  {\
  1395.   draw_roundrects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  1396.  };\
  1397. };\
  1398. };\
  1399. function canvas_remove(x,y){\
  1400. for(var p = 0;p < userdraw_x.length ; p++){\
  1401.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  1402.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  1403.    if( confirm(\"remove rectangle ?\" )){\
  1404.     if( p%%2 == 0 ){\
  1405.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  1406.     }\
  1407.     else\
  1408.     {\
  1409.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  1410.     }\
  1411.     xy_cnt--;\
  1412.     context_userdraw.clearRect(0,0,xsize,ysize);\
  1413.     if(xy_cnt < 2){xy_cnt = 0;click_cnt = 0;userdraw_x = [];userdraw_y = [];return;};\
  1414.     if( roundrect == 0 ){\
  1415.      draw_rects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  1416.     }\
  1417.     else\
  1418.     {\
  1419.      draw_roundrects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  1420.     }\
  1421.     return;\
  1422.    };\
  1423.   };\
  1424.  };\
  1425. };\
  1426. };",draw_type,roundrect,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,num);
  1427. }
  1428.  
  1429. void add_js_poly(FILE *js_include_file,int num,char *draw_type,int line_width,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  1430. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on currect active canvas -->\n\
  1431. var canvas_rect;\
  1432. var num = %d;\
  1433. var line_width = %d;\
  1434. var stroke_color = \"%s\";\
  1435. var stroke_opacity = %f;\
  1436. var use_filled = %d;\
  1437. var fill_color = \"%s\";\
  1438. var fill_opacity = %f;\
  1439. var use_dashed = %d;\
  1440. var dashtype0 = %d;\
  1441. var dashtype1 = %d;\
  1442. var use_rotate = 0;\
  1443. var angle = 0;\
  1444. var use_translate = 0;\
  1445. var vector=[0,0];\
  1446. var closed_path = 1;\
  1447. var done = 1;\
  1448. var x,y;\
  1449. var marge = 10*line_width;\
  1450. function user_draw(evt){\
  1451. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1452. y = evt.clientY - canvas_rect.top;\
  1453. if( y < ysize + 1 ){\
  1454.  x = evt.clientX - canvas_rect.left;\
  1455.  var xy = new Array(2);\
  1456.  if( use_snap_to_points != 0 ){\
  1457.   if( use_snap_to_points == 1 ){\
  1458.    xy = snap_to_points(x,y);\
  1459.   }\
  1460.   else\
  1461.   {\
  1462.    xy = snap_to_fun(x,y);\
  1463.   };\
  1464.   x = xy[0];y = xy[1];\
  1465.  }\
  1466.  else\
  1467.  {\
  1468.   if( x_use_snap_to_grid == 1 ){\
  1469.    x = snap_to_x(x);\
  1470.   };\
  1471.   if( y_use_snap_to_grid == 1 ){\
  1472.    y = snap_to_y(y);\
  1473.   };\
  1474.  };\
  1475.  if( evt.which == 1){\
  1476.   if( num == -1 && xy_cnt > 2 ){\
  1477.    if( x - marge < userdraw_x[0] && x + marge > userdraw_x[0]){\
  1478.     if( y - marge < userdraw_y[0] && y + marge > userdraw_y[0]){\
  1479.      userdraw_x.splice(xy_cnt,1);userdraw_y.splice(xy_cnt,1);\
  1480.      draw_paths(context_userdraw,userdraw_x,userdraw_y,line_width,closed_path,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  1481.      done = 1;return;\
  1482.     };\
  1483.    };\
  1484.   }\
  1485.   else\
  1486.   {\
  1487.    if( xy_cnt == num - 1){\
  1488.     draw_paths(context_userdraw,userdraw_x,userdraw_y,line_width,closed_path,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  1489.     done = 1;return;\
  1490.    };\
  1491.   };\
  1492.   done = 0;\
  1493.   userdraw_x[xy_cnt] = x;userdraw_y[xy_cnt] = y;xy_cnt++;\
  1494.   user_drag(evt);\
  1495.  }\
  1496.  else\
  1497.  {\
  1498.   canvas_remove(x,y);\
  1499.   return;\
  1500.  }\
  1501. };\
  1502. };\
  1503. function user_drag(evt){\
  1504. if( done == 0 ){\
  1505.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1506.  x = evt.clientX - canvas_rect.left;\
  1507.  y = evt.clientY - canvas_rect.top;\
  1508.  if( use_snap_to_points != 0 ){\
  1509.   var xy = new Array(2);\
  1510.   if( use_snap_to_points == 1 ){\
  1511.    xy = snap_to_points(x,y);\
  1512.   }\
  1513.   else\
  1514.   {\
  1515.    xy = snap_to_fun(x,y);\
  1516.   };\
  1517.   x = xy[0];y = xy[1];\
  1518.  }\
  1519.  else\
  1520.  {\
  1521.   if( x_use_snap_to_grid == 1 ){\
  1522.    x = snap_to_x(x);\
  1523.   };\
  1524.   if( y_use_snap_to_grid == 1 ){\
  1525.    y = snap_to_y(y);\
  1526.   };\
  1527.  };\
  1528.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1529.  userdraw_x[xy_cnt] = x;userdraw_y[xy_cnt] = y;\
  1530.  draw_paths(context_userdraw,userdraw_x,userdraw_y,line_width,closed_path,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  1531. }\
  1532. }\
  1533. function canvas_remove(x,y){\
  1534. for(var p = 0;p < userdraw_x.length ; p++){\
  1535.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  1536.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  1537.    if( confirm(\"remove polygone ?\" )){\
  1538.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  1539.     xy_cnt = 0;userdraw_x = [];userdraw_y = [];done = 1;\
  1540.    }\
  1541.    return;\
  1542.   }\
  1543.  }\
  1544. }\
  1545. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);
  1546. }
  1547.  
  1548. void add_js_polyline(FILE *js_include_file,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1){
  1549. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  1550. var canvas_rect;\
  1551. var cnt = 0;\
  1552. var line_width = %d;\
  1553. var stroke_color = \"%s\";\
  1554. var stroke_opacity = %f;\
  1555. var use_dashed = %d;\
  1556. var dashtype0 = %d;\
  1557. var dashtype1 = %d;\
  1558. function user_draw(evt){\
  1559. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1560. var x = evt.clientX - canvas_rect.left;\
  1561. var y = evt.clientY - canvas_rect.top;\
  1562. var lu = userdraw_x.length;\
  1563. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1564. if( use_snap_to_points != 0 ){\
  1565.  var xy = new Array(2);\
  1566.  if( use_snap_to_points == 1 ){\
  1567.   xy = snap_to_points(x,y);\
  1568.  }\
  1569.  else\
  1570.  {\
  1571.   xy = snap_to_fun(x,y);\
  1572.  };\
  1573.  x = xy[0];y = xy[1];\
  1574. }\
  1575. else\
  1576. {\
  1577.  if( x_use_snap_to_grid == 1 ){\
  1578.   x = snap_to_x(x);\
  1579.  };\
  1580.  if( y_use_snap_to_grid == 1 ){\
  1581.   y = snap_to_y(y);\
  1582.  };\
  1583. };\
  1584. if( evt.which == 1 ){\
  1585.  userdraw_x[lu] = x;userdraw_y[lu] = y;\
  1586.  if( cnt == 0 ){\
  1587.   user_drag(evt);\
  1588.   cnt = 1;\
  1589.  }\
  1590.  else\
  1591.  {\
  1592.    cnt = 0;\
  1593.    draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1594.  }\
  1595. }\
  1596. else\
  1597. {\
  1598.  canvas_remove(x,y);\
  1599. }\
  1600. };\
  1601. function user_drag(evt){\
  1602. if( cnt == 0){\
  1603.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1604.  var x = evt.clientX - canvas_rect.left;\
  1605.  var y = evt.clientY - canvas_rect.top;\
  1606.  if( use_snap_to_points != 0 ){\
  1607.   var xy = new Array(2);\
  1608.   if( use_snap_to_points == 1 ){\
  1609.    xy = snap_to_points(x,y);\
  1610.   }\
  1611.   else\
  1612.   {\
  1613.    xy = snap_to_fun(x,y);\
  1614.   };\
  1615.   x = xy[0];y = xy[1];\
  1616.  }\
  1617.  else\
  1618.  {\
  1619.   if( x_use_snap_to_grid == 1 ){\
  1620.    x = snap_to_x(x);\
  1621.   };\
  1622.   if( y_use_snap_to_grid == 1 ){\
  1623.    y = snap_to_y(y);\
  1624.   };\
  1625.  };\
  1626.  var lu = userdraw_x.length;\
  1627.  if( lu > 0 ){\
  1628.   userdraw_x[lu - 1] = x; userdraw_y[lu - 1] = y;\
  1629.   draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1630.  };\
  1631. }\
  1632. };\
  1633. function canvas_remove(x,y){\
  1634. if( confirm(\"remove line ?\" )){\
  1635.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1636.  userdraw_x = [];userdraw_y = [];cnt = 1;\
  1637.  return;\
  1638. }\
  1639. };",draw_type,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  1640. }
  1641.  
  1642. void add_js_segments(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1){
  1643. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  1644. var canvas_rect;\
  1645. var num = %d;\
  1646. var line_width = %d;\
  1647. var stroke_color = \"%s\";\
  1648. var stroke_opacity = %f;\
  1649. var use_dashed = %d;\
  1650. var dashtype0 = %d;\
  1651. var dashtype1 = %d;\
  1652. var x0,y0;\
  1653. function user_draw(evt){\
  1654. var lu = userdraw_x.length;\
  1655. if( lu != 0 && lu%%2 == 0){\
  1656.  draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1657. }\
  1658. var y = evt.clientY - canvas_rect.top;\
  1659. if( y < ysize + 1){\
  1660.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1661.  var x = evt.clientX - canvas_rect.left;\
  1662.  if( use_snap_to_points != 0 ){\
  1663.   var xy = new Array(2);\
  1664.   if( use_snap_to_points == 1 ){\
  1665.    xy = snap_to_points(x,y);\
  1666.   }\
  1667.   else\
  1668.   {\
  1669.    xy = snap_to_fun(x,y);\
  1670.   };\
  1671.   x = xy[0];y = xy[1];\
  1672.  }\
  1673.  else\
  1674.  {\
  1675.   if( x_use_snap_to_grid == 1 ){\
  1676.    x = snap_to_x(x);\
  1677.   };\
  1678.   if( y_use_snap_to_grid == 1 ){\
  1679.    y = snap_to_y(y);\
  1680.   };\
  1681.  };\
  1682.  if( evt.which == 1 ){\
  1683.   if( lu%%2 == 0){\
  1684.    x0 = x;y0 = y;\
  1685.    if(num == 1){ userdraw_x = [];userdraw_y = [];userdraw_x[0] = x0;userdraw_y[0] = y0;} else {userdraw_x[lu] = x0;userdraw_y[lu] = y0;}\
  1686.    draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  1687.    user_drag(evt);\
  1688.   }\
  1689.   else\
  1690.   {\
  1691.    if( num == 1 ){ userdraw_x[1] = x;userdraw_y[1] = y;} else {userdraw_x[lu] = x;userdraw_y[lu] = y;};\
  1692.    draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1693.   }\
  1694.  }\
  1695.  else\
  1696.  {\
  1697.   canvas_remove(x,y);\
  1698.  }\
  1699. }\
  1700. };\
  1701. function user_drag(evt){\
  1702. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1703. var x = evt.clientX - canvas_rect.left;\
  1704. var y = evt.clientY - canvas_rect.top;\
  1705. var lu = userdraw_x.length;\
  1706. if( use_snap_to_points != 0 ){\
  1707.  var xy = new Array(2);\
  1708.  if( use_snap_to_points == 1 ){\
  1709.   xy = snap_to_points(x,y);\
  1710.  }\
  1711.  else\
  1712.  {\
  1713.   xy = snap_to_fun(x,y);\
  1714.  };\
  1715.  x = xy[0];y = xy[1];\
  1716. }\
  1717. else\
  1718. {\
  1719.  if( x_use_snap_to_grid == 1 ){\
  1720.   x = snap_to_x(x);\
  1721.  };\
  1722.  if( y_use_snap_to_grid == 1 ){\
  1723.   y = snap_to_y(y);\
  1724.  };\
  1725. };\
  1726. if( lu%%2 != 0 ){\
  1727.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1728.  draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  1729.  draw_circles(context_userdraw,[x],[y],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  1730.  draw_segments(context_userdraw,[x0,x],[y0,y],line_width,stroke_color,stroke_opacity);\
  1731.  if( lu > 0){\
  1732.   draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1733.  }\
  1734. }\
  1735. };\
  1736. function canvas_remove(x,y){\
  1737. var marge = 10*line_width;\
  1738. for(var p = 0;p < userdraw_x.length ; p++){\
  1739.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  1740.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  1741.    if( confirm(\"remove line ?\" )){\
  1742.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  1743.     if( p%%2 == 0 ){\
  1744.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  1745.     }\
  1746.     else\
  1747.     {\
  1748.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  1749.     }\
  1750.     if(userdraw_x.length < 2){ userdraw_x = [];userdraw_y = [];return;};\
  1751.     draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1752.    }\
  1753.    return;\
  1754.   }\
  1755.  }\
  1756. }\
  1757. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  1758. }
  1759.  
  1760. void add_js_demilines(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1){
  1761. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  1762. var canvas_rect;\
  1763. var num = %d;\
  1764. var line_width = %d;\
  1765. var stroke_color = \"%s\";\
  1766. var stroke_opacity = %f;\
  1767. var use_dashed = %d;\
  1768. var dashtype0 = %d;\
  1769. var dashtype1 = %d;\
  1770. var x0,y0;\
  1771. function user_draw(evt){\
  1772. var lu = userdraw_x.length;\
  1773. if( lu != 0 && lu%%2 == 0){\
  1774.  draw_demilines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1775. }\
  1776. var y = evt.clientY - canvas_rect.top;\
  1777. if( y < ysize + 1){\
  1778.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1779.  var x = evt.clientX - canvas_rect.left;\
  1780.  if( use_snap_to_points != 0 ){\
  1781.   var xy = new Array(2);\
  1782.   if( use_snap_to_points == 1 ){\
  1783.    xy = snap_to_points(x,y);\
  1784.   }\
  1785.   else\
  1786.   {\
  1787.    xy = snap_to_fun(x,y);\
  1788.   };\
  1789.   x = xy[0];y = xy[1];\
  1790.  }\
  1791.  else\
  1792.  {\
  1793.   if( x_use_snap_to_grid == 1 ){\
  1794.    x = snap_to_x(x);\
  1795.   };\
  1796.   if( y_use_snap_to_grid == 1 ){\
  1797.    y = snap_to_y(y);\
  1798.   };\
  1799.  };\
  1800.  if( evt.which == 1 ){\
  1801.   if( lu%%2 == 0){\
  1802.    x0 = x;y0 = y;\
  1803.    if(num == 1){ userdraw_x = [];userdraw_y = [];userdraw_x[0] = x0;userdraw_y[0] = y0;} else {userdraw_x[lu] = x0;userdraw_y[lu] = y0;}\
  1804.    draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  1805.    user_drag(evt);\
  1806.   }\
  1807.   else\
  1808.   {\
  1809.    if( num == 1 ){ userdraw_x[1] = x;userdraw_y[1] = y;} else {userdraw_x[lu] = x;userdraw_y[lu] = y;};\
  1810.    draw_demilines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1811.   }\
  1812.  }\
  1813.  else\
  1814.  {\
  1815.   canvas_remove(x,y);\
  1816.  }\
  1817. }\
  1818. };\
  1819. function user_drag(evt){\
  1820. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1821. var x = evt.clientX - canvas_rect.left;\
  1822. var y = evt.clientY - canvas_rect.top;\
  1823. var lu = userdraw_x.length;\
  1824. if( use_snap_to_points != 0 ){\
  1825.  var xy = new Array(2);\
  1826.  if( use_snap_to_points == 1 ){\
  1827.   xy = snap_to_points(x,y);\
  1828.  }\
  1829.  else\
  1830.  {\
  1831.   xy = snap_to_fun(x,y);\
  1832.  };\
  1833.  x = xy[0];y = xy[1];\
  1834. }\
  1835. else\
  1836. {\
  1837.  if( x_use_snap_to_grid == 1 ){\
  1838.   x = snap_to_x(x);\
  1839.  };\
  1840.  if( y_use_snap_to_grid == 1 ){\
  1841.   y = snap_to_y(y);\
  1842.  };\
  1843. };\
  1844. if( lu%%2 != 0 ){\
  1845.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1846.  draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  1847.  draw_circles(context_userdraw,[x],[y],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  1848.  draw_demilines(context_userdraw,[x0,x],[y0,y],line_width,stroke_color,stroke_opacity);\
  1849.  if( lu > 0){\
  1850.   draw_demilines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1851.  }\
  1852. }\
  1853. };\
  1854. function canvas_remove(x,y){\
  1855. var marge = 10*line_width;\
  1856. for(var p = 0;p < userdraw_x.length ; p++){\
  1857.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  1858.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  1859.    if( confirm(\"remove line ?\" )){\
  1860.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  1861.     if( p%%2 == 0 ){\
  1862.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  1863.     }\
  1864.     else\
  1865.     {\
  1866.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  1867.     }\
  1868.     if(userdraw_x.length < 2){ userdraw_x = [];userdraw_y = [];return;};\
  1869.     draw_demilines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1870.    }\
  1871.    return;\
  1872.   }\
  1873.  }\
  1874. }\
  1875. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  1876. }
  1877.  
  1878.  
  1879. /*
  1880. num=1 single horizontal line
  1881. num=2 multiple horizontal lines
  1882. num=3 single vertical line
  1883. num=4 multiple vertical lines
  1884. */
  1885. void add_js_hlines(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1){
  1886. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  1887. var canvas_rect;\
  1888. var num = %d;\
  1889. var line_width = %d;\
  1890. var stroke_color = \"%s\";\
  1891. var stroke_opacity = %f;\
  1892. var use_dashed = %d;\
  1893. var dashtype0 = %d;\
  1894. var dashtype1 = %d;\
  1895. var x0,y0;\
  1896. function user_draw(evt){\
  1897. if( evt.which == 1 ){\
  1898.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1899.  var y = evt.clientY - canvas_rect.top;\
  1900.  var x = evt.clientX - canvas_rect.left;\
  1901.  if( use_snap_to_points != 0 ){\
  1902.   var xy = new Array(2);\
  1903.   if( use_snap_to_points == 1 ){\
  1904.    xy = snap_to_points(x,y);\
  1905.   }\
  1906.   else\
  1907.   {\
  1908.    xy = snap_to_fun(x,y);\
  1909.   };\
  1910.   x = xy[0];y = xy[1];\
  1911.  }\
  1912.  else\
  1913.  {\
  1914.   if( x_use_snap_to_grid == 1 ){\
  1915.    x = snap_to_x(x);\
  1916.   };\
  1917.   if( y_use_snap_to_grid == 1 ){\
  1918.    y = snap_to_y(y);\
  1919.   };\
  1920.  };\
  1921.  var lu = userdraw_x.length;\
  1922.  switch(num){\
  1923.   case 1: userdraw_x[0] = x;userdraw_x[1] = xmax;userdraw_y[0] = y; userdraw_y[1] = y;break;\
  1924.   case 2: userdraw_x[lu] = x;userdraw_x[lu+1] = xmax;userdraw_y[lu] = y;userdraw_y[lu+1] = y;break;\
  1925.   case 3: userdraw_x[0] = x;userdraw_x[1] = x;userdraw_y[0] = y; userdraw_y[1] = ymax;break;\
  1926.   case 4: userdraw_x[lu] = x;userdraw_x[lu+1] = x;userdraw_y[lu] = y;userdraw_y[lu+1] = ymax;break;\
  1927.  };\
  1928.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1929.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1930. }\
  1931. else\
  1932. {\
  1933.  userdraw_x = [];userdraw_y = [];context_userdraw.clearRect(0,0,xsize,ysize);return;\
  1934. };\
  1935. };\
  1936. function user_drag(evt){ return evt; };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  1937. }
  1938.  
  1939.  
  1940.  
  1941. void add_js_lines(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1){
  1942. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  1943. var canvas_rect;\
  1944. var num = %d;\
  1945. var line_width = %d;\
  1946. var stroke_color = \"%s\";\
  1947. var stroke_opacity = %f;\
  1948. var use_dashed = %d;\
  1949. var dashtype0 = %d;\
  1950. var dashtype1 = %d;\
  1951. var x0,y0;\
  1952. function user_draw(evt){\
  1953. var lu = userdraw_x.length;\
  1954. if( lu != 0 && lu%%2 == 0){\
  1955.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1956. }\
  1957. var y = evt.clientY - canvas_rect.top;\
  1958. if( y < ysize + 1){\
  1959.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1960.  var x = evt.clientX - canvas_rect.left;\
  1961.  if( use_snap_to_points != 0 ){\
  1962.   var xy = new Array(2);\
  1963.   if( use_snap_to_points == 1 ){\
  1964.    xy = snap_to_points(x,y);\
  1965.   }\
  1966.   else\
  1967.   {\
  1968.    xy = snap_to_fun(x,y);\
  1969.   };\
  1970.   x = xy[0];y = xy[1];\
  1971.  }\
  1972.  else\
  1973.  {\
  1974.   if( x_use_snap_to_grid == 1 ){\
  1975.    x = snap_to_x(x);\
  1976.   };\
  1977.   if( y_use_snap_to_grid == 1 ){\
  1978.    y = snap_to_y(y);\
  1979.   };\
  1980.  };\
  1981.  if( evt.which == 1 ){\
  1982.   if( lu%%2 == 0){\
  1983.    x0 = x;y0 = y;\
  1984.    if(num == 1){ userdraw_x = [];userdraw_y = [];userdraw_x[0] = x0;userdraw_y[0] = y0;} else {userdraw_x[lu] = x0;userdraw_y[lu] = y0;}\
  1985.    draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  1986.    user_drag(evt);\
  1987.   }\
  1988.   else\
  1989.   {\
  1990.    if( num == 1 ){ userdraw_x[1] = x;userdraw_y[1] = y;} else {userdraw_x[lu] = x;userdraw_y[lu] = y;};\
  1991.    draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1992.   };\
  1993.  }\
  1994.  else\
  1995.  {\
  1996.   canvas_remove(x,y);\
  1997.  };\
  1998. };\
  1999. };\
  2000. function user_drag(evt){\
  2001. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  2002. var x = evt.clientX - canvas_rect.left;\
  2003. var y = evt.clientY - canvas_rect.top;\
  2004. var lu = userdraw_x.length;\
  2005. if( use_snap_to_points != 0 ){\
  2006.  var xy = new Array(2);\
  2007.  if( use_snap_to_points == 1 ){\
  2008.   xy = snap_to_points(x,y);\
  2009.  }\
  2010.  else\
  2011.  {\
  2012.   xy = snap_to_fun(x,y);\
  2013.  };\
  2014.  x = xy[0];y = xy[1];\
  2015. }\
  2016. else\
  2017. {\
  2018.  if( x_use_snap_to_grid == 1 ){\
  2019.   x = snap_to_x(x);\
  2020.  };\
  2021.  if( y_use_snap_to_grid == 1 ){\
  2022.   y = snap_to_y(y);\
  2023.  };\
  2024. };\
  2025. if( lu%%2 != 0 ){\
  2026.  context_userdraw.clearRect(0,0,xsize,ysize);\
  2027.  draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  2028.  draw_circles(context_userdraw,[x],[y],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  2029.  draw_lines(context_userdraw,[x0,x],[y0,y],line_width,stroke_color,stroke_opacity);\
  2030.  if( lu > 0){\
  2031.   draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  2032.  }\
  2033. }\
  2034. };\
  2035. function canvas_remove(x,y){\
  2036. var marge = 10*line_width;\
  2037. for(var p = 0;p < userdraw_x.length ; p++){\
  2038.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  2039.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  2040.    if( confirm(\"remove line ?\" )){\
  2041.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  2042.     if( p%%2 == 0 ){\
  2043.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  2044.     }\
  2045.     else\
  2046.     {\
  2047.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  2048.     }\
  2049.     if(userdraw_x.length < 2){ userdraw_x = [];userdraw_y = [];return;};\
  2050.     draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  2051.    }\
  2052.    return;\
  2053.   }\
  2054.  }\
  2055. }\
  2056. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  2057. }
  2058.  
  2059.  
  2060. void add_js_arrows(FILE *js_include_file,int num,char *draw_type,int line_width,int type, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1,int arrow_head){
  2061. /*
  2062. constants in draw_arrows() ... for this moment: ;var use_rotate = 0;var angle = 0;var use_translate = 0 ;var vector = [0,0];\
  2063. */
  2064. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  2065. var canvas_rect;\
  2066. var num = %d;\
  2067. var line_width = %d;\
  2068. var stroke_color = \"%s\";\
  2069. var stroke_opacity = %f;\
  2070. var use_dashed = %d;\
  2071. var dashtype0 = %d;\
  2072. var dashtype1 = %d;\
  2073. var arrow_head = %d;\
  2074. var x0,y0;\
  2075. var type = %d;\
  2076. var use_rotate = 0;var angle = 0;var use_translate = 0 ;var vector = [0,0];\
  2077. function user_draw(evt){\
  2078. var lu = userdraw_x.length;\
  2079. if( lu != 0 && lu%%2 == 0){\
  2080.  draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,0,[1,0,0,1,0,0]);\
  2081. }\
  2082. var y = evt.clientY - canvas_rect.top;\
  2083. if( y < ysize + 1){\
  2084.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  2085.  var x = evt.clientX - canvas_rect.left;\
  2086.  if( use_snap_to_points != 0 ){\
  2087.   var xy = new Array(2);\
  2088.   if( use_snap_to_points == 1 ){\
  2089.    xy = snap_to_points(x,y);\
  2090.   }\
  2091.   else\
  2092.   {\
  2093.    xy = snap_to_fun(x,y);\
  2094.   };\
  2095.   x = xy[0];y = xy[1];\
  2096.  }\
  2097.  else\
  2098.  {\
  2099.   if( x_use_snap_to_grid == 1 ){\
  2100.    x = snap_to_x(x);\
  2101.   };\
  2102.   if( y_use_snap_to_grid == 1 ){\
  2103.    y = snap_to_y(y);\
  2104.   };\
  2105.  };\
  2106.  if( evt.which == 1 ){\
  2107.   if( lu%%2 == 0){\
  2108.    x0 = x;y0 = y;\
  2109.    if(num == 1){ userdraw_x = [];userdraw_y = [];userdraw_x[0] = x0;userdraw_y[0] = y0;} else {userdraw_x[lu] = x0;userdraw_y[lu] = y0;}\
  2110.    user_drag(evt);\
  2111.   }\
  2112.   else\
  2113.   {\
  2114.    if( num == 1 ){ userdraw_x[1] = x;userdraw_y[1] = y;} else {userdraw_x[lu] = x;userdraw_y[lu] = y;};\
  2115.    draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,0,[1,0,0,1,0,0]);\
  2116.   }\
  2117.  }\
  2118.  else\
  2119.  {\
  2120.   canvas_remove(x,y);\
  2121.  }\
  2122. }\
  2123. };\
  2124. function user_drag(evt){\
  2125. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  2126. var x = evt.clientX - canvas_rect.left;\
  2127. var y = evt.clientY - canvas_rect.top;\
  2128. var lu = userdraw_x.length;\
  2129. if( use_snap_to_points != 0 ){\
  2130.  var xy = new Array(2);\
  2131.  if( use_snap_to_points == 1 ){\
  2132.   xy = snap_to_points(x,y);\
  2133.  }\
  2134.  else\
  2135.  {\
  2136.   xy = snap_to_fun(x,y);\
  2137.  };\
  2138.  x = xy[0];y = xy[1];\
  2139. }\
  2140. else\
  2141. {\
  2142.  if( x_use_snap_to_grid == 1 ){\
  2143.   x = snap_to_x(x);\
  2144.  };\
  2145.  if( y_use_snap_to_grid == 1 ){\
  2146.   y = snap_to_y(y);\
  2147.  };\
  2148. };\
  2149. if( lu%%2 != 0 ){\
  2150.  context_userdraw.clearRect(0,0,xsize,ysize);\
  2151.  draw_arrows(context_userdraw,[x0,x],[y0,y],arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,0,[1,0,0,1,0,0]);\
  2152.  if( lu > 0){\
  2153.    draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,0,[1,0,0,1,0,0]);\
  2154.  }\
  2155. }\
  2156. };\
  2157. function canvas_remove(x,y){\
  2158. var marge = 10*line_width;\
  2159. for(var p = 0;p < userdraw_x.length ; p++){\
  2160.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  2161.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  2162.    if( confirm(\"remove line ?\" )){\
  2163.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  2164.     if( p%%2 == 0 ){\
  2165.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  2166.     }\
  2167.     else\
  2168.     {\
  2169.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  2170.     }\
  2171.     if(userdraw_x.length < 2){ userdraw_x = [];userdraw_y = [];return;};\
  2172.     draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,0,[1,0,0,1,0,0],type,use_rotate,angle,0,[1,0,0,1,0,0]);\
  2173.    }\
  2174.    return;\
  2175.   }\
  2176.  }\
  2177. }\
  2178. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,arrow_head,type);
  2179.  
  2180. }
  2181.  
  2182. void add_js_paths(FILE *js_include_file,int num,char *draw_type,int line_width, int closed_path,char *stroke_color,double stroke_opacity,int use_filled, char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  2183. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  2184. var path_cnt = 0;\
  2185. var temp_x = [];\
  2186. var temp_y = [];\
  2187. var num = %d;\
  2188. xy_cnt=0;\
  2189. var line_width = %d;\
  2190. var stroke_color = \"%s\";\
  2191. var stroke_opacity = %f;\
  2192. var fill_color = \"%s\";\
  2193. var fill_opacity = %f;\
  2194. var use_filled = %d;\
  2195. var use_dashed = %d;\
  2196. var dashtype0 = %d;\
  2197. var dashtype1 = %d;\
  2198. var closed_path = 0;\
  2199. var click_cnt=0;\
  2200. var x0,y0;\
  2201. var canvas_rect = canvas_userdraw.getBoundingClientRect();\
  2202. function user_draw(evt){\
  2203. if(evt.which == 1 ){\
  2204.  if( click_cnt == 0 ){\
  2205.   click_cnt = 1;\
  2206.   user_drag(evt);\
  2207.  }\
  2208.  else\
  2209.  {\
  2210.   userdraw_x[path_cnt] = new Array();\
  2211.   userdraw_y[path_cnt] = new Array();\
  2212.   userdraw_x[path_cnt] = temp_x;\
  2213.   userdraw_y[path_cnt] = temp_y;\
  2214.   path_cnt++;\
  2215.   temp_x = [];\
  2216.   temp_y = [];\
  2217.   click_cnt = 0;\
  2218.   xy_cnt = 0;\
  2219.  };\
  2220. }\
  2221. else\
  2222. {\
  2223.   canvas_remove(evt.clientX - canvas_rect.left,evt.clientY - canvas_rect.top);\
  2224. };\
  2225. context_userdraw.clearRect(0,0,xsize,ysize);\
  2226. for(var p=0; p < path_cnt; p++){\
  2227.  if(userdraw_x[p] != null){\
  2228.   draw_paths(context_userdraw,userdraw_x[p],userdraw_y[p],line_width,0,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  2229.  };\
  2230. };\
  2231. };\
  2232. function user_drag(evt){\
  2233. if(click_cnt == 1 ){\
  2234.  temp_y[xy_cnt] = evt.clientY - canvas_rect.top;\
  2235.  if( temp_y[xy_cnt] < ysize + 1){\
  2236.   temp_x[xy_cnt] = evt.clientX - canvas_rect.left;\
  2237.   if( x_use_snap_to_grid == 1 ){\
  2238.    temp_x[xy_cnt] = snap_to_x(temp_x[xy_cnt]);\
  2239.   };\
  2240.   if( y_use_snap_to_grid == 1 ){\
  2241.    temp_y[xy_cnt] = snap_to_y(temp_y[xy_cnt]);\
  2242.   };\
  2243.   xy_cnt++;\
  2244.   draw_paths(context_userdraw,temp_x,temp_y,line_width,0,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  2245.  };\
  2246. };\
  2247. };\
  2248. function canvas_remove(x,y){\
  2249. var marge = 4*line_width;\
  2250. var tmpx = [];\
  2251. var tmpy = [];\
  2252. for(var i = 0 ; i < path_cnt; i++){\
  2253.  tmpx = userdraw_x[i];\
  2254.  if(tmpx != null){\
  2255.   tmpy = userdraw_y[i];\
  2256.   for(var p = 0;p<tmpx.length;p++){\
  2257.    if( x + marge > tmpx[p] &&  x - marge < tmpx[p] ){\
  2258.     if( y + marge > tmpy[p] &&  y - marge < tmpy[p] ){\
  2259.      if(confirm(\"Remove this drawing ?\")){\
  2260.       userdraw_x[i] = null;\
  2261.       userdraw_y[i] = null;\
  2262.       xy_cnt = 0;click_cnt = 0;\
  2263.       return;\
  2264.      };\
  2265.     };\
  2266.    };\
  2267.   };\
  2268.  };\
  2269. };\
  2270. };",draw_type,num,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1);
  2271. }
  2272.  
  2273. void add_js_popup(int canvas_root_id,int xsize,int ysize,char *getfile_cmd){
  2274. fprintf(stdout,"\n<!-- begin command popup %d -->\n\
  2275. <script type=\"text/javascript\">\n\
  2276. if( wims_status != 'done'){\n\
  2277. var popup = window.open('','','toolbar=no,scrollbars=yes,menubar=no,location=no,resizable=yes,top=4,left=4,status=no, width = %dpx, height = %dpx');\n\
  2278. var popupHTML =\"<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'>\\n<html><head></head>\\n<body><div style='width:%dpx;height:%dpx;position:relative' id='canvas_div%d'></div><div id='tooltip_placeholder_div%d' style='display:block;position:relative;margin-left:auto;margin-right:auto;margin-bottom:4px;'><span id='tooltip_placeholder%d' style='display:none;'></span></div></body></html>\";\n\
  2279. popup.document.write(popupHTML);\n\
  2280. var s0 = popup.document.createElement(\"script\");\n\
  2281. s0.text=\"var wims_status = window.opener.wims_status; var use_dragdrop_reply = window.opener.use_dragdrop_reply;window.opener.canvas_scripts.push('%d');\";\n\
  2282. popup.document.getElementsByTagName(\"HEAD\")[0].appendChild(s0);\n\
  2283. var s1 = popup.document.createElement(\"script\");\n\
  2284. s1.type = \"text/javascript\";\n\
  2285. s1.src = \"%s\"\n\
  2286. popup.document.getElementsByTagName(\"HEAD\")[0].appendChild(s1);\n\
  2287. popup.document.close();\n\
  2288. }else{\n\
  2289. var canvas_div = document.getElementById('canvas_div%d');\n\
  2290. canvas_div.style.display='block';\n\
  2291. };\n\
  2292. \n</script>\n\
  2293. <!-- end command popup %d -->\n",
  2294. canvas_root_id,
  2295. xsize+40,ysize+40,
  2296. xsize,ysize,
  2297. canvas_root_id,
  2298. canvas_root_id,
  2299. canvas_root_id,
  2300. canvas_root_id,
  2301. getfile_cmd,
  2302. canvas_root_id,
  2303. canvas_root_id);
  2304. }
  2305.  
  2306. void add_js_tooltip(int canvas_root_id,char *tooltip_text,char *bgcolor,int xsize,int ysize){
  2307. fprintf(stdout,"\n<!-- begin command intooltip %d -->\n\
  2308. <script type=\"text/javascript\">\n\
  2309. var xsize = %d;\
  2310. var ysize = %d;\
  2311. var tooltip%d_obj_x = 0;\
  2312. var tooltip%d_obj_y = 0;\
  2313. var tooltip%d_flipflop = 0;\
  2314. var tooltip%d_obj = document.getElementById(\"canvas_div%d\");\
  2315. tooltip%d_obj.style.display=\"none\";\
  2316. tooltip%d_obj.style.position=\"absolute\";\
  2317. var tooltip%d_link = document.createElement(\"a\");\
  2318. tooltip%d_link.addEventListener(\"mousemove\",tooltip%d_drag,false);\
  2319. tooltip%d_link.setAttribute(\"onclick\",\"tooltip%d_show()\");\
  2320. tooltip%d_link.innerHTML  = \"%s\";\
  2321. var tooltip_placeholder = document.getElementById(\"tooltip_placeholder%d\");\
  2322. tooltip_placeholder.style.display=\"block\";\
  2323. tooltip_placeholder.style.position=\"absolute\";\
  2324. tooltip_placeholder.style.backgroundColor=\"%s\";\
  2325. tooltip_placeholder.appendChild(tooltip%d_link);\
  2326. function tooltip%d_drag(action){\
  2327. if(!action){ action = event; }\
  2328. if(action.clientX){\
  2329.  tooltip%d_obj.style.left = (tooltip%d_mouseX(action) + 10) +\"px\";\
  2330.  var ytop = tooltip%d_mouseY(action);\
  2331.  if(ytop + ysize < window.innerHeight){\
  2332.   tooltip%d_obj.style.top = (ytop - 10) +\"px\";\
  2333.  }\
  2334.  else\
  2335.  {\
  2336.   tooltip%d_obj.style.top = parseInt(ytop - 0.8*ysize) +\"px\";\
  2337.  }\
  2338. }\
  2339. else\
  2340. {\
  2341.  return null;\
  2342. }\
  2343. }\
  2344. function tooltip%d_mouseX(action){\
  2345. if(action.pageX){\
  2346.  return action.pageX;\
  2347. }\
  2348. else\
  2349. {\
  2350.  if(action.clientX){\
  2351.   return action.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);\
  2352.  }\
  2353.  else\
  2354.  {\
  2355.   return null;\
  2356.  }\
  2357. }\
  2358. }\
  2359. function tooltip%d_mouseY(action){\
  2360. if(action.pageY){\
  2361.  return action.pageY;\
  2362. }\
  2363. else\
  2364. {\
  2365.  if(action.clientY){\
  2366.   return action.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop :document.body.scrollTop);\
  2367.  }\
  2368.  else\
  2369.  {\
  2370.   return null;\
  2371.  }\
  2372. }\
  2373. }\
  2374. function tooltip%d_show(){\
  2375. if(tooltip%d_flipflop == 0){\
  2376.  tooltip%d_obj.style.display = \"block\";\
  2377.  tooltip%d_flipflop = 1;\
  2378. }\
  2379. else\
  2380. {\
  2381.  tooltip%d_flipflop = 0;\
  2382.  tooltip%d_obj.style.display = \"none\";\
  2383. }\
  2384. };\n</script>\n<!-- end command intooltip %d -->\n",canvas_root_id,xsize,ysize,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,tooltip_text,canvas_root_id,bgcolor,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id);
  2385.  
  2386. }
  2387.  
  2388. void add_js_arc(FILE *js_include_file,int canvas_root_id,int num,int line_width,char *stroke_color,double stroke_opacity,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  2389. fprintf(js_include_file,"\n<!-- begin userdraw \"arc\" on final canvas -->\n\
  2390. var canvas_rect;\
  2391. function user_draw(evt){\
  2392. var num = %d;\
  2393. var x,xc,x1,x2,y,yc,y1,y2;var lu = userdraw_x.length;\
  2394. if( num == 1 && lu == 3 ){ userdraw_x = [];userdraw_y = [];userdraw_radius = [];};\
  2395. if(evt.which == 1){\
  2396.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  2397.  x = evt.clientX - canvas_rect.left;\
  2398.  y = evt.clientY - canvas_rect.top;\
  2399.  if( use_snap_to_points != 0 ){\
  2400.   var xy = new Array(2);\
  2401.   if( use_snap_to_points == 1 ){\
  2402.    xy = snap_to_points(x,y);\
  2403.   }\
  2404.   else\
  2405.   {\
  2406.    xy = snap_to_fun(x,y);\
  2407.   };\
  2408.   x = xy[0];y = xy[1];\
  2409.  }\
  2410.  else\
  2411.  {\
  2412.   if( x_use_snap_to_grid == 1 ){x = snap_to_x(x);};\
  2413.   if( y_use_snap_to_grid == 1 ){y = snap_to_y(y);};\
  2414.  };\
  2415.  if(num == 1 && lu == 3){userdraw_x = [];userdraw_y = [];userdraw_radius = [];};\
  2416.  lu = userdraw_x.push(x);userdraw_y.push(y);\
  2417.  if( lu != 0 && lu%%3 == 0){\
  2418.   context_userdraw.clearRect(0,0,xsize,ysize);\
  2419.   userdraw_radius = [];\
  2420.   for(var p = 0 ; p < lu; p = p + 3){\
  2421.     xc = userdraw_x[p];\
  2422.     yc = userdraw_y[p];\
  2423.     x1 = userdraw_x[p+1];\
  2424.     x2 = userdraw_x[p+2];\
  2425.     y1 = userdraw_y[p+1];\
  2426.     y2 = userdraw_y[p+2];\
  2427.     draw_userarc(context_userdraw,xc,yc,x1,y1,x2,y2,%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d);\
  2428.   };\
  2429.  };\
  2430. }\
  2431. else\
  2432. {\
  2433.  if( confirm(\"remove drawing ?\") ){\
  2434.   context_userdraw.clearRect(0,0,xsize,ysize);userdraw_x = [];userdraw_y = [];userdraw_radius = [];return;\
  2435.  };\
  2436. };\
  2437. };\
  2438. function user_drag(evt){ \
  2439. var lu = userdraw_x.length;\
  2440. if( (lu+1)%%3 == 0) {\
  2441.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  2442.  var x2 = evt.clientX - canvas_rect.left;\
  2443.  var y2 = evt.clientY - canvas_rect.top;\
  2444.  var xc = userdraw_x[lu-2];\
  2445.  var yc = userdraw_y[lu-2];\
  2446.  var x1 = userdraw_x[lu-1];\
  2447.  var y1 = userdraw_y[lu-1];\
  2448.  context_userdraw.clearRect(0,0,xsize,ysize);\
  2449.  draw_userarc(context_userdraw,xc,yc,x1,y1,x2,y2,1,\"255,0,0\",0.6,\"255,255,0\",0.4,0,2,2);\
  2450. };\
  2451. return;\
  2452. };\
  2453. var draw_userarc = function(ctx,xc,yc,x1,y1,x2,y2,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1){\
  2454. ctx.save();\
  2455. if( use_dashed == 1){if(ctx.setLineDash){ctx.setLineDash([dashtype0,dashtype1]);}else{if(ctx.mozDash){ ctx.mozDash = [dashtype0,dashtype1];};};};\
  2456. ctx.lineWidth = line_width;\
  2457. ctx.strokeStyle =  \"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  2458. ctx.fillStyle = \"rgba(\"+fill_color+\",\"+fill_opacity+\")\";\
  2459. var alpha = find_angle(xc,yc,x1,y1,x2,y2);\
  2460. if( %d == 1 ){userdraw_radius[0] = alpha;ctx.clearRect(0,0,xsize,ysize);}else{userdraw_radius.push(alpha);};\
  2461. var r = Math.sqrt(Math.pow(xc-x2,2)+Math.pow(yc-y2,2));\
  2462. var start;var tmp;var beta;\
  2463. if( x1 > x2 ){\
  2464.  tmp = x2; x2 = x1 ; x1 = tmp;\
  2465.  tmp = y2; y2 = y1 ; y1 = tmp;\
  2466. };\
  2467. if( y1 < yc ){\
  2468.  beta = find_angle(xc,yc,x1,yc,x1,y1);\
  2469.   if( x1 < xc ){\
  2470.    start = Math.PI + beta;\
  2471.   }\
  2472.   else\
  2473.   {\
  2474.    start = 2*Math.PI - beta;\
  2475.   }\
  2476. }\
  2477. else\
  2478. {\
  2479.  beta = find_angle(xc,yc,x2,yc,x2,y2);\
  2480.  if(x2 > xc){\
  2481.   start = beta;\
  2482.  }\
  2483.  else\
  2484.  {\
  2485.   start = Math.PI - beta;\
  2486.  }\
  2487. };\
  2488. ctx.translate(xc,yc);\
  2489. ctx.rotate(start);\
  2490. ctx.beginPath();\
  2491. ctx.arc(0,0,r,0,alpha,false);\
  2492. ctx.lineTo(0,0);\
  2493. ctx.closePath();\
  2494. ctx.fill();\
  2495. ctx.stroke();\
  2496. ctx.restore();\
  2497. };\
  2498. function find_angle(xc,yc,x1,y1,x2,y2){\
  2499. var a = Math.sqrt(Math.pow(xc-x1,2)+Math.pow(yc-y1,2));\
  2500. var b = Math.sqrt(Math.pow(xc-x2,2)+Math.pow(yc-y2,2));\
  2501. var c = Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2));\
  2502. return Math.acos((b*b+a*a-c*c)/(2*b*a));\
  2503. };",num,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,num);
  2504. }
  2505.  
  2506. void add_js_text(FILE *js_include_file,int canvas_root_id,int font_size,char *font_family,char *font_color,double stroke_opacity){
  2507. fprintf(js_include_file,"\n<!-- begin command userdraw text -->\n\
  2508. canvas_div.addEventListener(\"keydown\",user_text,false);\
  2509. var context_userdraw = canvas_userdraw.getContext(\"2d\");\
  2510. var font_color = \"%s\";\
  2511. var font_opacity = %f;\
  2512. var font_size = %d;\
  2513. var font_family = \"%s\";\
  2514. context_userdraw.fillStyle = \"rgba(\"+font_color+\",\"+font_opacity+\")\";\
  2515. context_userdraw.font = font_family;\
  2516. var userdraw_text = new Array();\
  2517. var txt_cnt = 0;\
  2518. var txt=\"\";\
  2519. var x_txt = 0;\
  2520. var y_txt = 0;\
  2521. var w_txt = 0;\
  2522. var typing = 0;\
  2523. var canvas_rect = canvas_userdraw.getBoundingClientRect();\
  2524. function user_draw(evt){\
  2525. y_txt = evt.clientY - canvas_rect.top;\
  2526. x_txt = evt.clientX - canvas_rect.left;\
  2527. if( use_snap_to_points != 0 ){\
  2528.  var xy = new Array(2);\
  2529.  if( use_snap_to_points == 1 ){\
  2530.   xy = snap_to_points(x_txt,y_txt);\
  2531.  }\
  2532.  else\
  2533.  {\
  2534.   xy = snap_to_fun(x_txt,y_txt);\
  2535.  };\
  2536.  x_txt = xy[0];y_txt = xy[1];\
  2537. }\
  2538. else\
  2539. {\
  2540.  if( x_use_snap_to_grid == 1 ){\
  2541.   x_txt = snap_to_x(x_txt);\
  2542.  };\
  2543.  if( y_use_snap_to_grid == 1 ){\
  2544.   y_txt = snap_to_y(y_txt);\
  2545.  };\
  2546. };\
  2547. return;\
  2548. };\
  2549. function user_drag(evt){\
  2550. return;\
  2551. };\
  2552. function user_text(evt){\
  2553. var kc = evt.keyCode;var w;\
  2554. if( kc== 8 || kc == 27 || kc == 46 ){\
  2555.  if(typing == 1 ){\
  2556.    w = context_userdraw.measureText(txt).width;\
  2557.    context_userdraw.clearRect(x_txt-2,y_txt-font_size-2,w+2,font_size+2);\
  2558.    txt = \"\";\
  2559.  }\
  2560.  else\
  2561.  {\
  2562.   for( var p=0 ; p < txt_cnt; p++){\
  2563.    var tmp = (userdraw_text[p]).split(\":\");\
  2564.    w = context_userdraw.measureText(tmp[0]).width;\
  2565.    var y1 = y_txt - font_size;\
  2566.    var y2 = y_txt + font_size;\
  2567.    if( tmp[1] < y2 && tmp[1] > y1){\
  2568.     var x1 = x_txt - font_size;\
  2569.     var x2 = x_txt + w;\
  2570.     if( tmp[0] < x2 && tmp[0] > x1){\
  2571.      if (confirm(\"delete this text : \"+tmp[2]+\"?\")){\
  2572.       context_userdraw.clearRect(x1,y1,x2,y2);\
  2573.       userdraw_text.splice(p,1);\
  2574.       txt_cnt--;\
  2575.       return;\
  2576.      };\
  2577.     };\
  2578.    };\
  2579.   };\
  2580.  };\
  2581. }\
  2582. else\
  2583. {\
  2584.  if( kc < 126 && kc > 40 ){\
  2585.   typing = 1;\
  2586.   txt=txt+String.fromCharCode(kc);\
  2587.   w = context_userdraw.measureText(txt).width;\
  2588.   context_userdraw.save();\
  2589.   context_userdraw.fillStyle = \"lightblue\";\
  2590.   context_userdraw.beginPath();\
  2591.   context_userdraw.rect(x_txt,y_txt-font_size,w,font_size);\
  2592.   context_userdraw.closePath();\
  2593.   context_userdraw.fill();\
  2594.   context_userdraw.restore();\
  2595.   context_userdraw.fillText(txt,x_txt,y_txt);\
  2596.  }\
  2597.  else\
  2598.  {\
  2599.   if(kc == 13 ){\
  2600.    w = context_userdraw.measureText(txt).width;\
  2601.    if(w < 1){alert(\"nothing typed...try again\");return;};\
  2602.    context_userdraw.clearRect(x_txt,y_txt-font_size,w,font_size);\
  2603.    context_userdraw.fillText(txt,x_txt,y_txt);\
  2604.    userdraw_text[txt_cnt] = Math.round(x_txt)+\":\"+Math.round(y_txt)+\":\"+txt;\
  2605.    txt=\"\";\
  2606.    w = 0;\
  2607.    txt_cnt++;\
  2608.    typing = 0;\
  2609.    return;\
  2610.   };\
  2611.  };\
  2612. };\
  2613. };",font_color,stroke_opacity,font_size,font_family);
  2614.  
  2615. }
  2616.  
  2617. /*
  2618.  
  2619. type = 0 : x-values only [command mousex]
  2620. type = 1 : y-values only [command mousey]
  2621. type = 2 : (x:y)         [command mouse]
  2622. type = 3 : degrees       [command mouse_degree]
  2623. */
  2624. void add_js_mouse(FILE *js_include_file,int canvas_cnt,int canvas_root_id,int precision,char *stroke_color,int font_size,double stroke_opacity,int type){
  2625. fprintf(js_include_file,"\n<!-- begin command mouse on current canvas -->\n\
  2626. function use_mouse_coordinates(){\
  2627. var type = %d;\
  2628. var current_canvas = create_canvas%d(%d,xsize,ysize);\
  2629. var current_context = current_canvas.getContext(\"2d\");\
  2630. current_context.clearRect(0,0,xsize,ysize);\
  2631. current_canvas.addEventListener(\"mousemove\",show_coordinate%d,false);\
  2632. current_canvas.addEventListener(\"touchmove\",show_coordinate%d,false);\
  2633. var prec = Math.log(%d)/(Math.log(10));\
  2634. function show_coordinate%d(evt){\
  2635.  var canvas_rect = (current_canvas).getBoundingClientRect();\
  2636.  var x = evt.clientX - canvas_rect.left;\
  2637.  var y = evt.clientY - canvas_rect.top;\
  2638.  var m_data = \"\";var l = userdraw_x.length;\
  2639.  switch(type){\
  2640.   case 0: m_data = \" \"+(px2x(x)).toFixed(prec)+\" \"+unit_x;break;\
  2641.   case 1: m_data = \" \"+(px2y(y)).toFixed(prec)+\" \"+unit_y;break;\
  2642.   case 2: m_data = \"(\"+(px2x(x)).toFixed(prec)+\":\"+(px2y(y)).toFixed(prec)+\")\";break;\
  2643.   case 3: m_data = \" \"+( ( Math.atan( ((xmax - xmin)*(px2y(y))) / ((ymax - ymin)*(px2x(x))) ) )/(Math.PI/180) ).toFixed(prec)+\" \\u00B0 \";break;\
  2644.   case 4: if( l > 0 ){ m_data = \" R = \"+((xmax - xmin)*(distance(x,y,userdraw_x[l-1],userdraw_y[l-1]))/xsize).toFixed(prec)+\" \"+unit_x;};break;\
  2645.   default:break;\
  2646.  };\
  2647.  var s = parseInt(0.8*%d*(m_data.toString()).length);\
  2648.  current_context.font = \"%dpx Ariel\";\
  2649.  current_context.fillStyle = \"rgba(%s,%f)\";\
  2650.  current_context.clearRect(0,0,s,1.2*%d);\
  2651.  current_context.fillText(m_data,0,%d);\
  2652. };\
  2653. };",type,canvas_root_id,MOUSE_CANVAS,canvas_root_id,canvas_root_id,precision,canvas_root_id,font_size,font_size,stroke_color,stroke_opacity,font_size,font_size);
  2654. }
  2655. /* to avoid easy js-code injection...but is it a real problem ? */
  2656. void add_safe_eval(FILE *js_include_file){
  2657. fprintf(js_include_file," \nfunction safe_eval(exp){\
  2658. exp = exp.replace(/pi/g,'3.14159');\
  2659. if(exp.indexOf('^') != -1){\
  2660.  exp = exp.replace(/[a-zA-Z]/g,' ');\
  2661.  exp = exp.replace(/\\*10\\^-/g,'e-');\
  2662.  exp = exp.replace(/\\*10\\^/g,'e+');\
  2663.  exp = exp.replace(/10\\^-/g,'1e-');exp = exp.replace(/10\\^/g,'1e+');\
  2664.  exp = eval(exp);\
  2665.  if(isNaN(exp)){alert(\"invalid input\\ntry just a real number \\ne.g. no calculations...\");return null;}\
  2666.  return exp;\
  2667. };\
  2668. var reg = /(?:[a-z$_][a-z0-9$_]*)|(?:[;={}\\[\\]\"'!&<>^\\\\?:])/ig;\
  2669. var valid = true;\
  2670. exp = exp.replace(reg,function($0){\
  2671.  if(Math.hasOwnProperty($0)){\
  2672.   return \"Math.\"+$0;\
  2673.  }\
  2674.  else\
  2675.  {\
  2676.   valid = false;\
  2677.  }\
  2678. }\
  2679. );\
  2680. if( !valid ){\
  2681.  alert(\"hmmm \"+exp+\" ?\"); exp = null;\
  2682. }\
  2683. else\
  2684. {\
  2685.  try{ exp = eval(exp); } catch(e){alert(\"Invalid arithmetic expression\"); exp = null;};\
  2686. };\
  2687. return exp;\
  2688. };");
  2689. }
  2690.  
  2691. /*
  2692. add display of slider value in mouse context
  2693. use_slider_display = 1 : x or x/y
  2694. use_slider_display = 2 : angle in degrees
  2695. use_slider_display = 3 : angle in radians
  2696. */
  2697. void add_slider_display(FILE *js_include_file,int canvas_root_id,int precision,int font_size,char *font_color,double stroke_opacity){
  2698. fprintf(js_include_file,"<!-- begin add_slider_display -->\n\
  2699. function show_slider_value(value,use_slider_display){\
  2700. var current_canvas = create_canvas%d(%d,xsize,ysize);\
  2701. var current_context = current_canvas.getContext(\"2d\");\
  2702. current_context.clearRect(0,0,xsize,ysize);\
  2703. var prec = Math.log(%d)/(Math.log(10));\
  2704. var string;\
  2705. if(use_slider_display == 1){\
  2706.  string = \" \"+value[0].toFixed(prec)+\" \"+unit_x+\":\"+value[1].toFixed(prec)+\" \"+unit_y;\
  2707. }else{\
  2708.  if(use_slider_display == 2){\
  2709.   value[1] = value[1]*180/Math.PI;\
  2710.   string = \" \"+value[1].toFixed(prec)+\"\\u00B0\";\
  2711.  }else{\
  2712.   if(use_slider_display == 3){\
  2713.    string = \" \"+value[1].toFixed(prec)+\" rad\";\
  2714.   };\
  2715.  };\
  2716. };\
  2717. var s = parseInt(1.2*%d*(string).length);\
  2718. current_context.font = \"%dpx Ariel\";\
  2719. current_context.strokeStyle = \"rgba(%s,%.2f)\";\
  2720. current_context.clearRect(0,0,s,1.2*%d);\
  2721. current_context.fillText(string,0,%d);\
  2722. };\n",canvas_root_id,MOUSE_CANVAS,precision,font_size,font_size,font_color,stroke_opacity,font_size,font_size);
  2723. }
  2724. /*
  2725. add slider
  2726. return value is array : value[0] is the actual value between value_1 and value_2
  2727. */
  2728. void add_slider(FILE *js_include_file,int canvas_root_id,double v1,double v2,int width,int height,int type,char *label,int slider_cnt,char *stroke_color,char *fill_color,int line_width,double opacity,char *font_family,char *font_color,int use_slider_display){
  2729. fprintf(js_include_file,"\n<!-- begin add_slider no. %d -->\n\
  2730. function add_slider_%d(){\
  2731. if( wims_status == \"done\" ){return;};\
  2732. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  2733. var slider_type = %d;\
  2734. var span = document.createElement(\"span\");\
  2735. span.setAttribute(\"style\",\"font:%s;color:%s\");\
  2736. var title = document.createTextNode(\" %s \");\
  2737. var br = document.createElement(\"br\");\
  2738. span.appendChild(title);\
  2739. span.appendChild(br);\
  2740. tooltip_div.appendChild(span);\
  2741. var slider_fillcolor = \"%s\";\
  2742. var slider_strokecolor = \"%s\";\
  2743. var slider_linewidth = \"%d\";\
  2744. var slider_canvas = document.createElement(\"canvas\");\
  2745. slider_canvas.id = \"slider_canvas%d\";\
  2746. tooltip_div.appendChild(slider_canvas);\
  2747. br = document.createElement(\"br\");\
  2748. tooltip_div.appendChild(br);\
  2749. var slider_width = %d;\
  2750. var slider_height = %d;\
  2751. var slider_center = %d;\
  2752. var slider_radius = 4*slider_linewidth;\
  2753. var slider_opacity = %f;\
  2754. slider_canvas.width = slider_width;\
  2755. slider_canvas.height = slider_height;\
  2756. var canvas_rect = (slider_canvas).getBoundingClientRect();\
  2757. var slider_ctx = slider_canvas.getContext(\"2d\");\
  2758. slider_ctx.font = \"%s\";\
  2759. slider_ctx.strokeStyle = \"rgba(\"+slider_strokecolor+\",\"+slider_opacity+\")\";\
  2760. slider_ctx.fillStyle = \"rgba(\"+slider_fillcolor+\",\"+slider_opacity+\")\";\
  2761. slider_ctx.lineWidth = slider_linewidth;\
  2762. slider_ctx.beginPath();\
  2763. slider_ctx.arc(10,slider_center,slider_radius,0,2*Math.PI,false);\
  2764. slider_ctx.moveTo(10,slider_center);\
  2765. slider_ctx.lineTo(slider_width-10,slider_center);\
  2766. slider_ctx.rect(0,0,slider_width,slider_height);\
  2767. slider_ctx.closePath();\
  2768. slider_ctx.fill();\
  2769. slider_ctx.stroke();\
  2770. slider_canvas.addEventListener(\"mousemove\",slider_%d,false);\
  2771. function slider_%d(evt){\
  2772. var value_1 = %f;\
  2773. var value_2 = %f;\
  2774. slider_ctx.clearRect(0,0,slider_width,slider_height);\
  2775. var x_px = evt.clientX - canvas_rect.left;\
  2776. var x;var y;\
  2777. if( slider_type == 1 ){\
  2778.  x = x_px*(value_2 - value_1)/slider_width + value_1;\
  2779.  y = 0;\
  2780. }else{\
  2781.  y = x_px*(value_2 - value_1)/slider_width + value_1;\
  2782.  x = 0;\
  2783. };\
  2784. slider_ctx.beginPath();\
  2785. slider_ctx.arc(x_px,slider_center,slider_radius,0,2*Math.PI,false);\
  2786. slider_ctx.moveTo(10,slider_center);\
  2787. slider_ctx.lineTo(slider_width-10,slider_center);\
  2788. slider_ctx.rect(0,0,slider_width,slider_height);\
  2789. slider_ctx.closePath();\
  2790. slider_ctx.fill();\
  2791. slider_ctx.stroke();\
  2792. dragstuff.Slide( [x,y] , %d );\
  2793. if(%d != 0 ){show_slider_value([x,y],%d);};\
  2794. return;\
  2795. };\
  2796. };\
  2797. add_slider_%d();\n",slider_cnt,slider_cnt,canvas_root_id,type,font_family,font_color,label,fill_color,stroke_color,line_width,slider_cnt,width,height,(int)(0.5*height),opacity,font_family,slider_cnt,slider_cnt,v1,v2,slider_cnt,use_slider_display,use_slider_display,slider_cnt);
  2798. }
  2799.  
  2800.  
  2801. /*
  2802. add xyslider
  2803.  return value is array : value[0] is the actual x-value between value_1 and value_2, value[1] is y-value between value_1 and value_2
  2804. */
  2805. void add_xyslider(FILE *js_include_file, int canvas_root_id,double v1,double v2,int width,int height,int type,char *label,int slider_cnt,char *stroke_color,char *fill_color,int line_width,double opacity,char *font_family,char *font_color,int use_slider_display){
  2806. fprintf(js_include_file,"\n<!-- begin add_slider no. %d -->\n\
  2807. function add_slider_%d(){\
  2808. if( wims_status == \"done\" ){return;};\
  2809. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  2810. var slider_type = %d;\
  2811. var span = document.createElement(\"span\");\
  2812. span.style= \"font:%s;color:%s\";\
  2813. var title = document.createTextNode(\" %s \");\
  2814. var br = document.createElement(\"br\");\
  2815. span.appendChild(title);\
  2816. span.appendChild(br);\
  2817. tooltip_div.appendChild(span);\
  2818. var slider_fillcolor = \"%s\";\
  2819. var slider_click = 0;\
  2820. var slider_strokecolor = \"%s\";\
  2821. var slider_linewidth = \"%d\";\
  2822. var slider_canvas = document.createElement(\"canvas\");\
  2823. slider_canvas.id = \"slider_canvas%d\";\
  2824. tooltip_div.appendChild(slider_canvas);\
  2825. br = document.createElement(\"br\");\
  2826. tooltip_div.appendChild(br);\
  2827. var slider_width = %d;\
  2828. var slider_height = %d;\
  2829. var slider_center = %d;\
  2830. var slider_radius = 4*slider_linewidth;\
  2831. var slider_opacity = %f;\
  2832. slider_canvas.width = slider_width;\
  2833. slider_canvas.height = slider_height;\
  2834. var canvas_rect = (slider_canvas).getBoundingClientRect();\
  2835. var slider_ctx = slider_canvas.getContext(\"2d\");\
  2836. slider_ctx.font = \"%s\";\
  2837. slider_ctx.strokeStyle = \"rgba(\"+slider_strokecolor+\",\"+slider_opacity+\")\";\
  2838. slider_ctx.fillStyle = \"rgba(\"+slider_fillcolor+\",\"+slider_opacity+\")\";\
  2839. slider_ctx.lineWidth = slider_linewidth;\
  2840. slider_ctx.beginPath();\
  2841. slider_ctx.arc(10,slider_center,slider_radius,0,2*Math.PI,false);\
  2842. slider_ctx.fill();\
  2843. slider_ctx.closePath();\
  2844. slider_ctx.rect(0,0,slider_width,slider_height);\
  2845. slider_ctx.stroke();\
  2846. slider_canvas.addEventListener(\"mousemove\",sliderdrag_%d,false);\
  2847. slider_canvas.addEventListener(\"mousedown\",sliderclick_%d,false);\
  2848. function sliderdrag_%d(evt){\
  2849. if(slider_click == 1){\
  2850.  var value_1 = %f;\
  2851.  var value_2 = %f;\
  2852.  var canvas_rect = (slider_canvas).getBoundingClientRect();\
  2853.  slider_ctx.clearRect(0,0,slider_width,slider_height);\
  2854.  var x_px = evt.clientX - canvas_rect.left;\
  2855.  var y_px = evt.clientY - canvas_rect.top;\
  2856.  var x = x_px*(value_2 - value_1)/slider_width + value_1;\
  2857.  var y = y_px*(value_2 - value_1)/slider_height + value_1;\
  2858.  x = parseFloat(eval(slider_function%d.x));\
  2859.  y = parseFloat(eval(slider_function%d.y));\
  2860.  slider_ctx.beginPath();\
  2861.  slider_ctx.arc(x_px,y_px,slider_radius,0,2*Math.PI,false);\
  2862.  slider_ctx.fill();\
  2863.  slider_ctx.rect(0,0,slider_width,slider_height);\
  2864.  slider_ctx.closePath();\
  2865.  slider_ctx.stroke();\
  2866.  dragstuff.Slide( [x,y] , %d );\
  2867.  if(%d != 0 ){show_slider_value([x,y],%d);}\
  2868. };\
  2869. };\
  2870. function sliderclick_%d(evt){\
  2871.  if(slider_click == 1){slider_click = 0;}else{slider_click = 1;};\
  2872. };\
  2873. };\
  2874. add_slider_%d();",slider_cnt,slider_cnt,canvas_root_id,type,font_family,font_color,label,fill_color,stroke_color,line_width,canvas_root_id,width,height,(int)(0.5*height),opacity,font_family,slider_cnt,slider_cnt,slider_cnt,v1,v2,slider_cnt,slider_cnt,slider_cnt,use_slider_display,slider_cnt,slider_cnt,slider_cnt);
  2875. }
  2876.  
  2877.  
  2878. /*
  2879. adds inputfield for x-value: returns the js-calculated y-value after click on 'OK' button
  2880. draws a non-configurable crosshair on this calculated location
  2881. */
  2882. void add_calc_y(FILE *js_include_file,int canvas_root_id,char *jsmath,int font_size,char *input_style){
  2883. fprintf(js_include_file,"\n<!-- begin add_calc_y -->\n\
  2884. use_jsmath=1;\
  2885. function add_calc_y(){\
  2886. if( wims_status == \"done\" ){return;};\
  2887. var fun = to_js_math(\"%s\");if(fun == null){return;};\
  2888. function eval_jsmath(x){return parseFloat(eval(fun));};\
  2889. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  2890. var calc_div = document.createElement('div');\
  2891. calc_div.id = \"calc_div\";\
  2892. tooltip_div.appendChild(calc_div);\
  2893. var label_x = \"x\";var label_y = \"y\";\
  2894. if( typeof xaxislabel !== 'undefined' ){label_x = xaxislabel;}\
  2895. if( typeof yaxislabel !== 'undefined' ){label_y = yaxislabel;}\
  2896. calc_div.innerHTML=\"<br /><span style='font-style:italic;font-size:%dpx'>\"+label_x+\" : <input type='text' size='4' value='' id='calc_input_x' style='%s' />&nbsp;\"+ label_y+\" : <input type='text' size='5' value='' id='calc_output_y' style='%s' readonly /><input id='calc_button' type='button' value='OK' onclick=''  style='color:red;background-color:lightblue;' /></span> \";\
  2897. var calc_button = document.getElementById(\"calc_button\");\
  2898. calc_button.addEventListener(\"mousedown\",function(e){var x_value=document.getElementById(\"calc_input_x\").value;\
  2899. var y_value = eval_jsmath(x_value);\
  2900. document.getElementById(\"calc_output_y\").value = y_value;\
  2901. if(isNaN(y_value)){return;};\
  2902. var canvas = create_canvas%d(123,xsize,ysize);\
  2903. var ctx = canvas.getContext(\"2d\");\
  2904. draw_crosshairs(ctx,[x2px(x_value)],[y2px(y_value)],1,5,\"#000000\",1,0,0,0,[0,0]);return;},false);\
  2905. };add_calc_y();",jsmath,canvas_root_id,font_size,input_style,input_style,canvas_root_id);
  2906. }
  2907. /*
  2908.  x-value of the mouse will be used to calculate via javascript the corresponding y-value using the verbatim js-math function
  2909.  a configurable crosshair and vertical/horizontal crosshair lines will be drawn
  2910.  function is called "use_mouse_coordinates() and thus can not be combined with command 'mouse'
  2911. */
  2912. void add_trace_js_mouse(FILE *js_include_file,int canvas_cnt,int canvas_root_id,char *stroke_color,char *jsmath,int font_size,double stroke_opacity,int line_width,int crosshair_size,char *input_style){
  2913. fprintf(js_include_file,"\n<!-- begin command add_trace_jsmath  trace_canvas -->\n\
  2914. use_jsmath=1;\
  2915. function use_trace_jsmath(){\
  2916. if( wims_status == \"done\" ){return;};\
  2917. var label_x = \"x\";var label_y = \"y\";\
  2918. if( typeof xaxislabel !== 'undefined' ){label_x = xaxislabel;}\
  2919. if( typeof yaxislabel !== 'undefined' ){label_y = yaxislabel;}\
  2920. var trace_canvas = create_canvas%d(%d,xsize,ysize);\
  2921. var trace_context = trace_canvas.getContext(\"2d\");\
  2922. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  2923. var trace_div = document.createElement('div');\
  2924. trace_div.id = \"trace_div\";\
  2925. tooltip_div.appendChild(trace_div);\
  2926. trace_div.innerHTML = \"<br /><span style='font-style:italic;font-size:%dpx'>\"+label_x+\" : <input type='text' size='4' value='' id='trace_input_x' style='%s' />\"+label_y+\" : <input type='text' size='5' value='' id='trace_input_y' style='%s' readonly /></span> \";\
  2927. canvas_div.addEventListener(\"mousemove\",trace,false);\
  2928. canvas_div.addEventListener(\"touchmove\",trace,false);\
  2929. var fun = to_js_math(\"%s\");if(fun == null){return;};\
  2930. function eval_jsmath(x){return parseFloat(eval(fun));};\
  2931. function trace(evt){\
  2932.  var canvas_rect = (trace_canvas).getBoundingClientRect();\
  2933.  var x_px = evt.clientX - canvas_rect.left;\
  2934.  var x = px2x(x_px);\
  2935.  var y = eval_jsmath(x);\
  2936.  if(isNaN(y)){return;};\
  2937.  var y_px = y2px(y);\
  2938.  trace_context.clearRect(0,0,xsize,ysize);\
  2939.  draw_crosshairs(trace_context,[x_px],[y_px],%d,%d,\"%s\",%f,0,0,0,[0,0]);\
  2940.  document.getElementById(\"trace_input_x\").value = x;\
  2941.  document.getElementById(\"trace_input_y\").value = y;\
  2942. };\
  2943. return;\
  2944. };use_trace_jsmath();",canvas_root_id,canvas_cnt,canvas_root_id,font_size,input_style,input_style,jsmath,line_width,crosshair_size,stroke_color,stroke_opacity);
  2945. }
  2946.  
  2947. /*
  2948. add a table with 2 textarea's labeled 'x' 'y' ( or 'xlabel' 'ylabel' if defined)
  2949. add two buttons: OK and NOK (OK draws; NOK will delete last item pair from userdraw_x / userdraw_y array's
  2950. */
  2951. void add_textarea_xy(FILE *js_include_file, int canvas_root_id, char *input_style){
  2952. fprintf(js_include_file,"\n<!-- begin add_textarea_xy -->\n\
  2953. function add_textarea_xy(){\
  2954. if( wims_status == \"done\" ){return;};\
  2955. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  2956. var textarea_div = document.createElement('div');\
  2957. textarea_div.id = \"textarea_div\";\
  2958. tooltip_div.appendChild(textarea_div);\
  2959. var label_x = \"x\";var label_y = \"y\";\
  2960. if( typeof xaxislabel !== 'undefined' ){label_x = xaxislabel;}\
  2961. if( typeof yaxislabel !== 'undefined' ){label_y = yaxislabel;}\
  2962. textarea_div.innerHTML=\"\
  2963. <table style=\'border:1px solid black;background-color:#ffffa0\' >\
  2964. <tr>\
  2965. <td><input id='textarea_ok_button' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;'/></td>\
  2966. <td><input id='textarea_nok_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'/></td>\
  2967. </tr>\
  2968. <tr>\
  2969. <td><em>\"+label_x+\"</em></td>\
  2970. <td><em>\"+label_y+\"</em></td>\
  2971. </tr>\
  2972. <tr>\
  2973. <td><textarea rows='5' cols='2' id='userinput_x' style='%s' ></textarea></td>\
  2974. <td><textarea rows='5' cols='2' id='userinput_y' style='%s' ></textarea></td>\
  2975. </tr>\
  2976. </table>\";\
  2977. var textarea_ok_button = document.getElementById(\"textarea_ok_button\");\
  2978. var textarea_nok_button = document.getElementById(\"textarea_nok_button\");\
  2979. textarea_ok_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  2980. textarea_nok_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);\
  2981. return;\
  2982. };add_textarea_xy();",canvas_root_id,input_style,input_style);
  2983. }
  2984.  
  2985. /*
  2986.  
  2987. */
  2988. void add_setlimits(FILE *js_include_file, int canvas_root_id,int font_size,char *input_style){
  2989. fprintf(js_include_file,"\n<!-- begin add_setlimits -->\n\
  2990. use_pan_and_zoom = 1;\
  2991. function use_setlimits(){\
  2992. if( wims_status == \"done\" ){return;};\
  2993. var label_x = \"x\";var label_y = \"y\";\
  2994. if( typeof xaxislabel !== 'undefined' ){label_x = xaxislabel;}\
  2995. if( typeof yaxislabel !== 'undefined' ){label_y = yaxislabel;}\
  2996. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  2997. var setlim_div = document.createElement('div');\
  2998. setlim_div.id = \"setlim_div\";\
  2999. tooltip_div.appendChild(setlim_div);\
  3000. setlim_div.innerHTML=\"<br /><span style='font-style:italic;font-size:%dpx'>\"+label_x+\"min = <input type='text' size='4' value='\"+xmin+\"' id='userinput_xmin' style='%s' /> \"+label_x+\"max = <input type='text' size='4' value='\"+xmax+\"' id='userinput_xmax' style='%s' /><br />\"+label_y+\"min = <input type='text' size='4' value='\"+ymin+\"' id='userinput_ymin' style='%s' /> \"+label_y+\"max = <input type='text' size='4' value='\"+ymax+\"' id='userinput_ymax' style='%s' /><br /><input id='set_limits' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;' />\";\
  3001. var setlimit_button = document.getElementById(\"set_limits\");\
  3002. function set_limits(e){\
  3003. xmin = safe_eval(document.getElementById('userinput_xmin').value);\
  3004. xmax = safe_eval(document.getElementById('userinput_xmax').value);\
  3005. ymin = safe_eval(document.getElementById('userinput_ymin').value);\
  3006. ymax = safe_eval(document.getElementById('userinput_ymax').value);\
  3007. if(xmin > xmax || ymin > ymax){alert(\"your limits are not correct...\");return;}\
  3008. try{start_canvas%d(1234)}catch(e){};try{dragstuff.Zoom(xmin,xmax,ymin,ymax)}catch(e){};return;};\
  3009. setlimit_button.addEventListener(\"mousedown\",function(e){set_limits();},false);\
  3010. };use_setlimits();",canvas_root_id,font_size,input_style,input_style,input_style,input_style,canvas_root_id);
  3011. }
  3012.  
  3013.  
  3014. void add_rawmath(FILE *js_include_file){
  3015. fprintf(js_include_file,"\n<!-- begin add_rawmath() -->\n\
  3016. function rawmath(i){\
  3017. i=i.toLowerCase();\
  3018. i=i.replace(/\\ /g,\"\");i=i.replace(/\\*\\*/g,\"^\");\
  3019. if(i.indexOf(\"e+\")!=-1){i=i.replace(\"e+\",\"*10^\");};\
  3020. if(i.indexOf(\"e-\")!=-1){i=i.replace(\"e-\",\"*10^-\");};\
  3021. i=i.replace(/\\*\\*/g,\"*\");\
  3022. if(i.charAt(0)==\"*\"){i=i.substring(1,i.length);};\
  3023. var fun=[\"asin\",\"acos\",\"atan\",\"sin\",\"cos\",\"tan\",\"log\",\"ln\",\"pi\",\"e\",\"x\",\"y\"];\
  3024. var cons=[\"pi\",\"e\",\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"];\
  3025. var cntl = 0;var cntr = 0;\
  3026. var len = i.length;\
  3027. for( var p = 0;p < len; p++){\
  3028.  if(i.charAt(p) == '('){cntl++;}\
  3029.  if(i.charAt(p) == ')'){cntr++;}\
  3030. };\
  3031. if(cntl != cntr){alert(\"unmatched parenthesis !!\");return null;};\
  3032. for(var p = 0; p < 12 ; p++){\
  3033.  for(var d = 0; d < 12 ; d++){\
  3034.   while(i.indexOf(cons[d]+\"\"+fun[p])!=-1){\
  3035.    i = i.replace(cons[d]+\"\"+fun[p],cons[d]+\"*\"+fun[p]);\
  3036.   };\
  3037.   while(i.indexOf(fun[p]+\"\"+cons[d])!=-1){\
  3038.    i = i.replace(fun[p]+\"\"+cons[d],fun[p]+\"*\"+cons[d]);\
  3039.   };\
  3040.  };\
  3041. };\
  3042. if(i.indexOf(\"(\")!=-1){\
  3043.  for(var p = 0;p < 12; p++){\
  3044.   if(i.indexOf(cons[p]+\"(\")!=-1){\
  3045.    i = i.replace(cons[p]+\"(\",cons[p]+\"*(\");\
  3046.   };\
  3047.   if(i.indexOf(\")\"+cons[p])!=-1){\
  3048.    i = i.replace(\")\"+cons[p],\")*\"+cons[p]);\
  3049.   };\
  3050.  };\
  3051.  i = i.replace(/\\)\\(/g,\")*(\");\
  3052. };\
  3053. return i;\
  3054. }\n");
  3055. }
  3056. void add_input_jsfunction(FILE *js_include_file, int canvas_root_id,char *input_style,char *input_label,int input_cnt,char *stroke_color,float stroke_opacity,int line_width,int use_dashed,int dashtype0,int dashtype1,int font_size){
  3057. fprintf(js_include_file,"\n<!-- begin add_input_jsfunction -->\n\
  3058. function clear_jsfunction(canvas_plot_id,input_field){\
  3059. try{\
  3060.  var canvas_plot = document.getElementById(\"wims_canvas%d\"+canvas_plot_id);\
  3061.  var canvas_plot_ctx = canvas_plot.getContext(\"2d\");\
  3062.  if( confirm(\"clear function plot?\") ){\
  3063.   canvas_plot_ctx.clearRect(0,0,xsize,ysize);\
  3064.   document.getElementById(input_field).value = \"\";\
  3065.  };\
  3066.  return;\
  3067. }catch(e){alert(e+\"nothing to remove...\");};\
  3068. return;\
  3069. };\
  3070. function add_input_jsfunction(input_cnt,input_style,input_label,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1){\
  3071. var canvas_plot_id = %d+input_cnt;\
  3072. var input_field = \"canvas_input\"+input_cnt;\
  3073. var update_button_id = \"update_button\"+input_cnt;\
  3074. var delete_button_id = \"delete_button\"+input_cnt;\
  3075. if( wims_status == \"done\" ){return;};\
  3076. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  3077. var input_jsfunction_div = document.createElement('div');\
  3078. input_jsfunction_div.id = \"input_jsfunction_div\"+input_cnt;\
  3079. tooltip_div.appendChild(input_jsfunction_div);\
  3080. input_jsfunction_div.innerHTML=\"<br /><br /><span style='font-style:italic;font-size:%dpx;color:rgb(\"+stroke_color+\")'><b>\"+input_label+\" <input type='text' size='16' value='' id='\"+input_field+\"' style='\"+input_style+\"' /></b><input id='\"+update_button_id+\"' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;'/><input id='\"+delete_button_id+\"' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'/></span> \";\
  3081. var update_button = document.getElementById(update_button_id);\
  3082. var delete_button = document.getElementById(delete_button_id);\
  3083. update_button.addEventListener(\"mousedown\",function(e){jsplot(canvas_plot_id,rawmath(document.getElementById(input_field).value),line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);return;},false);\
  3084. delete_button.addEventListener(\"mousedown\",function(e){clear_jsfunction(canvas_plot_id,input_field);return;},false);\
  3085. };\
  3086. add_input_jsfunction(%d,\"%s\",\"%s\",%d,\"%s\",%.2f,%d,%d,%d);\n",canvas_root_id,USERDRAW_JSPLOT,canvas_root_id,font_size,input_cnt,input_style,input_label,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  3087. }
  3088.  
  3089.  
  3090. /*
  3091. adds 2 inputfields (x:y) and 'ok' | 'nok' button
  3092. these are used for user drawing with inputfields...
  3093. */
  3094.  
  3095. void add_input_xy(FILE *js_include_file, int canvas_root_id,int font_size,char *input_style){
  3096. fprintf(js_include_file,"\n<!-- begin add_input_xy -->\n\
  3097. function add_input_xy(){\
  3098. if( wims_status == \"done\" ){return;};\
  3099. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  3100. var input_xy_div = document.createElement('div');\
  3101. input_xy_div.id = \"input_xy_div\";\
  3102. tooltip_div.appendChild(input_xy_div);\
  3103. var label_x = \"x\";var label_y = \"y\";\
  3104. input_xy_div.innerHTML=\"<br /><span style='font-style:italic;font-size:%dpx'><b>( <input type='text' size='5' value='' id='userinput_x' style='%s' /> : <input type='text' size='5' value='' id='userinput_y' style='%s' /> )</b><input id='update_button' type='button' value='OK' onclick=''  style='color:red;background-color:lightblue;'/><input id='delete_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'/></span> \";\
  3105. var update_button = document.getElementById(\"update_button\");\
  3106. var delete_button = document.getElementById(\"delete_button\");\
  3107. update_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  3108. delete_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);\
  3109. };add_input_xy();",canvas_root_id,font_size,input_style,input_style);
  3110. }
  3111.  
  3112. /* adds 4 inputfields (x1:y1) --- (x2:y2) and 'ok' + 'nok' button */
  3113. void add_input_x1y1x2y2(FILE *js_include_file, int canvas_root_id,int font_size,char *input_style){
  3114. fprintf(js_include_file,"\n<!-- begin add_input_x1y1x2y2 -->\n\
  3115. function add_input_x1y1x2y2(){\
  3116. if( wims_status == \"done\" ){return;};\
  3117. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  3118. var input_x1y1x2y2_div = document.createElement('div');\
  3119. input_x1y1x2y2_div.id = \"input_x1y1x2y2_div\";\
  3120. tooltip_div.appendChild(input_x1y1x2y2_div);\
  3121. input_x1y1x2y2_div.innerHTML=\"<br /><span style='font-size:%dpx'><b>( <input type='text' size='5' value='' id='userinput_x1' style='%s' /> : <input type='text' size='5' value='' id='userinput_y1' style='%s' /> ) ----- ( <input type='text' size='5' value='' id='userinput_x2' style='%s' /> : <input type='text' size='5' value='' id='userinput_y2' style='%s'/> )</b><input id='update_button' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;'/><input id='delete_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;' /></span> \";\
  3122. var update_button = document.getElementById(\"update_button\");\
  3123. var delete_button = document.getElementById(\"delete_button\");\
  3124. update_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  3125. delete_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);\
  3126. };add_input_x1y1x2y2();",canvas_root_id,font_size,input_style,input_style,input_style,input_style);
  3127. }
  3128.  
  3129. /* adds 3 inputfields Center (x:y) Radius r and 'ok'+'nok' buttons */
  3130. void add_input_xyr(FILE *js_include_file, int canvas_root_id,int font_size,char *input_style){
  3131. fprintf(js_include_file,"\n<!-- begin add_input_xyr -->\n\
  3132. function add_input_xyr(){\
  3133. if( wims_status == \"done\" ){return;};\
  3134. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  3135. var input_xyr_div = document.createElement('div');\
  3136. input_xyr_div.id = \"input_xyr_div\";\
  3137. tooltip_div.appendChild(input_xyr_div);\
  3138. input_xyr_div.innerHTML=\"<br /><span style='font-style:italic;font-size:%dpx'><b>Center : ( <input type='text' size='5' value='' id='userinput_x' style='%s' /> : <input type='text' size='5' value='' id='userinput_y' style='%s' /> ) Radius : <input type='text' size='5' value='' id='userinput_r' style='%s' /></b><input id='update_button' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;'/><input id='delete_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'/></span> \";\
  3139. var update_button = document.getElementById(\"update_button\");\
  3140. var delete_button = document.getElementById(\"delete_button\");\
  3141. update_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  3142. delete_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);\
  3143. };add_input_xyr();",canvas_root_id,font_size,input_style,input_style,input_style);
  3144. }
  3145.  
  3146. /* THESE JS-FUNCTIONS COULD BE MADE LESS COPY & PASTE "PROGRAMMING" */
  3147.  
  3148. /* draw circle(s) / point(s) via 3 inputfields */
  3149. void add_input_circle(FILE *js_include_file,int type,int num){
  3150. /*
  3151. type = 0 : a point ...radius is fixed
  3152. type = 1 : a circle ... read inputfield userinput_r
  3153. num = 1 : a single point / circle
  3154. num = 2 : multiple points / circles
  3155. */
  3156. fprintf(js_include_file,"\n<!-- begin add_input_circle -->\n\
  3157. function user_redraw(t){\
  3158. var type = %d;\
  3159. var num = %d;\
  3160. var lu = userdraw_x.length;\
  3161. if( t == -1 && lu > 0){\
  3162.  userdraw_x.splice(lu-1,1);\
  3163.  userdraw_y.splice(lu-1,1);\
  3164.  if(type == 1){\
  3165.    userdraw_radius.splice(lu-1,1);\
  3166.  };\
  3167.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3168.  draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  3169.  return;\
  3170. };\
  3171. var add_x = safe_eval( document.getElementById(\"userinput_x\").value );\
  3172. var add_y = safe_eval( document.getElementById(\"userinput_y\").value );\
  3173. if( add_x != null && add_y != null ){\
  3174.  if( type == 2 ){\
  3175.   var add_r = safe_eval( document.getElementById(\"userinput_r\").value );if( add_r == null ){alert(\"illegal radius input \");return;}\
  3176.   if( num == 1 ){\
  3177.    userdraw_radius[0] = parseInt(Math.abs(xsize*(add_r)/(xmax - xmin)));\
  3178.   }\
  3179.   else\
  3180.   {\
  3181.    userdraw_radius[lu] = parseInt(Math.abs(xsize*(add_r)/(xmax - xmin)));\
  3182.   };\
  3183.  }\
  3184.  else\
  3185.  {\
  3186.    userdraw_radius[lu] = userdraw_radius[0];\
  3187.  };\
  3188.  if( num == 1 ){\
  3189.  userdraw_x[0] = x2px(add_x);\
  3190.  userdraw_y[0] = y2px(add_y);\
  3191.  }\
  3192.  else\
  3193.  {\
  3194.    userdraw_x[lu] = x2px(add_x);\
  3195.    userdraw_y[lu] = y2px(add_y);\
  3196.    xy_cnt++;\
  3197.  };\
  3198.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3199.  draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  3200. };\
  3201. return;\
  3202. };",type,num);
  3203. }
  3204. /* draw crosshairs via inputfields x/y */
  3205. void add_input_crosshair(FILE *js_include_file,int num){
  3206. fprintf(js_include_file,"\n<!-- begin add_input_crosshair -->\n\
  3207. function user_redraw(t){\
  3208. var lu = userdraw_x.length;\
  3209. if( t == -1 && lu > 0){\
  3210.  userdraw_x.splice(lu-1,1);\
  3211.  userdraw_y.splice(lu-1,1);\
  3212.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3213.  draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  3214.  return;\
  3215. };\
  3216. var add_x = safe_eval( document.getElementById(\"userinput_x\").value );\
  3217. var add_y = safe_eval( document.getElementById(\"userinput_y\").value );\
  3218. if( add_x != null && add_y != null ){\
  3219.  if( %d == 1 ){\
  3220.   userdraw_x[0] = x2px(add_x);\
  3221.   userdraw_y[0] = y2px(add_y);\
  3222.  }\
  3223.  else\
  3224.  {\
  3225.    userdraw_x[lu] = x2px(add_x);\
  3226.    userdraw_y[lu] = y2px(add_y);\
  3227.    xy_cnt++;\
  3228.  };\
  3229.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3230.  draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  3231. };\
  3232. return;\
  3233. };",num);
  3234. }
  3235.  
  3236. /* draw arrows via inputfields x/y */
  3237. void add_input_arrow(FILE *js_include_file,int num){
  3238. fprintf(js_include_file,"\n<!-- begin add_input_arrow -->\n\
  3239. function user_redraw(t){\
  3240. var lu = userdraw_x.length;\
  3241. if( t == -1 && lu > 1 ){\
  3242.  userdraw_x.splice(lu-2,2);\
  3243.  userdraw_y.splice(lu-2,2);\
  3244.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3245.  draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,0,[1,0,0,1,0,0]);\
  3246.  return;\
  3247. };\
  3248. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  3249. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  3250. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  3251. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  3252. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  3253.  if( %d == 2 ){\
  3254.    var s = userdraw_x.length;\
  3255.    userdraw_x[lu] = x2px(add_x1);\
  3256.    userdraw_y[lu] = y2px(add_y1);\
  3257.    userdraw_x[lu+1] = x2px(add_x2);\
  3258.    userdraw_y[lu+1] = y2px(add_y2);\
  3259.  }\
  3260.  else\
  3261.  {\
  3262.   userdraw_x[0] = x2px(add_x1);\
  3263.   userdraw_y[0] = y2px(add_y1);\
  3264.   userdraw_x[1] = x2px(add_x2);\
  3265.   userdraw_y[1] = y2px(add_y2);\
  3266.  };\
  3267.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3268.  draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,0,[1,0,0,1,0,0]);\
  3269. };\
  3270. return;\
  3271. };",num);
  3272. }
  3273.  
  3274. /* draw line via inputfields x/y */
  3275. void add_input_line(FILE *js_include_file,int num){
  3276. fprintf(js_include_file,"\n<!-- begin line via inputfields  -->\n\
  3277. function user_redraw(t){\
  3278. var lu = userdraw_x.length;\
  3279. if( t == -1 && lu > 1){\
  3280.  userdraw_x.splice(lu-2,2);\
  3281.  userdraw_y.splice(lu-2,2);\
  3282.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3283.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,1,0,0);\
  3284.  return;\
  3285. };\
  3286. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  3287. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  3288. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  3289. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  3290. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  3291.  if( %d == 2 ){\
  3292.    userdraw_x[lu] = x2px(add_x1);\
  3293.    userdraw_y[lu] = y2px(add_y1);\
  3294.    userdraw_x[lu+1] = x2px(add_x2);\
  3295.    userdraw_y[lu+1] = y2px(add_y2);\
  3296.  }\
  3297.  else\
  3298.  {\
  3299.   userdraw_x[0] = x2px(add_x1);\
  3300.   userdraw_y[0] = y2px(add_y1);\
  3301.   userdraw_x[1] = x2px(add_x2);\
  3302.   userdraw_y[1] = y2px(add_y2);\
  3303.  };\
  3304.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3305.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,1,0,0);\
  3306. };\
  3307. return;\
  3308. };",num);
  3309. }
  3310.  
  3311.  
  3312. /* draw polyline via inputfields x/y */
  3313. void add_input_polyline(FILE *js_include_file){
  3314. fprintf(js_include_file,"\n<!-- begin polyline_segment via inputfields -->\n\
  3315. function user_redraw(t){\
  3316. var lu = userdraw_x.length;\
  3317. cnt = 1;\
  3318. if( t == -1 && lu > 0){\
  3319.  userdraw_x.splice(lu-1,1);\
  3320.  userdraw_y.splice(lu-1,1);\
  3321.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3322.  draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  3323.  return;\
  3324. };\
  3325. var add_x = safe_eval( document.getElementById(\"userinput_x\").value );\
  3326. var add_y = safe_eval( document.getElementById(\"userinput_y\").value );\
  3327. if(add_x != null && add_y != null ){\
  3328.  userdraw_x.push(x2px(add_x));\
  3329.  userdraw_y.push(y2px(add_y));\
  3330.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3331.  draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  3332. };\
  3333. return;\
  3334. };");
  3335. }
  3336. /* draw segment(s) via inputfields x/y */
  3337. void add_input_segment(FILE *js_include_file,int num){
  3338. fprintf(js_include_file,"\n<!-- begin add_input_segment -->\n\
  3339. function user_redraw(t){\
  3340. var lu = userdraw_x.length;\
  3341. if( t == -1 && lu > 1){\
  3342.  userdraw_x.splice(lu-2,2);\
  3343.  userdraw_y.splice(lu-2,2);\
  3344.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3345.  draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  3346.  return;\
  3347. };\
  3348. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  3349. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  3350. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  3351. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  3352. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  3353.  if( %d == 2 ){\
  3354.    var s = userdraw_x.length;\
  3355.    userdraw_x[s] = x2px(add_x1);\
  3356.    userdraw_y[s] = y2px(add_y1);\
  3357.    userdraw_x[s+1] = x2px(add_x2);\
  3358.    userdraw_y[s+1] = y2px(add_y2);\
  3359.  }\
  3360.  else\
  3361.  {\
  3362.   userdraw_x[0] = x2px(add_x1);\
  3363.   userdraw_y[0] = y2px(add_y1);\
  3364.   userdraw_x[1] = x2px(add_x2);\
  3365.   userdraw_y[1] = y2px(add_y2);\
  3366.  };\
  3367.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3368.  draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  3369. };\
  3370. return;\
  3371. };",num);
  3372. }
  3373.  
  3374. /* draw demilines(s) via inputfields x/y */
  3375. void add_input_demiline(FILE *js_include_file,int num){
  3376. fprintf(js_include_file,"\n<!-- begin add_input_segment -->\n\
  3377. function user_redraw(t){\
  3378. var lu = userdraw_x.length;\
  3379. if( t == -1 && lu > 1){\
  3380.  userdraw_x.splice(lu-2,2);\
  3381.  userdraw_y.splice(lu-2,2);\
  3382.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3383.  draw_demilines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  3384.  return;\
  3385. };\
  3386. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  3387. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  3388. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  3389. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  3390. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  3391.  if( %d == 2 ){\
  3392.    var s = userdraw_x.length;\
  3393.    userdraw_x[s] = x2px(add_x1);\
  3394.    userdraw_y[s] = y2px(add_y1);\
  3395.    userdraw_x[s+1] = x2px(add_x2);\
  3396.    userdraw_y[s+1] = y2px(add_y2);\
  3397.  }\
  3398.  else\
  3399.  {\
  3400.   userdraw_x[0] = x2px(add_x1);\
  3401.   userdraw_y[0] = y2px(add_y1);\
  3402.   userdraw_x[1] = x2px(add_x2);\
  3403.   userdraw_y[1] = y2px(add_y2);\
  3404.  };\
  3405.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3406.  draw_demilines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  3407. };\
  3408. return;\
  3409. };",num);
  3410. }
  3411.  
  3412. /* draw polygon via 2 textarea's x/y : split into lines ! */
  3413. void add_textarea_polygon(FILE *js_include_file){
  3414. fprintf(js_include_file,"\n<!-- begin polygon via 2 textareas x / y -->\n\
  3415. function user_redraw(t){\
  3416. var lu = userdraw_x.length;\
  3417. if( t == -1 && lu > 0){\
  3418.  if( lu < 3 ){\
  3419.   userdraw_x = [];\
  3420.   userdraw_y = [];\
  3421.  }\
  3422.  else\
  3423.  {\
  3424.  userdraw_x.splice(lu-1,1);\
  3425.  userdraw_y.splice(lu-1,1);\
  3426.  };\
  3427.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3428.  draw_paths(context_userdraw,userdraw_x,userdraw_y,line_width,closed_path,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,use_rotate,angle,0,[1,0,0,1,0,0]);\
  3429.  cnt = 1; return;\
  3430. };\
  3431. var add_x_values = (document.getElementById(\"userinput_x\").value).split('\\n');\
  3432. var add_y_values = (document.getElementById(\"userinput_y\").value).split('\\n');\
  3433. var lx = add_x_values.length;\
  3434. var ly = add_y_values.length;\
  3435. if( lx != ly){ if(lx > ly){alert(\'x/y mismatch\\ntoo few y-values\');return}else{alert(\'x/y mismatch\\ntoo many y-values\');return}};\
  3436. var add_x;var add_y;\
  3437. for(var p = 0 ; p < lx ; p++){\
  3438.  add_x = safe_eval( add_x_values[p] );\
  3439.  add_y = safe_eval( add_y_values[p] );\
  3440.  if( add_x == null || add_y == null ){return;};\
  3441.  userdraw_x[lu+p] = x2px(add_x);\
  3442.  userdraw_y[lu+p] = y2px(add_y);\
  3443.  if(p>100){alert(\"hmmmm\");return;};\
  3444. };\
  3445. draw_paths(context_userdraw,userdraw_x,userdraw_y,line_width,closed_path,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,use_rotate,angle,0,[1,0,0,1,0,0]);\
  3446. cnt = 1;\
  3447. return;\
  3448. };");
  3449. }
  3450.  
  3451. void add_jsplot(FILE *js_include_file,int canvas_root_id){
  3452. fprintf(js_include_file,"\n<!-- begin jsplot() -->\n\
  3453. var jsplot = function(canvas_type,f,linewidth,color,opacity,use_dashed,dashtype0,dashtype1){\
  3454. var obj;\
  3455. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){\
  3456.  obj = document.getElementById(\"wims_canvas%d\"+canvas_type);\
  3457. }\
  3458. else\
  3459. {\
  3460.  obj = create_canvas%d(canvas_type,xsize,ysize);\
  3461. };\
  3462. var ctx = obj.getContext(\"2d\");\
  3463. ctx.clearRect(0,0,xsize,ysize);\
  3464. function eval_jsmath(x){return parseFloat(eval(fun));};\
  3465. var fun = to_js_math(f);if(fun == null){alert(\"Syntax Error...\\nAttention : try use very precise notation !\\nlike :\\n6*(0.25)^(1.23)\\n1/(sin(5*x))\\n(3*x+4)/(x^(2*pi)) \");return;};\
  3466. try{ parseFloat( eval_jsmath( px2x(0) ) );}catch(e){alert(\"\\nSyntax Error...\\nAttention : try use very precise notation !\\nlike :\\n6*(0.25)^(1.23)\\n1/(sin(5*x))\\n(3*x+4)/(x^(2*pi))\");return;};\
  3467. ctx.lineWidth = linewidth;\
  3468. ctx.strokeStyle=\"rgba(\"+color+\",\"+opacity+\")\";\
  3469. if(use_dashed == 1){if(ctx.setLineDash){ctx.setLineDash([dashtype0,dashtype1]);}else{ctx.mozDash =[dashtype0,dashtype1];}};\
  3470. var y1;var x1;var y2;var x2;\
  3471. ctx.beginPath();\
  3472. for(var p=0 ; p<xsize;p++){\
  3473.  x1 = px2x(p);\
  3474.  y1 = y2px(parseFloat(eval_jsmath(x1)));\
  3475.  x2 = px2x(p+1);\
  3476.  y2 = y2px(parseFloat(eval_jsmath(x2)));\
  3477.  if(Math.abs(y2-y1) < ysize ){\
  3478.    ctx.moveTo(p,y1);\
  3479.    ctx.lineTo(p+1,y2);\
  3480.  };\
  3481. };\
  3482. ctx.closePath();\
  3483. ctx.stroke();\
  3484. };",canvas_root_id,canvas_root_id,canvas_root_id);
  3485. }
  3486.  
  3487. void add_to_js_math(FILE *js_include_file){
  3488. fprintf(js_include_file,"\n<!-- begin to_js_math() -->\n\
  3489. var to_js_math = function(math_fun){\
  3490. if(math_fun == null){return;};\
  3491. var infun=[\"sqrt\",\"^\",\"asin\",\"acos\",\"atan\",\"log\",\"pi\",\"abs\",\"sin\",\"cos\",\"tan\",\"e\"];\
  3492. var outfun=[\"Math.sqrt\",\"Math.pow\",\"Math.asin\",\"Math.acos\",\"Math.atan\",\"Math.log\",\"(3.14159265358979)\",\"Math.abs\",\"Math.sin\",\"Math.cos\",\"Math.tan\",\"(2.718281828459045)\"];\
  3493. var len = infun.length;var in_fun;var In_Fun;var out_fun;var w_cnt;\
  3494. for(var p=0 ; p < len ; p++){\
  3495.  in_fun = infun[p];In_Fun = in_fun.toUpperCase();out_fun = outfun[p];w_cnt=0;\
  3496.  if(math_fun.indexOf(in_fun) != -1){\
  3497.   if(in_fun == \"^\"){\
  3498.    var tab = [];var small_trick = \"___small_trick___\";\
  3499.    while (math_fun.indexOf(\"(\") != -1){\
  3500.     math_fun = math_fun.replace(/(\\([^\\(\\)]*\\))/g, function(m, t){tab.push(t);return (small_trick + (tab.length - 1));});\
  3501.     w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  3502.    };\
  3503.    tab.push(math_fun);w_cnt = 0;math_fun = small_trick + (tab.length - 1);\
  3504.    while (math_fun.indexOf(small_trick) != -1){\
  3505.     math_fun = math_fun.replace(new RegExp(small_trick + \"(\\\\d+)\", \"g\"), function(m, d){return tab[d].replace(/(\\w*)\\^(\\w*)/g, out_fun+\"($1,$2)\");});\
  3506.     w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  3507.    };\
  3508.   }\
  3509.   else\
  3510.   {\
  3511.    while( math_fun.indexOf(in_fun) != -1 ){\
  3512.     math_fun = math_fun.replace(in_fun,out_fun);\
  3513.     math_fun = math_fun.replace(in_fun,In_Fun);\
  3514.     w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  3515.    };\
  3516.   };\
  3517.  };\
  3518. };\
  3519. for(var p=0 ; p < len ; p++){\
  3520.  in_fun = infun[p];In_Fun = in_fun.toUpperCase();w_cnt = 0;\
  3521.  if(math_fun.indexOf(In_Fun) != -1 ){\
  3522.   while(math_fun.indexOf(In_Fun) != -1){\
  3523.    math_fun = math_fun.replace(In_Fun,in_fun);\
  3524.    w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  3525.   };\
  3526.  };\
  3527. };\
  3528. return math_fun;\
  3529. };\n");
  3530. }
  3531.  
  3532. void add_clear_button(FILE *js_include_file,int canvas_root_id,char *input_style,char *button_text){
  3533. /* 25/11/2014 added clearing of reply array
  3534. all members will be set to 0 eg reply[0] = 0 , reply[1] = 0 ...
  3535. hope this does not interfere with existing work...
  3536. */
  3537. /*
  3538. 12/2016 changed  to 'setAttribute()' because of trouble on Chromium/Safari/IE
  3539. */
  3540. fprintf(js_include_file,"<!-- add clear button -->\n\
  3541. clear_draw_area%d = function(){\
  3542. if(confirm(\"remove all drawings ? \")){\
  3543.  var canvas_userdraw = create_canvas%d(%d,xsize,ysize);\
  3544.  var context_userdraw = canvas_userdraw.getContext(\"2d\");\
  3545.  context_userdraw.clearRect(0,0,xsize,ysize);\
  3546.  userdraw_x = [];userdraw_y = [];userdraw_radius = [];\
  3547.  for(var p = 0;p < reply.length; p++){\
  3548.   reply[p] = 0;\
  3549.  };\
  3550.  return;\
  3551. };\
  3552. };\
  3553. function add_clear_button(){\
  3554. var tooltip_placeholder_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  3555. var button = document.createElement('input');\
  3556. button.setAttribute(\"type\" , \"button\");\
  3557. button.setAttribute(\"style\" , \"%s\");\
  3558. button.setAttribute(\"value\" , \"%s\");\
  3559. button.setAttribute(\"onclick\",\"clear_draw_area%d()\");\
  3560. tooltip_placeholder_div.appendChild(button);\
  3561. };\
  3562. add_clear_button();\
  3563. ",canvas_root_id,canvas_root_id,DRAW_CANVAS,canvas_root_id,input_style,button_text,canvas_root_id);
  3564. }
  3565.  
  3566.  
  3567. /* GNU libmatheval library for evaluating mathematical functions. */
  3568. char *eval(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int plotsteps,int precision){
  3569.     void *f;
  3570.     double x;
  3571.     double y;
  3572.     int xv;
  3573.     int i = 0;
  3574.     int xstep =(int)(xsize/plotsteps);
  3575.     if( xstep == 0 ){xstep = 1;}
  3576.     double a = (xmax - xmin)/xsize;
  3577.     f = eval_create(fun);
  3578.     assert (f);
  3579.     if( f == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;}
  3580.     /* we supply the true x/y values...draw_curve() will convert these (x:y) to pixels : used for pan/scale */
  3581.     double xydata[MAX_BUFFER+1];/* hmmm */
  3582.     int lim_ymin =(int)( ymin - 4*fabs(ymin));/* 19-4-2015 replacing "abs" by "fabs"*/
  3583.     int lim_ymax =(int)( ymax + 4*fabs(ymax));/* 19-4-2015 replacing "abs" by "fabs"*/
  3584.     for ( xv = 0 ;xv < xsize ; xv = xv+xstep ){
  3585.         x = (double) (xv*a + xmin);
  3586.         if( i < MAX_BUFFER - 2){
  3587.             y = eval_x(f, x);
  3588.             if(y < lim_ymax && y > lim_ymin ){
  3589.                 xydata[i++] = x;
  3590.                 xydata[i++] = y;
  3591.             }
  3592.         }
  3593.         else
  3594.         {
  3595.             canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps or some other means to reduce the amount of data... ");
  3596.         }
  3597.     }
  3598.     eval_destroy(f);
  3599.     return double_xy2js_array(xydata,i,find_number_of_digits(precision));
  3600. }
  3601. /* plot a very primitive (!) levelcurve : not to be compared with "flydraw levelcurve" */
  3602. char *eval_levelcurve(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int plotsteps,int precision,double level){
  3603.     void *f = eval_create(fun);
  3604.     assert (f);
  3605.     if( f == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;}
  3606.     double a = (double)((xmax - xmin)/plotsteps);
  3607.     double b = (double)((ymax - ymin)/plotsteps);
  3608.     double x;double y;double diff;
  3609.     double xydata[MAX_BUFFER+1];
  3610.     int i = 0;
  3611.     ymin = ymin - 1;
  3612.     xmin = xmin - 1;
  3613.     ymax = ymax + 1;
  3614.     xmax = xmax + 1;
  3615.     for( x = xmin ;x < xmax ; x = x + a ){
  3616.         for ( y = ymin ;y < ymax ; y = y + b ){
  3617.             if( i < MAX_BUFFER - 2){
  3618.                 diff = level - eval_x_y(f, x,y);
  3619.                 if(diff < 0.1 && diff > -0.1){
  3620.                     xydata[i++] = x;
  3621.                     xydata[i++] = y;
  3622.                 }
  3623.             }
  3624.             else
  3625.             {
  3626.                 canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps, decrease image size...\nor some other means to reduce the amount of data... ");
  3627.             }
  3628.         }
  3629.     }
  3630.     eval_destroy(f);
  3631.     return double_xy2js_array(xydata,i,find_number_of_digits(precision));
  3632. }
  3633.  
  3634. /* plot parametric function */
  3635. char *eval_parametric(int xsize,int ysize,char *fun1,char* fun2,double xmin,double xmax,double ymin,double ymax,
  3636.  double tmin,double tmax,int plotsteps,int precision){
  3637.     void *fx;
  3638.     void *fy;
  3639.     double t;
  3640.     int i = 0;
  3641.     double tstep = (tmax-tmin)/plotsteps;
  3642.     if( tstep == 0 ){canvas_error("zero step for t variable : reduce plotsteps or inrease trange");}
  3643.     fx = eval_create(fun1);
  3644.     fy = eval_create(fun2);
  3645.     assert(fx);
  3646.     assert(fy);
  3647.     if( fx == NULL || fy == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;}
  3648.     /* we supply the true x/y values...draw_curve() will convert these (x:y) to pixels : used for pan/scale */
  3649.     double xydata[MAX_BUFFER+1];/* hmmm */
  3650.     double x; /* real x-values */
  3651.     double y; /* real y-values */
  3652.     int lim_ymin =(int)( ymin - 4*fabs(ymin));/* 19-4-2015 replacing "abs" by "fabs"*/
  3653.     int lim_ymax =(int)( ymax + 4*fabs(ymax));/* 19-4-2015 replacing "abs" by "fabs"*/
  3654.     for( t = tmin ;t <= tmax ; t = t + tstep ){
  3655.         if( i < MAX_BUFFER - 2 ){
  3656.             y = eval_t(fy, t);
  3657.             if(y > lim_ymin && y < lim_ymax){
  3658.                 x = eval_t(fx, t);
  3659.                 xydata[i++] = x;
  3660.                 xydata[i++] = y;
  3661.             }
  3662.         }
  3663.         else
  3664.         {
  3665.             canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps or some other means to reduce the amount of data... ");
  3666.         }
  3667.     }
  3668.     eval_destroy(fx);
  3669.     eval_destroy(fy);
  3670.     return double_xy2js_array(xydata,i,find_number_of_digits(precision));
  3671. }
  3672.  
  3673. char *double_xy2js_array(double xy[],int len,int decimals){
  3674.  /*
  3675.     1,2,3,4,5,6,7,8 --> [1,3,5,7],[2,4,6,8]
  3676.     int xy[] is already checked for errors or overflow in "get_real()"
  3677.     just to be sure we double check the size of "temp"
  3678. */
  3679.     char temp[2*MAX_BUFFER], *string;
  3680.     char *tmp = my_newmem(16);/* <= 9999999999999999  */
  3681.     memset(temp,'\0',2*MAX_BUFFER);/* clear memory */
  3682.     int i;int space_left;
  3683.     temp[0] = '[';/* start js-array */
  3684.     for(i = 0; i < len;i = i + 2){ /*  x_points[] */
  3685.         if(i == len - 2){sprintf(tmp, "%.*f",decimals, xy[i]);}else{sprintf(tmp, "%.*f,",decimals,xy[i]);}
  3686.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  3687.         if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce your image size or plotsteps ");}
  3688.     }
  3689.     strncat(temp,"],[",3); /* close js x_values array and start new */
  3690.     for(i = 1; i < len;i = i + 2){ /* y_points */
  3691.         if(i == len - 1){ sprintf(tmp, "%.*f",decimals,xy[i]);}else{sprintf(tmp, "%.*f,",decimals,xy[i]);}
  3692.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  3693.         if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce your image size or plotsteps");}
  3694.     }
  3695.     strncat(temp,"]",1);
  3696.     string=(char *)my_newmem(sizeof(temp));
  3697.     snprintf(string,sizeof(temp),"%s",temp);
  3698.     return string;
  3699. }
  3700.  
  3701. char *xy2js_array(int xy[],int len){
  3702.  /*
  3703.     1,2,3,4,5,6,7,8 --> [1,3,5,7],[2,4,6,8]
  3704.     int xy[] is already checked for errors or overflow in "get_real()"
  3705.     just to be sure we double check the size of "temp"
  3706. */
  3707.     char temp[MAX_BUFFER], *string;
  3708.     char *tmp = my_newmem(16);/* <= 9999999999999999  */
  3709.     memset(temp,'\0',MAX_BUFFER);/* clear memory */
  3710.     int i;int space_left;
  3711.     temp[0] = '[';/* start js-array */
  3712.     for(i = 0; i < len;i = i + 2){ /*  x_points[] */
  3713.         if(i == len - 2){sprintf(tmp, "%d", xy[i]);}else{sprintf(tmp, "%d,", xy[i]);}
  3714.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  3715.         if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce image size or plotsteps ");}
  3716.     }
  3717.     strncat(temp,"],[",3); /* close js x_values array and start new */
  3718.     for(i = 1; i < len;i = i + 2){ /* y_points */
  3719.         if(i == len - 1){ sprintf(tmp, "%d", xy[i]);}else{sprintf(tmp, "%d,", xy[i]);}
  3720.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  3721.         if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data\nreduce image size or plotsteps \n");}
  3722.     }
  3723.     strncat(temp,"]",1);
  3724.     string=(char *)my_newmem(sizeof(temp));
  3725.     snprintf(string,sizeof(temp),"%s",temp);
  3726.     return string;
  3727. }
  3728.  
  3729. char *data2js_array(int data[],int len){
  3730.  /*
  3731.     1,2,3,4,5,6,7,8 --> [1,2,3,4,5,6,7,8]
  3732.     int data[] is already checked for errors or overflow in "get_real()"
  3733.     just to be sure we double check the size of "temp"
  3734. */
  3735.     char temp[MAX_BUFFER], *string;
  3736.     char *tmp = my_newmem(16);/* <= 9999999999999999  */
  3737.     memset(temp,'\0',MAX_BUFFER);/* clear memory */
  3738.     int i;int space_left;
  3739.     temp[0] = '[';/* start js-array */
  3740.     for(i = 0; i < len; i++){
  3741.         if(i == len - 1){sprintf(tmp, "%d", data[i]);}else{sprintf(tmp, "%d,", data[i]);}
  3742.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  3743.         if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce image size or plotsteps ");}
  3744.     }
  3745.     strncat(temp,"]",1);
  3746.     string=(char *)my_newmem(sizeof(temp));
  3747.     snprintf(string,sizeof(temp),"%s",temp);
  3748.     return string;
  3749. }
  3750.  
  3751.  
  3752. void *my_newmem(size_t size){
  3753.         void    *p;
  3754.         if ((p = malloc(size +1)) == NULL){canvas_error("canvasdraw: ran out of memory\n");}
  3755.         return p;
  3756. }
  3757.  
  3758. int find_number_of_digits(int i){
  3759.     if(i < 0 ){ i = -1*i;}
  3760.     int digits = 0;
  3761.     while ( i > 0){
  3762.         digits++;
  3763.         i = i/10;
  3764.     }
  3765.     return digits;
  3766. }
  3767.  
  3768. struct colors colors[]={
  3769.  {"#FF0000","red","255,0,0"},
  3770.  {"#00FF00","lime","0,255,0"},
  3771.  {"#0000FF","blue","0,0,255"},
  3772.  {"#FFA500","orange","255,165,0"},
  3773.  {"#E9967A","darksalmon","233,150,122"},
  3774.  {"#F0FFFF","azure","240,255,255"},
  3775.  {"#CD5C5C","indianred","205,92,92"},
  3776.  {"#E0FFFF","lightcyan","224,255,255"},
  3777.  {"#FFE4E1","mistyrose","255,228,225"},
  3778.  {"#DC143C","crimson","220,20,60"},
  3779.  {"#FFC0CB","pink","255,192,203"},
  3780.  {"#FFD700","gold","255,215,0"},
  3781.  {"#E6E6FA","lavender","230,230,250"},
  3782.  {"#808080","gray","128,128,128"},
  3783.  {"#F0F8FF","aliceblue","240,248,255"},
  3784.  {"#C71585","mediumvioletred","199,21,133"},
  3785.  {"#FFF0F5","lavenderblush","255,240,245"},
  3786.  {"#DAA520","goldenrod","218,165,32"},
  3787.  {"#FFB6C1","lightpink","255,182,193"},
  3788.  {"#00FFFF","aqua","0,255,255"},
  3789.  {"#FF69B4","hotpink","255,105,180"},
  3790.  {"#00FFFF","cyan","0,255,255"},
  3791.  {"#FF1493","deeppink","255,20,147"},
  3792.  {"#7FFFD4","aquamarine","127,255,212"},
  3793.  {"#FA8072","salmon","250,128,114"},
  3794.  {"#DEB887","burlywood","222,184,135"},
  3795.  {"#DB7093","palevioletred","219,112,147"},
  3796.  {"#D2B48C","tan","210,180,140"},
  3797.  {"#BDB76B","darkkhaki","189,183,107"},
  3798.  {"#B22222","firebrick","178,34,34"},
  3799.  {"#FF4500","orangered","255,69,0"},
  3800.  {"#8B4513","saddlebrown","139,69,19"},
  3801.  {"#FF8C00","darkorange","255,140,0"},
  3802.  {"#FFFFE0","lightyellow","255,255,224"},
  3803.  {"#FFFF00","yellow","255,255,0"},
  3804.  {"#FFFACD","lemonchiffon","255,250,205"},
  3805.  {"#F5F5DC","beige","245,245,220"},
  3806.  {"#FFEFD5","papayawhip","255,239,213"},
  3807.  {"#FAFAD2","lightgoldenrodyellow","250,250,210"},
  3808.  {"#FFE4B5","moccasin","255,228,181"},
  3809.  {"#B8860B","darkgoldenrod","184,134,11"},
  3810.  {"#FFF8DC","cornsilk","255,248,220"},
  3811.  {"#FFEBCD","blanchedalmond","255,235,205"},
  3812.  {"#FFE4C4","bisque","255,228,196"},
  3813.  {"#FFDEAD","navajowhite","255,222,173"},
  3814.  {"#F5DEB3","wheat","245,222,179"},
  3815.  {"#CD853F","peru","205,133,63"},
  3816.  {"#D2691E","chocolate","210,105,30"},
  3817.  {"#A0522D","sienna","160,82,45"},
  3818.  {"#A52A2A","brown","165,42,42"},
  3819.  {"#BC8F8F","rosybrown","188,143,143"},
  3820.  {"#F08080","lightcoral","240,128,128"},
  3821.  {"#FFA07A","lightsalmon","255,160,122"},
  3822.  {"#8B0000","darkred","139,0,0"},
  3823.  {"#800000","maroon","128,0,0"},
  3824.  {"#FAA460","sandybrown","250,164,96"},
  3825.  {"#FF7F50","coral","255,127,80"},
  3826.  {"#FF6347","tomato","255,99,71"},
  3827.  {"#FFDAB9","peachpuff","255,218,185"},
  3828.  {"#EEE8AA","palegoldenrod","238,232,170"},
  3829.  {"#F0E68C","khaki","240,230,140"},
  3830.  {"#D8BFD8","thistle","216,191,216"},
  3831.  {"#DDA0DD","plum","221,160,221"},
  3832.  {"#FF00FF","fuchsia","255,0,255"},
  3833.  {"#FF00FF","magenta","255,0,255"},
  3834.  {"#EE82EE","violet","238,130,238"},
  3835.  {"#DA70D6","orchid","218,112,214"},
  3836.  {"#BA55D3","mediumorchid","186,85,211"},
  3837.  {"#9370DB","mediumpurple","147,112,219"},
  3838.  {"#8A2BE2","blueviolet","138,43,226"},
  3839.  {"#9400D3","darkviolet","148,0,211"},
  3840.  {"#9932CC","darkorchid","153,50,204"},
  3841.  {"#8B008B","darkmagenta","139,0,139"},
  3842.  {"#800080","purple","128,0,128"},
  3843.  {"#4B0082","indigo","75,0,130"},
  3844.  {"#483D8B","darkslateblue","72,61,139"},
  3845.  {"#6A5ACD","slateblue","106,90,205"},
  3846.  {"#7B68EE","mediumslateblue","123,104,238"},
  3847.  {"#98FB98","palegreen","152,251,152"},
  3848.  {"#ADFF2F","greenyellow","173,255,47"},
  3849.  {"#7FFF00","chartreuse","127,255,0"},
  3850.  {"#7CFC00","lawngreen","124,252,0"},
  3851.  {"#00FF7F","springgreen","0,255,127"},
  3852.  {"#00FA9A","mediumspringgreen","0,250,154"},
  3853.  {"#90EE90","lightgreen","144,238,144"},
  3854.  {"#32CD32","limegreen","50,205,50"},
  3855.  {"#3CB371","mediumseagreen","60,179,113"},
  3856.  {"#2E8B57","seagreen","46,139,87"},
  3857.  {"#228B22","forestgreen","34,139,34"},
  3858.  {"#008000","green","0,128,0"},
  3859.  {"#006400","darkgreen","0,100,0"},
  3860.  {"#9ACD32","yellowgreen","154,205,50"},
  3861.  {"#6B8E23","olivedrab","107,142,35"},
  3862.  {"#808000","olive","128,128,0"},
  3863.  {"#556B2F","darkolivegreen","85,107,47"},
  3864.  {"#8FBC8F","darkseagreen","143,188,143"},
  3865.  {"#66CDAA","mediumaquamarine","102,205,170"},
  3866.  {"#20B2AA","lightseagreen","32,178,170"},
  3867.  {"#008B8B","darkcyan","0,139,139"},
  3868.  {"#008080","teal","0,128,128"},
  3869.  {"#AFEEEE","paleturquoise","175,238,238"},
  3870.  {"#40E0D0","turquoise","64,224,208"},
  3871.  {"#48D1CC","mediumturquoise","72,209,204"},
  3872.  {"#00CED1","darkturquoise","0,206,209"},
  3873.  {"#5F9EA0","cadetblue","95,158,160"},
  3874.  {"#4682B4","steelblue","70,130,180"},
  3875.  {"#B0C4DE","lightsteelblue","176,196,222"},
  3876.  {"#B0E0E6","powderblue","176,224,230"},
  3877.  {"#ADD8E6","lightblue","173,216,230"},
  3878.  {"#87CEEB","skyblue","135,206,235"},
  3879.  {"#87CEFA","lightskyblue","135,206,250"},
  3880.  {"#00BFFF","deepskyblue","0,191,255"},
  3881.  {"#1E90FF","dodgerblue","30,144,255"},
  3882.  {"#6495ED","cornflowerblue","100,149,237"},
  3883.  {"#4169E1","royalblue","65,105,225"},
  3884.  {"#0000CD","mediumblue","0,0,205"},
  3885.  {"#00008B","darkblue","0,0,139"},
  3886.  {"#000080","navy","0,0,128"},
  3887.  {"#191970","midnightblue","25,25,112"},
  3888.  {"#DCDCDC","gainsboro","220,220,220"},
  3889.  {"#D3D3D3","lightgrey","211,211,211"},
  3890.  {"#808080","grey","128,128,128"},
  3891.  {"#C0C0C0","silver","192,192,192"},
  3892.  {"#A9A9A9","darkgray","169,169,169"},
  3893.  {"#778899","lightslategray","119,136,153"},
  3894.  {"#708090","slategray","112,128,144"},
  3895.  {"#696969","dimgray","105,105,105"},
  3896.  {"#2F4F4F","darkslategray","47,79,79"},
  3897.  {"#000000","black","0,0,0"},
  3898.  {"#F5FFFA","mintcream","245,255,250"},
  3899.  {"#FFFFFF","white","255,255,255"},
  3900.  {"#F0FFF0","honeydew","240,255,240"},
  3901.  {"#F5F5F5","whitesmoke","245,245,245"},
  3902.  {"#F8F8FF","ghostwhite","248,248,255"},
  3903.  {"#FFFFF0","ivory","255,255,240"},
  3904.  {"#FFFAFA","snow","255,250,250"},
  3905.  {"#FFFAF0","floralwhite","255,250,240"},
  3906.  {"#FFF5EE","seashell","255,245,238"},
  3907.  {"#FDF5E6","oldlace","253,245,230"},
  3908.  {"#FAF0E6","linen","250,240,230"},
  3909.  {"#FAEBD7","antiquewhite","250,235,215"},
  3910.  };
  3911. int NUMBER_OF_COLORNAMES=(sizeof(colors)/sizeof(colors[0]));
  3912.  
  3913. void add_drag_code(FILE *js_include_file,int canvas_cnt,int canvas_root_id ){
  3914. /* in drag& drop / onclick library:
  3915.     obj_type = 1 == rect / rects
  3916.     obj_type = 2 == point / points (do not scale with zoom)
  3917.     obj_type = 3 == ellipse
  3918.     obj_type = 4 == polyline / segment / segments /line / vline / hline
  3919.     obj_type = 5 == closed path (polygon)
  3920.     obj_type = 6 == roundrect /roundrects
  3921.     obj_type = 7 == crosshair / crosshairs
  3922.     obj_type = 8 == arrow / arrows
  3923.     obj_type = 9 == curve
  3924.     obj_type = 10== arrow2 / arrows2
  3925.     obj_type = 11== parallel  (no drag or onclick)
  3926.     obj_type = 12== arc : radius is in pixels , so no zooming in/out
  3927.     obj_type = 13== circle / circles (will scale on zoom)
  3928.     obj_type = 14== text (will not scale or pan on zoom)
  3929.     obj_type = 15== animated point on curve
  3930.     obj_type = 16== pixels
  3931.     obj_type = 17== new arc [command angle] :radius in x-range, so will scale on zooming in/out
  3932.     obj_type = 18== halfline
  3933.     obj_type = 19== yerrorbars
  3934.     obj_type = 20== xerrorbars
  3935.    
  3936.    
  3937.     arc
  3938. x[0] = x[1] = xc = double_data[0]                                                              
  3939. y[0] = y[1] = yc = double_data[1]                                                              
  3940. w[0] = width = int_data[0]                                                                      
  3941. w[1] = height = int_data[1]                                                                    
  3942. h[0] = start_angle = double_data[2]                                                            
  3943. h[1] = end_angle = double_data[3]  
  3944.       myState.selection.line_width = org_line_width;myState.selection.font_family = org_font_family;break;\
  3945.  
  3946. */
  3947. fprintf(js_include_file,"\n<!-- begin drag_drop_onclick shape library -->\n\
  3948. if( typeof dragdrop_precision == 'undefined' ){var dragdrop_precision = 100;};\
  3949. function Shape(click_cnt,onclick,direction,type,x,y,w,h,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1,use_rotate,angle,text,font_size,font_family,use_affine,affine_matrix,slider,slider_cnt,rotation_center){\
  3950. this.slider = slider || 0;\
  3951. this.slider_cnt = slider_cnt || 0;\
  3952. this.text = text || 0;\
  3953. this.font_size = font_size || 12;\
  3954. if( font_family.indexOf('px') > 0 ){this.font_family = font_family;}else{this.font_family = this.font_size+'px Ariel';};\
  3955. this.use_rotate = use_rotate || 0;\
  3956. this.angle = angle*(Math.PI/180) || 0;\
  3957. this.use_affine = use_affine || 0;\
  3958. this.affine_matrix = affine_matrix || [1,0,0,1,0,0];\
  3959. this.click_cnt = click_cnt || 0;\
  3960. this.onclick = onclick || 0;\
  3961. if(this.onclick == 1 ){reply[click_cnt] = 0;};\
  3962. this.direction = direction || 0;\
  3963. this.type = type || 1;\
  3964. this.xorg = x;\
  3965. this.yorg = y;\
  3966. this.x = [x.length];\
  3967. this.y = [x.length];\
  3968. this.w = [x.length];\
  3969. this.h = [x.length];\
  3970. for(var p=0;p<x.length;p++){\
  3971.  this.x[p] = x2px(x[p]-xstart);\
  3972.  this.y[p] = y2px(y[p]-ystart);\
  3973.  if( p > w.length){\
  3974.    this.w[p] = w[0];\
  3975.    this.h[p] = h[0];\
  3976.  }\
  3977.  else\
  3978.  {\
  3979.    this.w[p] = w[p];\
  3980.    this.h[p] = h[p];\
  3981.  }\
  3982. };\
  3983. if( rotation_center != null ){\
  3984.  this.rotation_center = [x2px(rotation_center[0]),y2px(rotation_center[1])];\
  3985. }else{this.rotation_center = [this.x[0],this.y[0]];};\
  3986. this.line_width = line_width || 30;\
  3987. this.org_line_width = line_width || 30;\
  3988. this.stroke_opacity = stroke_opacity || 1.0;\
  3989. this.stroke_color = \"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\" || '#FF0000';\
  3990. this.fill_opacity = fill_opacity || 1.0;\
  3991. this.fill_color = \"rgba(\"+fill_color+\",\"+fill_opacity+\")\" || '#FF0000';\
  3992. this.use_filled = use_filled || 0;\
  3993. this.use_dashed = use_dashed || 0;\
  3994. this.dashtype0 = dashtype0 || 4;\
  3995. this.dashtype1 = dashtype1 || 4;\
  3996. };\
  3997. Shape.prototype.draw = function(ctx)\
  3998. {\
  3999. ctx.lineWidth = this.line_width;\
  4000. ctx.strokeStyle = this.stroke_color;\
  4001. ctx.fillStyle = this.fill_color;\
  4002. ctx.lineJoin = \"round\";\
  4003. ctx.save();\
  4004. if(this.use_rotate == 1){\
  4005.   ctx.translate(this.rotation_center[0],this.rotation_center[1]);\
  4006.   ctx.rotate(this.angle);\
  4007.   ctx.translate(-1*(this.rotation_center[0]),-1*(this.rotation_center[1]));\
  4008. };\
  4009. if( this.use_affine == 1 ){\
  4010.  ctx.setTransform(this.affine_matrix[0],this.affine_matrix[1],this.affine_matrix[2],this.affine_matrix[3],this.affine_matrix[4],this.affine_matrix[5]);\
  4011. };\
  4012. ctx.beginPath();\
  4013.  if(this.line_width%%2 == 1){ctx.translate(0.5,0.5);};\
  4014.  switch(this.type){\
  4015.  case 1: for(var p = 0 ; p < this.x.length;p = p+4){ctx.rect(this.x[p], this.y[p], this.x[p+1]-this.x[p], this.y[p+2] - this.y[p]);};break;\
  4016.  case 2: ctx.arc(this.x[0],this.y[0],0.5*this.w[0],0,2*Math.PI,false);break;\
  4017.  case 3: ctx.save();var w = 0.5*(scale_x_radius(this.w[0]));var h = 0.5*(scale_y_radius(this.h[0]));ctx.scale(1,h/w);ctx.beginPath();ctx.arc(this.x[0], w/h*this.y[0], w, 0, 2 * Math.PI);if(this.use_filled == 1){ ctx.fillStyle = this.fill_color; ctx.fill(); };ctx.closePath();ctx.stroke();ctx.restore();break;\
  4018.  case 4: for(var p = 0; p < this.x.length - 1;p++){ctx.moveTo(this.x[p], this.y[p]);ctx.lineTo(this.x[p+1],this.y[p+1]);};break;\
  4019.  case 5: ctx.moveTo(this.x[0],this.y[0]);for(var p = 1; p < this.x.length;p++){ctx.lineTo(this.x[p],this.y[p]);};ctx.lineTo(this.x[0],this.y[0]);break;\
  4020.  case 6: var w = this.x[1] - this.x[0];var h = this.y[1] - this.y[0];var r = this.w[0];ctx.beginPath();ctx.moveTo(this.x[0] + r, this.y[0]);ctx.lineTo(this.x[0] + w - r, this.y[0]);ctx.quadraticCurveTo(this.x[0] + w, this.y[0], this.x[0] + w, this.y[0] + r);ctx.lineTo(this.x[0] + w, this.y[0] + h - r);ctx.quadraticCurveTo(this.x[0] + w, this.y[0] + h, this.x[0] + w - r, this.y[0] + h);ctx.lineTo(this.x[0] + r, this.y[0] + h);ctx.quadraticCurveTo(this.x[0], this.y[0] + h, this.x[0], this.y[0] + h - r);ctx.lineTo(this.x[0], this.y[0] + r);ctx.quadraticCurveTo(this.x[0], this.y[0], this.x[0] + r, this.y[0]);ctx.closePath();break;\
  4021.  case 7: ctx.moveTo(this.x[0]-this.w[0],this.y[0]-this.h[0]);ctx.lineTo(this.x[0]+this.w[0],this.y[0]+this.h[0]);ctx.moveTo(this.x[0]-this.w[0],this.y[0]+this.h[0]);ctx.lineTo(this.x[0]+this.w[0],this.y[0]-this.h[0]);break;\
  4022.  case 8: var dx;var dy;var len;var arrow_head = this.w[0];for(var p = 0; p < this.x.length - 1;p++){ctx.save();if(this.use_dashed == 1 ){if( ctx.setLineDash ){ ctx.setLineDash([this.dashtype0,this.dashtype1]);}else{ ctx.mozDash = [this.dashtype0,this.dashtype1];};};dx = this.x[p+1] - this.x[p];dy = this.y[p+1] - this.y[p];len = Math.sqrt(dx*dx+dy*dy);ctx.translate(this.x[p+1],this.y[p+1]);ctx.rotate(Math.atan2(dy,dx));ctx.lineCap = \"round\";ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(-len,0);ctx.closePath();ctx.stroke();ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(-1*arrow_head,-0.5*arrow_head);ctx.lineTo(-1*arrow_head, 0.5*arrow_head);ctx.closePath();ctx.fill();ctx.restore();};break;\
  4023.  case 9: ctx.moveTo(this.x[0], this.y[0]);for(var p = 1; p < this.x.length - 1;p++){if( Math.abs(this.y[p] - this.y[p-1]) < ysize && Math.abs(this.y[p+1] - this.y[p]) < ysize ){ctx.lineTo(this.x[p],this.y[p]);}else{ctx.moveTo(this.x[p],this.y[p]);};};break;\
  4024.  case 10: var dx;var dy;var len;ctx.save();if(this.use_dashed == 1 ){if( ctx.setLineDash ){ ctx.setLineDash([this.dashtype0,this.dashtype1]);}else{ ctx.mozDash = [this.dashtype0,this.dashtype1];};};dx = this.x[1] - this.x[0];dy = this.y[1] - this.y[0];len = Math.sqrt(dx*dx+dy*dy);ctx.translate(this.x[1],this.y[1]);ctx.rotate(Math.atan2(dy,dx));ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(-len,0);ctx.closePath();ctx.stroke();ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(-1*this.w[0],0.5*this.w[0]);ctx.lineTo(-1*this.w[0],-0.5*this.w[0]);ctx.closePath();ctx.lineCap = \"round\";ctx.fill();ctx.restore();ctx.save();ctx.translate(this.x[0],this.y[0]);ctx.rotate(Math.atan2(dy,dx));ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(this.w[0],0.4*this.w[0]);ctx.lineTo(this.w[0],-0.4*this.w[0]);ctx.closePath();ctx.lineCap = \"round\";ctx.fill(); break;\
  4025.  case 11: var x1 = this.x[0];var y1 = this.y[0];var x2 = this.x[1];var y2 = this.y[1];var dx = this.x[2];var dy = this.y[2];var n  = this.w[0];for(var p = 0 ; p < n ; p++ ){ctx.beginPath();ctx.moveTo(x1,y1);ctx.lineTo(x2,y2);ctx.stroke();x1 = x1 + dx;y1 = y1 + dy;x2 = x2 + dx;y2 = y2 + dy;ctx.closePath();};break;\
  4026.  case 12: ctx.save();var start;var end;if(this.h[0] < this.h[1]){start = this.h[0];end = this.h[1]}else{start = this.h[1];end = this.h[0];};start=360-start;end=360-end;var w = 0.5*(scale_x_radius(this.w[0]));var h = 0.5*(scale_y_radius(this.w[1]));ctx.scale(1,h/w);ctx.arc(this.x[0], w/h*this.y[0], w,start*(Math.PI / 180), end*(Math.PI / 180),true);ctx.stroke();if(this.use_filled == 1){ ctx.fillStyle = this.fill_color; ctx.lineTo(this.x[0],this.y[0]);ctx.fill(); };ctx.restore();break;\
  4027.  case 13: for(var p = 0; p < this.x.length; p++){ ctx.arc(this.x[p],this.y[p],scale_x_radius(this.w[p]),0,2*Math.PI,false);};break;\
  4028.  case 14: ctx.font = this.font_family ;ctx.fillText(this.text,this.x[0],this.y[0]);break;\
  4029.  case 15: break;\
  4030.  case 16: for(var p = 0; p < this.x.length;p++){ctx.fillRect( this.x[p], this.y[p],this.line_width,this.line_width );};break;\
  4031.  case 17: ctx.save();var start;var end;if(this.h[0] < this.h[1]){start = this.h[0];end = this.h[1]}else{start = this.h[1];end = this.h[0];};start=360-start;end=360-end;var r = scale_x_radius(this.w[0]);ctx.arc(this.x[0], this.y[0], r, start*(Math.PI / 180), end*(Math.PI / 180),true);if(this.use_filled){ctx.lineTo(this.x[0],this.y[0]);ctx.fill();};ctx.restore();break;\
  4032.  case 18: for(var p=0 ; p < this.x.length ;p=p+2){ctx.moveTo(this.x[p], this.y[p]);ctx.lineTo(this.x[p+1],this.y[p+1]);};break;\
  4033.  case 19: ctx.arc(this.x[0],this.y[0],this.line_width,0,2*Math.PI,false);var E1 = y2px(px2y(this.y[0]) - this.h[0]);var E2 = y2px(px2y(this.y[0]) + this.w[0]);ctx.moveTo(this.x[0],E1);ctx.lineTo(this.x[0],E2);ctx.moveTo(this.x[0] - 2*(this.line_width),E1);ctx.lineTo(this.x[0] + 2*(this.line_width),E1);ctx.moveTo(this.x[0] - 2*(this.line_width),E2);ctx.lineTo(this.x[0] + 2*(this.line_width),E2);break;\
  4034.  case 20: ctx.arc(this.x[0],this.y[0],this.line_width,0,2*Math.PI,false);var E1 = x2px(px2x(this.x[0]) - this.w[0]);var E2 = x2px(px2x(this.x[0]) + this.h[0]);ctx.moveTo(E1,this.y[0]);ctx.lineTo(E2,this.y[0]);ctx.moveTo(E1,this.y[0]-2*(this.line_width));ctx.lineTo(E1,this.y[0]+2*(this.line_width));ctx.moveTo(E2,this.y[0]-2*(this.line_width));ctx.lineTo(E2,this.y[0]+2*(this.line_width));break;\
  4035.  default: alert(\"draw primitive unknown\");break;\
  4036. };\
  4037. if(this.use_filled == 1){ ctx.fill();}\
  4038. if(this.use_dashed == 1 ){if( ctx.setLineDash ){ ctx.setLineDash([this.dashtype0,this.dashtype1]);}else{ ctx.mozDash = [this.dashtype0,this.dashtype1];};};\
  4039. ctx.stroke();\
  4040. ctx.restore();\
  4041. };\
  4042. Shape.prototype.contains = function(mx, my){\
  4043. var marge = 2*this.line_width;\
  4044. switch(this.type){\
  4045.  case 1: for(var p = 0 ; p < this.x.length; p++ ){if( mx < this.x[p] + marge &&  mx > this.x[p] - marge ){if( my < this.y[p]+marge && my > this.y[p] - marge ){return p;};};};break;\
  4046.  case 2: for(var p = 0 ; p < this.x.length; p++ ){if( Math.abs(distance(this.x[p],this.y[p],mx,my) ) < this.w[p] + 4*marge ){return p;break;};};break;\
  4047.  case 3: for(var p = 0 ; p < this.x.length; p++ ){if( Math.abs(distance(this.x[p],this.y[p],mx,my) ) < scale_x_radius(this.w[p]) + marge ){return p;break;};};break;\
  4048.  case 4: var diff;var q;var r;for(var p = 0 ; p < this.x.length-1; p = p+2  ){if( ((this.x[p+1] - this.x[p]) != 0)  && ((this.y[p+1]-this.y[p]) != 0) ){r = (this.y[p+1]-this.y[p])/(this.x[p+1]-this.x[p]);q = this.y[p] - (r)*(this.x[p]);diff = distance_to_line(r,q,mx,my);}else{if( (this.y[p+1]-this.y[p]) != 0 ){diff = Math.abs(this.x[p] - mx);}else{diff = Math.abs(this.y[p] - my);};};if( diff  < marge ){ return p;};}; break;\
  4049.  case 5: marge = 2*marge;for(var p = 0 ; p < this.x.length; p++ ){if( mx < this.x[p] + marge &&  mx > this.x[p] - marge ){if( my < this.y[p]+marge && my > this.y[p] - marge ){return p;};};};break;\
  4050.  case 6: marge = 0.5*this.w[0];for(var p = 0 ; p < this.x.length; p++ ){if( mx < this.x[p] + marge &&  mx > this.x[p] - marge ){if( my < this.y[p]+marge && my > this.y[p] - marge ){return p;};};};break;\
  4051.  case 7: for(var p = 0 ; p < this.x.length; p++ ){if( (this.x[p] - this.w[p] <= mx) && (this.x[p] + this.w[p] >= mx) &&  (this.y[p] - this.h[p] <= my) && (this.y[p] + this.h[p] >= my) ){return p;};};break;\
  4052.  case 8: var diff;var q;var r;for(var p = 0 ; p < this.x.length-1; p = p+2  ){if( ((this.x[p+1] - this.x[p]) != 0)  && ((this.y[p+1]-this.y[p]) != 0) ){r = (this.y[p+1]-this.y[p])/(this.x[p+1]-this.x[p]);q = this.y[p] - (r)*(this.x[p]);diff = distance_to_line(r,q,mx,my);}else{if( (this.y[p+1]-this.y[p]) != 0 ){diff = Math.abs(this.x[p] - mx);}else{diff = Math.abs(this.y[p] - my);};};if( diff  < marge ){ return p;};}; break;\
  4053.  case 9: for(var p = 0 ; p < this.x.length; p++ ){if( (this.x[p] - this.line_width <= mx) && (this.x[p] + this.w[p] + this.line_width >= mx) &&  (this.y[p] - this.line_width <= my) && (this.y[p] + this.h[p] +this.line_width  >= my) ){return p;};};break;\
  4054.  case 10: var diff;var q;var r;for(var p = 0 ; p < this.x.length-1; p = p+2  ){if( ((this.x[p+1] - this.x[p]) != 0)  && ((this.y[p+1]-this.y[p]) != 0) ){r = (this.y[p+1]-this.y[p])/(this.x[p+1]-this.x[p]);q = this.y[p] - (r)*(this.x[p]);diff = distance_to_line(r,q,mx,my);}else{if( (this.y[p+1]-this.y[p]) != 0 ){diff = Math.abs(this.x[p] - mx);}else{diff = Math.abs(this.y[p] - my);};};if( diff  < marge ){ return p;};}; break;\
  4055.  case 11: break;\
  4056.  case 12: break;\
  4057.  case 13: for(var p = 0 ; p < this.x.length; p++ ){if( Math.abs(distance(this.x[p],this.y[p],mx,my) ) < scale_x_radius(this.w[p]) + marge ){return p;break;};};break;\
  4058.  case 14: for(var p = 0 ; p < this.x.length; p++ ){if(this.y[p] < my + 0.5*(this.font_size) && this.y[p] > my - 0.5*(this.font_size)){var w = parseInt(0.8*(this.font_size)*((this.text).length));if(this.x[p] < mx + w && this.x[p] > mx - w ){ return p;break;};};};break;\
  4059.  case 15: break;\
  4060.  case 16: break;\
  4061.  case 17: break;\
  4062.  case 18: var diff;var q;var r;if(((this.x[1] - this.x[0]) != 0) && ((this.y[1]-this.y[0]) != 0)){r = (this.y[1]-this.y[0])/(this.x[1]-this.x[0]);q = this.y[0] - (r)*(this.x[0]);diff = distance_to_line(r,q,mx,my);}else{if((this.y[1]-this.y[0])!= 0){diff = Math.abs(this.x[0] - mx);}else{diff = Math.abs(this.y[0] - my);};};if( diff  < marge ){ return 0;};break;\
  4063.  default: for(var p = 0 ; p < this.x.length; p++ ){if( (this.x[p] - this.line_width <= mx) && (this.x[p] + this.w[p] + this.line_width >= mx) &&  (this.y[p] - this.line_width <= my) && (this.y[p] + this.h[p] +this.line_width  >= my) ){return p;};};break;\
  4064. };\
  4065. return -1;\
  4066. };\
  4067. var reply = [];\
  4068. function CanvasState(canvas,container_div){\
  4069. this.canvas = canvas;\
  4070. this.width = canvas.width;\
  4071. this.height = canvas.height;\
  4072. var ctx = canvas.getContext(\"2d\");\
  4073. this.ctx = ctx;\
  4074. this.valid = false;\
  4075. this.shapes = [];\
  4076. this.moved = [];\
  4077. this.dragging = false;\
  4078. this.selection = null;\
  4079. var myState = this;\
  4080. container_div.addEventListener( 'mouseup'    , mouseup,false);\
  4081. container_div.addEventListener( 'mousemove'  , mousemove,false);\
  4082. container_div.addEventListener( 'mousedown'  , mousedown,false);\
  4083. container_div.addEventListener( 'touchend'   , mouseup,false);\
  4084. container_div.addEventListener( 'selectstart', function(e) { e.preventDefault(); return false; }, false);\
  4085. container_div.addEventListener( 'touchstart' , mousedown,false);\
  4086. container_div.addEventListener( 'touchmove'  , mousemove,false);\
  4087. function mousedown(e){\
  4088.  var mouse = myState.getMouse(e);\
  4089.  var mx = mouse.x;\
  4090.  var my = mouse.y;\
  4091.  if( use_pan_and_zoom == 1 && my > ysize - 15){\
  4092.   check_zoom_or_pan(mx);\
  4093.  }\
  4094.  else\
  4095.  {\
  4096.   if( wims_status == \"done\"){return null;};\
  4097.   var shapes = myState.shapes;\
  4098.   var l = shapes.length;\
  4099.   var chk = -1;\
  4100.   for(var i=0;i<l;i++){\
  4101.    chk = shapes[i].contains(mx, my);\
  4102.    if ( chk != -1 ){\
  4103.     if( myState.moved[shapes[i].click_cnt] != 1){\
  4104.      myState.moved[shapes[i].click_cnt] = 1;\
  4105.      myState.x_start = shapes[i].x[chk];\
  4106.      myState.y_start = shapes[i].y[chk];\
  4107.     };\
  4108.     myState.chk = chk;\
  4109.     myState.selection = shapes[i];\
  4110.     myState.valid = false;\
  4111.     switch(shapes[i].onclick){\
  4112.      case 0: myState.dragging = false;break;\
  4113.      case 1: \
  4114.       if( reply[myState.selection.click_cnt] == 0 ){\
  4115.        myState.selection.line_width = 3*(myState.selection.org_line_width);\
  4116.        reply[myState.selection.click_cnt] = 1;\
  4117.       }else{ reply[myState.selection.click_cnt] = 0;myState.selection.line_width = myState.selection.org_line_width;};\
  4118.       myState.dragging = false;myState.draw();\
  4119.       break;\
  4120.      case 2: myState.dragging = true;break;\
  4121.      default:break;\
  4122.     };\
  4123.     return;\
  4124.    };\
  4125.   };\
  4126.  };\
  4127.  myState.selection = null;\
  4128.  myState.valid = true;\
  4129.  return;\
  4130. };\
  4131. function mouseup(e){;\
  4132.  if(myState.selection != null ){\
  4133.   if(myState.selection.onclick == 2 ){\
  4134.    if( x_use_snap_to_grid == 1 || y_use_snap_to_grid == 1 || use_snap_to_points != 0){\
  4135.     var mouse = myState.getMouse(e);\
  4136.     var dx=mouse.x;\
  4137.     var dy=mouse.y;\
  4138.     if( use_snap_to_points != 0){\
  4139.      var xy = new Array(2);\
  4140.      if(use_snap_to_points == 1 ){\
  4141.       xy = snap_to_points(dx,dy);\
  4142.      }\
  4143.      else\
  4144.      {\
  4145.       xy = snap_to_fun(dx,dy);\
  4146.      };\
  4147.      dx = xy[0] - myState.selection.x[myState.chk];\
  4148.      dy = xy[1] - myState.selection.y[myState.chk];\
  4149.     }\
  4150.     else\
  4151.     {\
  4152.      if( x_use_snap_to_grid == 1 && y_use_snap_to_grid == 1 ){ \
  4153.       dx = snap_to_x(dx) - myState.selection.x[myState.chk];\
  4154.       dy = snap_to_y(dy) - myState.selection.y[myState.chk];\
  4155.      }else{\
  4156.       if( x_use_snap_to_grid == 1 ){ \
  4157.        dx = snap_to_x(dx) - myState.selection.x[myState.chk];\
  4158.        dy = 0;\
  4159.       }\
  4160.       else\
  4161.       {\
  4162.        dx = 0;\
  4163.        dy = snap_to_y(dy) - myState.selection.y[myState.chk];\
  4164.       };\
  4165.      };\
  4166.     };\
  4167.     switch(myState.selection.direction){\
  4168.      case 0: myState.selection = move(myState.selection,dx,dy);break;\
  4169.      case 1: myState.selection = move(myState.selection,dx,0);break;\
  4170.      case 2: myState.selection = move(myState.selection,0,dy); break;\
  4171.     };\
  4172.    };\
  4173.    reply[myState.selection.click_cnt] = myState.selection.click_cnt+\":\"+px2x(myState.x_start)+\":\"+px2y(myState.y_start)+\":\"+(Math.round(dragdrop_precision*(px2x(myState.selection.x[myState.chk]))))/dragdrop_precision+\":\"+(Math.round(dragdrop_precision*(px2y(myState.selection.y[myState.chk]))))/dragdrop_precision;\
  4174.    myState.valid = false;\
  4175.    myState.draw();\
  4176.    myState.valid = true;\
  4177.   };\
  4178.  };\
  4179.  myState.dragging = false;\
  4180. };\
  4181. function mousemove(e){\
  4182.  if(myState.dragging){\
  4183.   var mouse = myState.getMouse(e);\
  4184.   var dx=mouse.x - myState.selection.x[myState.chk];\
  4185.   var dy=mouse.y - myState.selection.y[myState.chk];\
  4186.   switch(myState.selection.direction){\
  4187.    case 0: myState.selection = move(myState.selection,dx,dy);break;\
  4188.    case 1: myState.selection = move(myState.selection,dx,0);break;\
  4189.    case 2: myState.selection = move(myState.selection,0,dy); break;\
  4190.    default:break;\
  4191.   };\
  4192.   myState.valid = false;\
  4193.  };\
  4194. };\
  4195. function check_zoom_or_pan(x){\
  4196.  var key = -1;\
  4197.  for(var p = 15 ; p < 106 ; p = p+15){\
  4198.    key++;\
  4199.    if(x > xsize - p){start_canvas%d(key);return;}\
  4200.  }\
  4201.  return;\
  4202. };\
  4203. this.interval = 30;\
  4204. setInterval(function() { myState.draw(); }, myState.interval);\
  4205. };\
  4206. CanvasState.prototype.addShape = function(shape){\
  4207. this.shapes.push(shape);\
  4208. this.valid = false;\
  4209. };\
  4210. CanvasState.prototype.clear = function(){\
  4211. this.ctx.clearRect(0, 0, this.width, this.height);\
  4212. };\
  4213. CanvasState.prototype.draw = function(){\
  4214. if(this.valid == false ){\
  4215.  var shapes = this.shapes;\
  4216.  this.clear();\
  4217.  var l = shapes.length;var shape;\
  4218.  for(var i = 0; i < l; i++){\
  4219.   shape = shapes[i];\
  4220.   shape.draw(this.ctx);\
  4221.  };\
  4222.  this.valid = true;\
  4223. }\
  4224. };\
  4225. CanvasState.prototype.Slide = function(slider_value,slider_count){\
  4226. this.ctx.clearRect(0,0,xsize,ysize);\
  4227. var what;var len = this.shapes.length;var shape;var lu;\
  4228. for(var i = 0; i < len ; i++){\
  4229.  if( this.shapes[i] ){\
  4230.   shape = this.shapes[i];\
  4231.   if( shape.slider != 0 ){\
  4232.    if(shape.slider_cnt == slider_count ){\
  4233.     what = shape.slider;\
  4234.     lu = shape.x.length;\
  4235.     reply[shape.click_cnt] = shape.click_cnt+\":\"+slider_value;\
  4236.     switch(what){\
  4237.      case 3: if(shape.type == 12 || shape.type == 17){\
  4238.       shape.h[1] = 180*slider_value[0]/Math.PI;}\
  4239.       else\
  4240.       {shape.use_rotate = 1;shape.angle = -1*slider_value[1];};break;\
  4241.      default:slide(shape,slider_value[0],slider_value[1]);break;\
  4242.     };\
  4243.    };\
  4244.   };\
  4245.   this.valid = false;\
  4246.   shape.draw(this.ctx);\
  4247.  };\
  4248. };\
  4249. };\
  4250. CanvasState.prototype.Zoom = function(xmin,xmax,ymin,ymax){\
  4251. (this.ctx).clearRect(0,0,this.width,this.height);\
  4252. var len = this.shapes.length;var shape;\
  4253. for(var i = 0; i < len ; i++){\
  4254.  shape = this.shapes[i];\
  4255.  for(var p = 0 ; p < shape.x.length;p++){\
  4256.   shape.x[p] = x2px(shape.xorg[p]);\
  4257.   shape.y[p] = y2px(shape.yorg[p]);\
  4258.  }\
  4259.  this.valid = false;\
  4260.  shape.draw(this.ctx);\
  4261. };\
  4262. };\
  4263. CanvasState.prototype.getMouse = function(e){\
  4264. var element = this.canvas, offsetX = 0,offsetY = 0;\
  4265. while( ( element = element.offsetParent) ){\
  4266. offsetX += element.offsetLeft;\
  4267. offsetY += element.offsetTop;\
  4268. }\
  4269. var mx = e.clientX - offsetX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);\
  4270. var my = e.clientY - offsetY + (document.documentElement.scrollTop ? document.documentElement.scrollTop :document.body.scrollTop);\
  4271. return {x: mx, y: my};\
  4272. };\
  4273. CanvasState.prototype.read_dragdrop = function(){\
  4274. if( wims_status == \"done\" || use_dragdrop_reply == -1 ){return null;};\
  4275. var moved_objects = new Array();\
  4276. var c = 0;\
  4277. for(var p = 0 ; p < reply.length ; p++){\
  4278.  if( reply[p] != null ){\
  4279.   moved_objects[c] = reply[p];\
  4280.   c++;\
  4281.  };\
  4282. }\
  4283. return moved_objects;\
  4284. };\
  4285. var obj = create_canvas%d(%d,xsize,ysize);\
  4286. var container_div = document.getElementById(\"canvas_div%d\");\
  4287. var dragstuff = new CanvasState(obj,container_div);\
  4288. read_dragdrop%d = dragstuff.read_dragdrop;\n",canvas_root_id,canvas_root_id,DRAG_CANVAS,canvas_root_id,canvas_root_id);
  4289. }
  4290.  
  4291. /*
  4292. #define BG_CANVAS 0 may be used for floodfill
  4293. #define STATIC_CANVAS 1 may be used for floodfill
  4294. #define MOUSE_CANVAS 2 xx
  4295. #define GRID_CANVAS 3 may be used for floodfill
  4296. #define DRAG_CANVAS 4 default for floodfill
  4297. #define DRAW_CANVAS 5 may be used for floodfill
  4298.  
  4299. */
  4300.  
  4301.  
  4302. void add_js_floodfill(FILE *js_include_file,int canvas_root_id){
  4303. fprintf(js_include_file,"\n<!-- begin command floodfill -->\n\
  4304. var floodfill = function(interaction,xs,ys,color){\
  4305. var canvas = document.getElementById(\"wims_canvas%d%d\");\
  4306. if( ! canvas ){ return; };\
  4307. var ctx = canvas.getContext(\"2d\");\
  4308. ctx.save();\
  4309. if(interaction == 1 ){\
  4310.  if( ys > ysize - 15){return;}\
  4311. }\
  4312. else\
  4313. {\
  4314.  xs = x2px(xs);\
  4315.  ys = y2px(ys);\
  4316. };\
  4317. var image = ctx.getImageData(0, 0, xsize, ysize);\
  4318. var imageData = image.data;\
  4319. var pixelStack = [[xs, ys]];\
  4320. var px1;\
  4321. var newPos;\
  4322. var pixelPos;\
  4323. var found_left_border;\
  4324. var found_right_border;\
  4325. function _getPixel(pixelPos){\
  4326.  return {r:imageData[pixelPos], g:imageData[pixelPos+1], b:imageData[pixelPos+2], a:imageData[pixelPos+3]};\
  4327. };\
  4328. function _setPixel(pixelPos){\
  4329.  imageData[pixelPos] = color.r;\
  4330.  imageData[pixelPos+1] = color.g;\
  4331.  imageData[pixelPos+2] = color.b;\
  4332.  imageData[pixelPos+3] = color.a;\
  4333. };\
  4334. function _comparePixel(px2){\
  4335.  return (px1.r === px2.r && px1.g === px2.g && px1.b === px2.b && px1.a === px2.a);\
  4336. };\
  4337. px1 = _getPixel(((ys * xsize) + xs) * 4);\
  4338. color = {\
  4339.  r: parseInt(color[0], 10),\
  4340.  g: parseInt(color[1], 10),\
  4341.  b: parseInt(color[2], 10),\
  4342.  a: parseInt(color[3] || 255, 10)\
  4343. };\
  4344. if( _comparePixel(color) ) { return true; }\
  4345. while (pixelStack.length) {\
  4346.  newPos = pixelStack.pop();\
  4347.  xs = newPos[0];ys = newPos[1];\
  4348.  pixelPos = (ys*xsize + xs) * 4;\
  4349.  while(ys-- >= 0 && _comparePixel(_getPixel(pixelPos))){\
  4350.   pixelPos -= xsize * 4;\
  4351.  }\
  4352.  pixelPos += xsize * 4;\
  4353.  ++ys;\
  4354.  found_left_border = false;\
  4355.  found_right_border = false;\
  4356.  while( ys++ < ysize-1 && _comparePixel(_getPixel(pixelPos)) ){\
  4357.   _setPixel(pixelPos);\
  4358.   if( xs > 0 ){\
  4359.    if( _comparePixel(_getPixel(pixelPos - 4)) ){\
  4360.    if( !found_left_border ){\
  4361.     pixelStack.push( [xs - 1, ys] );\
  4362.     found_left_border = true;\
  4363.    }\
  4364.   }\
  4365.   else if( found_left_border ){\
  4366.     found_left_border = false;\
  4367.    }\
  4368.   }\
  4369.   if( xs < xsize-1 ){\
  4370.    if( _comparePixel(_getPixel(pixelPos + 4)) ){\
  4371.     if( !found_right_border){\
  4372.      pixelStack.push( [xs + 1, ys] );\
  4373.      found_right_border = true;\
  4374.     }\
  4375.    }\
  4376.    else if(found_right_border){\
  4377.      found_right_border = false;\
  4378.     }\
  4379.    }\
  4380.   pixelPos += xsize * 4;\
  4381.  }\
  4382. };\
  4383. ctx.putImageData(image, 0, 0);\
  4384. ctx.restore();\
  4385. };",canvas_root_id,DRAG_CANVAS);
  4386.  
  4387. }
  4388.  
  4389. void add_js_filltoborder(FILE *js_include_file,int canvas_root_id){
  4390. fprintf(js_include_file,"\n<!-- begin command filltoborder -->\n\
  4391. var filltoborder = function(xs,ys,bordercolor,color){\
  4392. var canvas = document.getElementById(\"wims_canvas%d%d\");\
  4393. if( ! canvas ){ return; };\
  4394. var ctx = canvas.getContext(\"2d\");\
  4395. ctx.save();\
  4396. xs = x2px(xs);\
  4397. ys = y2px(ys);\
  4398. var image = ctx.getImageData(0, 0, xsize, ysize);\
  4399. var imageData = image.data;\
  4400. var pixelStack = [[xs, ys]];\
  4401. var px1;\
  4402. var newPos;\
  4403. var pixelPos;\
  4404. var found_left_border;\
  4405. var found_right_border;\
  4406. function _getPixel(pixelPos){\
  4407.  return {r:imageData[pixelPos], g:imageData[pixelPos+1], b:imageData[pixelPos+2], a:imageData[pixelPos+3]};\
  4408. };\
  4409. function _setPixel(pixelPos){\
  4410.  imageData[pixelPos] = color.r;\
  4411.  imageData[pixelPos+1] = color.g;\
  4412.  imageData[pixelPos+2] = color.b;\
  4413.  imageData[pixelPos+3] = color.a;\
  4414. };\
  4415. function _comparePixel(px2){\
  4416.  return (px2.r === px1.r && px2.g === px1.g && px2.b === px1.b );\
  4417. };\
  4418. function _compareBorder(px2){\
  4419.  return (bordercolor.r !== px2.r && bordercolor.g !== px2.g && bordercolor.b !== px2.b );\
  4420. };\
  4421. px1 = _getPixel(((ys * xsize) + xs) * 4);\
  4422. color = {\
  4423.  r: parseInt(color[0], 10),\
  4424.  g: parseInt(color[1], 10),\
  4425.  b: parseInt(color[2], 10),\
  4426.  a: parseInt(color[3] || 255, 10)\
  4427. };\
  4428. bordercolor = {\
  4429.  r: parseInt(bordercolor[0], 10),\
  4430.  g: parseInt(bordercolor[1], 10),\
  4431.  b: parseInt(bordercolor[2], 10),\
  4432.  a: parseInt(bordercolor[3] || 255, 10)\
  4433. };\
  4434. if( _comparePixel(color) ) { return true; }\
  4435. while (pixelStack.length) {\
  4436.  newPos = pixelStack.pop();\
  4437.  xs = newPos[0];ys = newPos[1];\
  4438.  pixelPos = (ys*xsize + xs) * 4;\
  4439.  while(ys-- >= 0 && _comparePixel(_getPixel(pixelPos))){\
  4440.   pixelPos -= xsize * 4;\
  4441.  }\
  4442.  pixelPos += xsize * 4;\
  4443.  ++ys;\
  4444.  found_left_border = false;\
  4445.  found_right_border = false;\
  4446.  while( ys++ < ysize-1 && ( _comparePixel(_getPixel(pixelPos))  || _compareBorder(_getPixel(pixelPos))) ){\
  4447.   _setPixel(pixelPos);\
  4448.   if( xs > 0 ){\
  4449.    if( _comparePixel(_getPixel(pixelPos - 4)) ){\
  4450.    if( !found_left_border ){\
  4451.     pixelStack.push( [xs - 1, ys] );\
  4452.     found_left_border = true;\
  4453.    }\
  4454.   }\
  4455.   else if( found_left_border ){\
  4456.     found_left_border = false;\
  4457.    }\
  4458.   }\
  4459.   if( xs < xsize-1 ){\
  4460.    if( _comparePixel(_getPixel(pixelPos + 4)) ){\
  4461.     if( !found_right_border){\
  4462.      pixelStack.push( [xs + 1, ys] );\
  4463.      found_right_border = true;\
  4464.     }\
  4465.    }\
  4466.    else if(found_right_border){\
  4467.      found_right_border = false;\
  4468.     }\
  4469.    }\
  4470.   pixelPos += xsize * 4;\
  4471.  }\
  4472. };\
  4473. ctx.putImageData(image, 0, 0);\
  4474. ctx.restore();\
  4475. };",canvas_root_id,DRAG_CANVAS);
  4476.  
  4477. }
  4478.  
  4479. void add_js_ruler(FILE *js_include_file,
  4480. int canvas_root_id,double x,double y,double sizex,double sizey,char *font,
  4481. char *stroke_color,double stroke_opacity,char *fill_color,double fill_opacity,
  4482. int line_width,int dynamic){
  4483.  fprintf(js_include_file,"\n<!-- begin command ruler -->\n\
  4484. var ruler_data = new Array(3);\
  4485. var ruler%d = function(){\
  4486.  var full = 2*Math.PI;\
  4487.  var once = true;\
  4488.  var canvas = create_canvas%d(3000,xsize,ysize);\
  4489.  var canvas_rect = canvas.getBoundingClientRect();\
  4490.  var ctx = canvas.getContext(\"2d\");\
  4491.  var canvas_temp =  document.createElement(\"canvas\");\
  4492.  var size_x = xsize*(%f)/(xmax - xmin);\
  4493.  var size_y = ysize*(%f)/(ymax - ymin);\
  4494.  var dx = xsize/(xmax - xmin);\
  4495.  var dy = 0.8*ysize/(ymax - ymin);\
  4496.  canvas_temp.width = xsize;\
  4497.  canvas_temp.height = ysize;\
  4498.  var ctx_temp = canvas_temp.getContext(\"2d\");\
  4499.  var xcenter = x2px(%f);\
  4500.  var ycenter = y2px(%f);\
  4501.  var ruler_x = xcenter;\
  4502.  var ruler_y = ycenter;\
  4503.  ctx_temp.font = \"%s\";\
  4504.  ctx_temp.strokeStyle = \"rgba(%s,%f)\";\
  4505.  ctx_temp.fillStyle = \"rgba(%s,%f)\";\
  4506.  ctx_temp.lineWidth = %d;\
  4507.  ctx_temp.save();\
  4508.  if(once){\
  4509.   ctx_temp.beginPath();\
  4510.   ctx_temp.moveTo(ruler_x,ruler_y);\
  4511.   ctx_temp.lineTo(ruler_x+size_x,ruler_y);\
  4512.   ctx_temp.lineTo(ruler_x+size_x,ruler_y-size_y);\
  4513.   ctx_temp.lineTo(ruler_x,ruler_y-size_y);\
  4514.   ctx_temp.lineTo(ruler_x,ruler_y);\
  4515.   ctx_temp.closePath();\
  4516.   ctx_temp.fill();\
  4517.   ctx_temp.stroke();\
  4518.   ctx_temp.fillStyle = ctx_temp.strokeStyle;\
  4519.   var txtsize;\
  4520.   var num = 1;\
  4521.   for(var p = dx ; p < size_x ; p = p+dx){\
  4522.     txtsize = 0.5*(ctx_temp.measureText(num).width);\
  4523.     ctx_temp.fillText(num,ruler_x + p -txtsize,ruler_y - 0.9*dy);\
  4524.     num++;\
  4525.   };\
  4526.   ctx_temp.strokeStyle = \"rgba(0,0,255,0.6)\";\
  4527.   ctx_temp.lineWidth = 2;\
  4528.   for(var p = 0; p < size_x ; p = p+dx){\
  4529.    ctx_temp.beginPath();\
  4530.    ctx_temp.moveTo(ruler_x+p,ruler_y);\
  4531.    ctx_temp.lineTo(ruler_x+p,ruler_y-0.8*dy);\
  4532.    ctx_temp.closePath();\
  4533.    ctx_temp.stroke();\
  4534.   };\
  4535.   ctx_temp.strokeStyle = \"rgba(0,0,255,0.6)\";\
  4536.   ctx_temp.lineWidth = 1;\
  4537.   for(var p = 0; p < size_x ; p = p+0.5*dx){\
  4538.    ctx_temp.beginPath();\
  4539.    ctx_temp.moveTo(ruler_x+p,ruler_y);\
  4540.    ctx_temp.lineTo(ruler_x+p,ruler_y-0.6*dy);\
  4541.    ctx_temp.closePath();\
  4542.    ctx_temp.stroke();\
  4543.   };\
  4544.   ctx_temp.strokeStyle = \"rgba(255,0,0,0.6)\";\
  4545.   ctx_temp.lineWidth = 0.5;\
  4546.   for(var p = 0; p < size_x ; p = p+0.1*dx){\
  4547.    ctx_temp.beginPath();\
  4548.    ctx_temp.moveTo(ruler_x+p,ruler_y);\
  4549.    ctx_temp.lineTo(ruler_x+p,ruler_y-0.4*dy);\
  4550.    ctx_temp.closePath();\
  4551.    ctx_temp.stroke();\
  4552.   };\
  4553.   ctx_temp.drawImage(canvas,ruler_x,ruler_y);\
  4554.   once = false;\
  4555.  }",canvas_root_id,canvas_root_id,sizex,sizey,x,y,font,stroke_color,stroke_opacity,fill_color,fill_opacity,line_width);
  4556.  
  4557.  if( dynamic == -1 ){
  4558.  fprintf(js_include_file,"\
  4559. ctx.drawImage(canvas_temp,0,0);\
  4560.   if(wims_status != \"done\"){\
  4561.    canvas_div.addEventListener( 'mouseup'   , ruler_stop,false);\
  4562.    canvas_div.addEventListener( 'mousedown' , ruler_start,false);\
  4563.    canvas_div.addEventListener( 'mousemove' , ruler_move,false);\
  4564.   };\
  4565.   function ruler_stop(evt){\
  4566.    ruler_data[0] = ruler_x;\
  4567.    ruler_data[1] = ruler_y;\
  4568.    ruler_data[2] = angle;\
  4569.    return;\
  4570.   };\
  4571.   var ruler_click_cnt = 0;\
  4572.   function ruler_start(evt){\
  4573.     canvas_rect = canvas.getBoundingClientRect();\
  4574.     var mouse_y = evt.clientY - canvas_rect.top;\
  4575.     if( mouse_y > ysize - 20 ){return;};\
  4576.     var mouse_x = evt.clientX - canvas_rect.left;\
  4577.     if( mouse_x > ruler_x - 50 && mouse_x < ruler_x + size_x + 50){\
  4578.      if( mouse_y > ruler_y - 50 && mouse_y < ruler_y + size_y + 50){\
  4579.       ruler_click_cnt++;\
  4580.       ruler_move(evt);\
  4581.       return;\
  4582.      };\
  4583.     }else{ruler_click_cnt = 0; return;};\
  4584.   };\
  4585.   var angle = 0;\
  4586.   function ruler_move(evt){\
  4587.    switch(ruler_click_cnt){\
  4588.     case 1:\
  4589.      angle = 0;\
  4590.      canvas_rect = canvas.getBoundingClientRect();\
  4591.      ruler_y = evt.clientY - canvas_rect.top;\
  4592.      if( ruler_y > ysize - 20 ){ruler_y = 0.5*ysize;ruler_x = 0.5*xsize;return;};\
  4593.      ruler_x = evt.clientX - canvas_rect.left;\
  4594.      if( x_use_snap_to_grid == 1 ){\
  4595.       ruler_x = snap_to_x(ruler_x);\
  4596.      };\
  4597.      if( y_use_snap_to_grid == 1 ){\
  4598.       ruler_y = snap_to_y(ruler_y);\
  4599.      };\
  4600.      ctx.clearRect(0,0,xsize,ysize);\
  4601.      ctx.save();\
  4602.      ctx.translate(ruler_x - xcenter,ruler_y - ycenter);\
  4603.      ctx.drawImage(canvas_temp,0,0);\
  4604.      ctx.restore();\
  4605.      break;\
  4606.     case 2:\
  4607.      canvas_rect = canvas.getBoundingClientRect();\
  4608.      var mouse_y = evt.clientY - canvas_rect.top;\
  4609.      var mouse_x = evt.clientX - canvas_rect.left;\
  4610.      angle = find_angle(ruler_x,ruler_y,mouse_x,mouse_y);\
  4611.      if(angle > full){angle = angle - full;};\
  4612.      ctx.clearRect(0,0,xsize,ysize);\
  4613.      ctx.save();\
  4614.      ctx.translate(ruler_x,ruler_y);\
  4615.      ctx.rotate(angle);\
  4616.      ctx.translate( -1*xcenter, -1*ycenter );\
  4617.      ctx.drawImage( canvas_temp,0,0 );\
  4618.      ctx.restore();\
  4619.      break;\
  4620.     case 3:ruler_click_cnt = 0;break;\
  4621.     default:ruler_stop(evt);break;\
  4622.    };\
  4623.   };\
  4624.   function find_angle(xc,yc,x1,y1){\
  4625.    var dx = Math.abs(x1 - xc);\
  4626.    var dy = yc - y1 ;\
  4627.    if( x1 >= xc ){\
  4628.     return -1*Math.atan(dy/dx);\
  4629.    };\
  4630.    if(x1 <= xc && y1 <= yc){return Math.PI - Math.atan(-1*dy/dx);};\
  4631.    if(x1 <= xc && y1 >= yc){return Math.PI + Math.atan(dy/dx);};\
  4632.   };\
  4633.  };\
  4634.  ruler%d();\n",canvas_root_id);
  4635.  }
  4636.  else
  4637.  {
  4638.   fprintf(js_include_file,"\
  4639.   ctx.clearRect(0,0,xsize,ysize);\
  4640.   ctx.save();\
  4641.   ctx.translate(ruler_x,ruler_y);\
  4642.   ctx.rotate(%d*Math.PI/180);\
  4643.   ctx.translate( -1*xcenter, -1*ycenter );\
  4644.   ctx.drawImage( canvas_temp,0,0 );\
  4645.   ctx.restore();\
  4646.  };\
  4647.  ruler%d();",dynamic,canvas_root_id);
  4648.  }
  4649. }
  4650.  
  4651. void add_js_protractor(FILE *js_include_file,int canvas_root_id,int type,double xcenter,double ycenter,int size,char *font,char *stroke_color,double stroke_opacity,char *fill_color,double fill_opacity,int line_width,int display_type,int use_scale,int dynamic){
  4652.  
  4653. /*
  4654. use_slider_display = 2 : angle in degrees
  4655. use_slider_display = 3 : angle in radians
  4656. void add_slider_display(FILE *js_include_file,int canvas_root_id,int precision,int font_size,char *font_color,double stroke_opacity){
  4657. fprintf(js_include_file,"<!-- begin add_slider_display -->\n\
  4658. function show_slider_value(value,use_slider_display)
  4659. */
  4660.  
  4661. if( type == 1 ){ /* geodriehoek */
  4662.  fprintf(js_include_file,"\n<!-- begin command protractor type 1 -->\n\
  4663. var protractor_data = new Array(3);\
  4664. var protractor%d = function(){\
  4665.  var once = true;\
  4666.  var full = 2*Math.PI;\
  4667.  var canvas = create_canvas%d(2000,xsize,ysize);\
  4668.  var canvas_rect = canvas.getBoundingClientRect();\
  4669.  var ctx = canvas.getContext(\"2d\");\
  4670.  var canvas_temp =  document.createElement(\"canvas\");\
  4671.  var size = parseInt(xsize*(%d)/(xmax - xmin));\
  4672.  canvas_temp.width = xsize;\
  4673.  canvas_temp.height = ysize;\
  4674.  var ctx_temp = canvas_temp.getContext(\"2d\");\
  4675.  var type = %d;\
  4676.  var xcenter = x2px(%f);\
  4677.  var ycenter = y2px(%f);\
  4678.  var half = 0.5*size;\
  4679.  var radius1 = 0.6*half;\
  4680.  var radius2 = 0.65*half;\
  4681.  var radius3 = 0.7*half;\
  4682.  ctx_temp.font = \"%s\";\
  4683.  ctx_temp.strokeStyle = \"rgba(%s,%f)\";\
  4684.  ctx_temp.fillStyle = \"rgba(%s,%f)\";\
  4685.  ctx_temp.lineWidth =%d;\
  4686.  var display_type = %d;\
  4687.  var use_scale = %d;\
  4688.  if( once ){\
  4689.   ctx_temp.clearRect(0,0,canvas_temp.width,canvas_temp.height);\
  4690.   ctx_temp.beginPath();\
  4691.   ctx_temp.moveTo(xcenter-half,ycenter );\
  4692.   ctx_temp.lineTo(xcenter,ycenter-half);\
  4693.   ctx_temp.lineTo(xcenter+half,ycenter);\
  4694.   ctx_temp.lineTo(xcenter-half,ycenter);\
  4695.   ctx_temp.moveTo(xcenter,ycenter );\
  4696.   ctx_temp.lineTo(xcenter+0.5*half,ycenter-0.5*half);\
  4697.   ctx_temp.moveTo(xcenter,ycenter );\
  4698.   ctx_temp.lineTo(xcenter-0.5*half,ycenter-0.5*half);\
  4699.   ctx_temp.moveTo(xcenter,ycenter );\
  4700.   ctx_temp.lineTo(xcenter,ycenter-half);\
  4701.   ctx_temp.closePath();\
  4702.   ctx_temp.fill();\
  4703.   ctx_temp.stroke();\
  4704.   ctx_temp.beginPath();\
  4705.   ctx_temp.arc(xcenter,ycenter,radius1,0,Math.PI,false);\
  4706.   ctx_temp.closePath();\
  4707.   if( use_scale == 1 ){\
  4708.    ctx_temp.fillStyle = ctx_temp.strokeStyle;\
  4709.    var txtsize;\
  4710.    for(var p = 45 ; p < 180;p = p+45){\
  4711.     txtsize = 0.5*(ctx_temp.measureText(p).width);\
  4712.     ctx_temp.fillText(p,xcenter+0.5*half*Math.cos(p*Math.PI/180) - txtsize,ycenter-0.5*half*Math.sin(p*Math.PI/180));\
  4713.    };\
  4714.   };\
  4715.   for(var p = 10 ; p < 180;p = p+10){\
  4716.    ctx_temp.beginPath();\
  4717.    ctx_temp.moveTo(xcenter+radius1*Math.cos(p*Math.PI/180),ycenter-radius1*Math.sin(p*Math.PI/180));\
  4718.    ctx_temp.lineTo(xcenter+radius3*Math.cos(p*Math.PI/180),ycenter-radius3*Math.sin(p*Math.PI/180));\
  4719.    ctx_temp.closePath();\
  4720.    ctx_temp.stroke();\
  4721.   };\
  4722.   for(var p = 0 ; p < 180;p=p+2){\
  4723.    if(p%%10 != 0){\
  4724.     ctx_temp.beginPath();\
  4725.     ctx_temp.moveTo(xcenter+radius1*Math.cos(p*Math.PI/180),ycenter-radius1*Math.sin(p*Math.PI/180));\
  4726.     ctx_temp.lineTo(xcenter+radius2*Math.cos(p*Math.PI/180),ycenter-radius2*Math.sin(p*Math.PI/180));\
  4727.     ctx_temp.closePath();\
  4728.     ctx_temp.stroke();\
  4729.    };\
  4730.   };\
  4731.   ctx_temp.drawImage(canvas,xcenter,ycenter);\
  4732.   ctx_temp.save();\
  4733.   once = false;\
  4734.  };\
  4735.  ",canvas_root_id,canvas_root_id,size,type,xcenter,ycenter,font,stroke_color,stroke_opacity,fill_color,fill_opacity,line_width,display_type,use_scale);
  4736.  
  4737. if(dynamic == -1 ){
  4738.  fprintf(js_include_file,"\
  4739.  var protractor_x = xcenter;\
  4740.  var protractor_y = ycenter;\
  4741.  ctx.drawImage(canvas_temp,0,0);\
  4742.  if(wims_status != \"done\"){\
  4743.   canvas_div.addEventListener( 'mouseup'   , protractor_stop,false);\
  4744.   canvas_div.addEventListener( 'mousedown' , protractor_start,false);\
  4745.   canvas_div.addEventListener( 'mousemove' , protractor_move,false);\
  4746.  };\
  4747.  function protractor_stop(evt){\
  4748.   if(display_type > 1 ){show_slider_value([0,angle],display_type);};\
  4749.   protractor_data[0] = protractor_x;\
  4750.   protractor_data[1] = protractor_y;\
  4751.   protractor_data[2] = angle;\
  4752.   return;\
  4753.  };\
  4754.  var protractor_click_cnt = 0;\
  4755.  function protractor_start(evt){\
  4756.    canvas_rect = canvas.getBoundingClientRect();\
  4757.    var mouse_y = evt.clientY - canvas_rect.top;\
  4758.    if( mouse_y > ysize - 20 ){return;};\
  4759.    var mouse_x = evt.clientX - canvas_rect.left;\
  4760.    if( mouse_x > protractor_x - 50 && mouse_x < protractor_x + size ){\
  4761.     if( mouse_y > protractor_y - 50 && mouse_y < protractor_y + size ){\
  4762.      protractor_click_cnt++;\
  4763.      protractor_move(evt);\
  4764.      return;\
  4765.     };\
  4766.    }else{protractor_click_cnt = 0; return;};\
  4767.  };\
  4768.  var angle = 0;\
  4769.  function protractor_move(evt){\
  4770.   switch(protractor_click_cnt){\
  4771.    case 1:\
  4772.      angle = 0;\
  4773.      canvas_rect = canvas.getBoundingClientRect();\
  4774.      protractor_y = evt.clientY - canvas_rect.top;\
  4775.      if( protractor_y > ysize - 20 ){protractor_y = 0.5*ysize;protractor_x = 0.5*xsize;return;};\
  4776.      protractor_x = evt.clientX - canvas_rect.left;\
  4777.      if( x_use_snap_to_grid == 1 ){\
  4778.       protractor_x = snap_to_x(protractor_x);\
  4779.      };\
  4780.      if( y_use_snap_to_grid == 1 ){\
  4781.       protractor_y = snap_to_y(protractor_y);\
  4782.      };\
  4783.      ctx.clearRect(0,0,xsize,ysize);\
  4784.      ctx.save();\
  4785.      ctx.translate(protractor_x - xcenter,protractor_y - ycenter);\
  4786.      ctx.drawImage(canvas_temp,0,0);\
  4787.      ctx.restore();\
  4788.    break;\
  4789.    case 2:\
  4790.      canvas_rect = canvas.getBoundingClientRect();\
  4791.      var mouse_y = parseInt(evt.clientY - canvas_rect.top);\
  4792.      var mouse_x = parseInt(evt.clientX - canvas_rect.left);\
  4793.      angle = find_angle(protractor_x,protractor_y,mouse_x,mouse_y);\
  4794.      ctx.clearRect(0,0,xsize,ysize);\
  4795.      ctx.save();\
  4796.      ctx.translate(protractor_x,protractor_y);\
  4797.      ctx.rotate(angle);\
  4798.      ctx.translate( -1*xcenter, -1*ycenter );\
  4799.      ctx.drawImage( canvas_temp,0,0 );\
  4800.      ctx.restore();\
  4801.      break;\
  4802.    case 3:protractor_click_cnt = 0;break;\
  4803.    default:protractor_stop(evt);\
  4804.   };\
  4805.  };\
  4806.  function find_angle(xc,yc,x1,y1){\
  4807.   var dx = Math.abs(x1 - xc);\
  4808.   var dy = yc - y1 ;\
  4809.   if( x1 >= xc ){\
  4810.    return -1*Math.atan(dy/dx);\
  4811.   };\
  4812.   if(x1 <= xc && y1 <= yc){return Math.PI - Math.atan(-1*dy/dx);};\
  4813.   if(x1 <= xc && y1 >= yc){return Math.PI + Math.atan(dy/dx);};\
  4814.  };\
  4815. };\
  4816. protractor%d();\n\
  4817. ",canvas_root_id);
  4818. }
  4819. else
  4820. {
  4821.  fprintf(js_include_file,"\
  4822.  ctx.save();\
  4823.  ctx.translate(xcenter,ycenter);\
  4824.  ctx.rotate(%d*Math.PI/180);\
  4825.  ctx.translate( -1*xcenter, -1*ycenter );\
  4826.  ctx.drawImage( canvas_temp,0,0 );\
  4827.  ctx.restore();\
  4828. };\
  4829. protractor%d();\n\
  4830. ",dynamic,canvas_root_id);
  4831. }
  4832. } /* end type == 1 */
  4833.  
  4834.  
  4835. if( type == 0 ){
  4836.  fprintf(js_include_file,"\n<!-- begin command protractor type 0 -->\n\
  4837. var protractor_data = new Array(3);\
  4838. var protractor%d = function(){\
  4839.  var once = true;\
  4840.  var full = 2*Math.PI;\
  4841.  var canvas = create_canvas%d(2000,xsize,ysize);\
  4842.  var canvas_rect = canvas.getBoundingClientRect();\
  4843.  var ctx = canvas.getContext(\"2d\");\
  4844.  var canvas_temp =  document.createElement(\"canvas\");\
  4845.  var size = parseInt(xsize*(%d)/(xmax - xmin));\
  4846.  canvas_temp.width = xsize;\
  4847.  canvas_temp.height = ysize;\
  4848.  var ctx_temp = canvas_temp.getContext(\"2d\");\
  4849.  var type = %d;\
  4850.  var xcenter = x2px(%f);\
  4851.  var ycenter = y2px(%f);\
  4852.  var half = 0.5*size;\
  4853.  var radius1 = 0.8*half;\
  4854.  var radius2 = 0.9*half;\
  4855.  var radius3 = half;\
  4856.  ctx_temp.font = \"%s\";\
  4857.  ctx_temp.strokeStyle = \"rgba(%s,%f)\";\
  4858.  ctx_temp.fillStyle = \"rgba(%s,%f)\";\
  4859.  ctx_temp.lineWidth =%d;\
  4860.  var display_type = %d;\
  4861.  var use_scale = %d;\
  4862.  if( once ){\
  4863.   ctx_temp.clearRect(0,0,xsize,ysize);\
  4864.   ctx_temp.arc(xcenter,ycenter,radius1,0,2*Math.PI,false);\
  4865.   ctx_temp.arc(xcenter,ycenter,radius2,0,2*Math.PI,false);\
  4866.   ctx_temp.arc(xcenter,ycenter,radius3,0,2*Math.PI,false);\
  4867.   ctx_temp.fill();\
  4868.   ctx_temp.stroke();\
  4869.   if( use_scale == 1 ){\
  4870.    ctx_temp.fillStyle = ctx_temp.strokeStyle;\
  4871.    var txtsize;\
  4872.    for(var p = 0 ; p < 360;p = p+45){\
  4873.     txtsize = 0.5*(ctx_temp.measureText(p).width);\
  4874.     ctx_temp.fillText(p,xcenter+0.6*half*Math.cos(p*Math.PI/180) - txtsize,ycenter-0.6*half*Math.sin(p*Math.PI/180));\
  4875.    };\
  4876.   };\
  4877.   ctx_temp.strokeStyle = \"rgba(255,0,0,0.4)\";\
  4878.   for(var p = 0 ; p < 360;p = p+10){\
  4879.    ctx_temp.beginPath();\
  4880.    ctx_temp.moveTo(xcenter+radius1*Math.cos(p*Math.PI/180),ycenter-radius1*Math.sin(p*Math.PI/180));\
  4881.    ctx_temp.lineTo(xcenter+radius3*Math.cos(p*Math.PI/180),ycenter-radius3*Math.sin(p*Math.PI/180));\
  4882.    ctx_temp.closePath();\
  4883.    ctx_temp.stroke();\
  4884.   };\
  4885.   ctx_temp.strokeStyle = \"rgba(0,0,255,0.4)\";\
  4886.   for(var p = 0 ; p < 360;p=p+2){\
  4887.     ctx_temp.beginPath();\
  4888.     ctx_temp.moveTo(xcenter+radius2*Math.cos(p*Math.PI/180),ycenter-radius2*Math.sin(p*Math.PI/180));\
  4889.     ctx_temp.lineTo(xcenter+radius3*Math.cos(p*Math.PI/180),ycenter-radius3*Math.sin(p*Math.PI/180));\
  4890.     ctx_temp.closePath();\
  4891.     ctx_temp.stroke();\
  4892.   };\
  4893.   ctx_temp.strokeStyle = \"rgba(0,0,0,0.6)\";\
  4894.   for(var p = 0 ; p < 360;p=p+45){\
  4895.     ctx_temp.beginPath();\
  4896.     ctx_temp.moveTo(xcenter,ycenter);\
  4897.     ctx_temp.lineTo(xcenter+radius3*Math.cos(p*Math.PI/180),ycenter-radius3*Math.sin(p*Math.PI/180));\
  4898.     ctx_temp.closePath();\
  4899.     ctx_temp.stroke();\
  4900.   };\
  4901.   ctx_temp.drawImage(canvas,0,0);\
  4902.   ctx_temp.save();\
  4903.   once = false;\
  4904.  };\n",canvas_root_id,canvas_root_id,size,type,xcenter,ycenter,font,stroke_color,stroke_opacity,fill_color,fill_opacity,line_width,display_type,use_scale);
  4905.  
  4906. if( dynamic == -1 ){
  4907.  fprintf(js_include_file,"\
  4908.  var protractor_x = xcenter;\
  4909.  var protractor_y = ycenter;\
  4910.  ctx.drawImage(canvas_temp,0,0);\
  4911.  if(wims_status != \"done\"){\
  4912.   canvas_div.addEventListener( 'mouseup'   , protractor_stop,false);\
  4913.   canvas_div.addEventListener( 'mousedown' , protractor_start,false);\
  4914.   canvas_div.addEventListener( 'mousemove' , protractor_move,false);\
  4915.  };\
  4916.  function protractor_stop(evt){\
  4917.   if(display_type > 1 ){show_slider_value([0,angle],display_type);};\
  4918.   protractor_data[0] = protractor_x;\
  4919.   protractor_data[1] = protractor_y;\
  4920.   protractor_data[2] = angle;\
  4921.   return;\
  4922.  };\
  4923.  var protractor_click_cnt = 0;\
  4924.  function protractor_start(evt){\
  4925.    canvas_rect = canvas.getBoundingClientRect();\
  4926.    var mouse_y = evt.clientY - canvas_rect.top;\
  4927.    if( mouse_y > ysize - 20 ){return;};\
  4928.    var mouse_x = evt.clientX - canvas_rect.left;\
  4929.    if( mouse_x > protractor_x - half && mouse_x < protractor_x + half ){\
  4930.     if( mouse_y > protractor_y - half && mouse_y < protractor_y + half ){\
  4931.      protractor_click_cnt++;\
  4932.      protractor_move(evt);\
  4933.      return;\
  4934.     };\
  4935.    }else{protractor_click_cnt = 0; return;};\
  4936.  };\
  4937.  var angle = 0;\
  4938.  function protractor_move(evt){\
  4939.   switch(protractor_click_cnt){\
  4940.    case 1:\
  4941.      angle = 0;\
  4942.      canvas_rect = canvas.getBoundingClientRect();\
  4943.      protractor_y = evt.clientY - canvas_rect.top;\
  4944.      if( protractor_y > ysize - 20 ){protractor_y = 0.5*ysize;protractor_x = 0.5*xsize;return;};\
  4945.      protractor_x = evt.clientX - canvas_rect.left;\
  4946.      if( x_use_snap_to_grid == 1 ){\
  4947.       protractor_x = snap_to_x(protractor_x);\
  4948.      };\
  4949.      if( y_use_snap_to_grid == 1 ){\
  4950.       protractor_y = snap_to_y(protractor_y);\
  4951.      };\
  4952.      ctx.clearRect(0,0,xsize,ysize);\
  4953.      ctx.save();\
  4954.      ctx.translate(protractor_x - xcenter,protractor_y - ycenter);\
  4955.      ctx.drawImage(canvas_temp,0,0);\
  4956.      ctx.restore();\
  4957.      break;\
  4958.    case 2:\
  4959.     canvas_rect = canvas.getBoundingClientRect();\
  4960.     var mouse_y = evt.clientY - canvas_rect.top;\
  4961.     var mouse_x = evt.clientX - canvas_rect.left;\
  4962.     angle = find_angle(protractor_x,protractor_y,mouse_x,mouse_y);\
  4963.     if(angle > full){angle = angle - full;};\
  4964.     ctx.clearRect(0,0,xsize,ysize);\
  4965.     ctx.save();\
  4966.     ctx.translate(protractor_x,protractor_y);\
  4967.     ctx.rotate(angle);\
  4968.     ctx.translate( -1*xcenter, -1*ycenter );\
  4969.     ctx.drawImage( canvas_temp,0,0 );\
  4970.     ctx.restore();\
  4971.     break;\
  4972.    case 3:protractor_click_cnt = 0;break;\
  4973.    default:protractor_stop(evt);\
  4974.   };\
  4975.  };\
  4976.  function find_angle(xc,yc,x1,y1){\
  4977.   var dx = Math.abs(x1 - xc);\
  4978.   var dy = yc - y1 ;\
  4979.   if( x1 >= xc ){\
  4980.    return -1*Math.atan(dy/dx);\
  4981.   };\
  4982.   if(x1 <= xc && y1 <= yc){return Math.PI - Math.atan(-1*dy/dx);};\
  4983.   if(x1 <= xc && y1 >= yc){return Math.PI + Math.atan(dy/dx);};\
  4984.  };\
  4985. };\
  4986. protractor%d();\n\
  4987. ",canvas_root_id);
  4988. }
  4989. else
  4990. {
  4991.  fprintf(js_include_file,"\
  4992.  ctx.save();\
  4993.  ctx.translate(xcenter,ycenter);\
  4994.  ctx.rotate(%d*Math.PI/180);\
  4995.  ctx.translate( -1*xcenter, -1*ycenter );\
  4996.  ctx.drawImage( canvas_temp,0,0 );\
  4997.  ctx.restore();\
  4998. };\
  4999. protractor%d();\
  5000. ",dynamic,canvas_root_id);
  5001. } /* end dynamic == -1*/
  5002.  
  5003. } /* end type == 0 */
  5004.  
  5005.  
  5006. }
  5007.  
  5008.