Subversion Repositories wimsdev

Rev

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

  1. void add_drag_code(FILE *js_include_file,int canvas_cnt,int canvas_root_id);
  2. 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);
  3. void add_setlimits(FILE *js_include_file, int canvas_root_id);
  4. void add_safe_eval(FILE *js_include_file);
  5. void add_to_js_math(FILE *js_include_file);
  6. void add_calc_y(FILE *js_include_file,int canvas_root_id,char *jsmath);
  7. void add_jsplot(FILE *js_include_file,int canvas_root_id);
  8. 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);
  9. void add_slider_display(FILE *js_include_file, int canvas_root_id,int precision,int font_size,char *font_color,double stroke_opacity);
  10. 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);
  11. void *my_newmem(size_t size);
  12. void canvas_error(char *msg);
  13. char *eval(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int xsteps,int precision);
  14. char *eval_parametric(int xsize,int ysize,char *fun1,char* fun2,double xmin,double xmax,double ymin,double ymax, double tmin,double tmax,int plotsteps,int precision);
  15. char *eval_levelcurve(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int plotsteps,int precision,double level);
  16. char *data2js_array(int data[],int len);
  17. char *xy2js_array(int xy[],int len);
  18. char *double_xy2js_array(double xy[],int len,int decimals);
  19. int find_number_of_digits(int i);
  20. int x2px(double x);
  21. int y2px(double y);
  22. void add_clear_button(FILE *js_include_file,int canvas_root_id,char *input_style,char *button_text);
  23. void add_js_inputs(FILE *js_include_file,int canvas_root_id,int num,int input_cnt,char *input_style,int line_width);
  24. 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);
  25. 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);
  26. 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);
  27. 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);
  28. 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);
  29. 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);
  30. 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);
  31. 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);
  32. 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);
  33. 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);
  34. 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);
  35. 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);
  36. void add_js_floodfill(FILE *js_include_file,int canvas_root_id);
  37. void add_js_filltoborder(FILE *js_include_file,int canvas_root_id);
  38. 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);
  39. void add_js_text(FILE *js_include_file,int canvas_root_id,int font_size,char *font_family,char *font_color,double stroke_opacity);
  40. void add_input_circle(FILE *js_include_file,int type,int num);
  41. void add_input_segment(FILE *js_include_file,int num);
  42. void add_input_line(FILE *js_include_file,int num);
  43. void add_input_polyline(FILE *js_include_file);
  44. void add_textarea_polygon(FILE *js_include_file);
  45. void add_input_crosshair(FILE *js_include_file,int num);
  46. void add_input_arrow(FILE *js_include_file,int num);
  47. void add_input_xy(FILE *js_include_file, int canvas_root_id);
  48. void add_input_xyr(FILE *js_include_file, int canvas_root_id);
  49. void add_input_x1y1x2y2(FILE *js_include_file, int canvas_root_id);
  50. void add_textarea_xy(FILE *js_include_file, int canvas_root_id);
  51. void add_zoom_buttons(FILE *js_include_file,int canvas_root_id,char *stroke_color,double stroke_opacity);
  52. void add_js_tooltip(int canvas_root_id,char *tooltip_text,char *bgcolor,int xsize,int ysize);
  53.  
  54.  
  55.  
  56. void add_js_inputs(FILE *js_include_file,int canvas_root_id,int num,int input_cnt,char *input_style,int line_width){
  57. fprintf(js_include_file,"\n<!-- user draw inputfields -->\n\
  58. var canvas_rect;\
  59. var input_cnt = %d;\
  60. var start_input_cnt = input_cnt;\
  61. function user_drag(evt){return;}\
  62. function user_draw(evt){\
  63. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  64. var x = evt.clientX - canvas_rect.left;\
  65. var y = evt.clientY - canvas_rect.top;\
  66. if( x_use_snap_to_grid == 1 ){\
  67.  x = snap_to_x(x);\
  68. };\
  69. if( y_use_snap_to_grid == 1 ){\
  70.  y = snap_to_y(y);\
  71. };\
  72. var num = %d;var inputs;var marge = 20;\
  73. if(evt.which == 1){\
  74.  var inputs;var xi;var yi;var wi;var hi;\
  75.  var div_x = findPosX(canvas_div);\
  76.  var div_y = findPosY(canvas_div);\
  77.  var found = 0;\
  78.  if( start_input_cnt < input_cnt){\
  79.   for(var p = start_input_cnt ; p < input_cnt ; p++ ){\
  80.    inputs = document.getElementById(\"canvas_input\"+p);\
  81.    xi = findPosX(inputs) - div_x;\
  82.    yi = findPosY(inputs) - div_y;\
  83.    wi = marge + inputs.clientWidth;\
  84.    hi = marge + inputs.clientHeight;\
  85.    if( x > xi - marge && x < xi + wi && y > yi - hi && y < yi + marge ){\
  86.     found = 1;\
  87.    };\
  88.   };\
  89.  };\
  90.  if( found == 0 ){\
  91.   if( num == 1 ){\
  92.    inputs = document.getElementById(\"canvas_input\"+start_input_cnt);\
  93.    try{canvas_div.removeChild(inputs);}catch(e){};\
  94.    input_cnt = 0;\
  95.   };\
  96.   userdraw_x.push(x);userdraw_y.push(y);\
  97.   draw_inputs(%d,input_cnt,x,y,%d,1,\"%s\",\"?\");\
  98.   input_cnt++;\
  99.  };\
  100. }\
  101. else\
  102. {\
  103.  for(var p = start_input_cnt ; p < input_cnt; p++){\
  104.   inputs = document.getElementById(\"canvas_input\"+p);\
  105.   try{canvas_div.removeChild(inputs);}catch(e){};\
  106.  };\
  107.  userdraw_x = [];userdraw_y = [];\
  108.  input_cnt = start_input_cnt;\
  109. };\
  110. };",input_cnt,num,canvas_root_id,line_width,input_style);
  111. }
  112.  
  113. void add_zoom_buttons(FILE *js_include_file,int canvas_root_id,char *stroke_color,double stroke_opacity){
  114. fprintf(js_include_file,"\n<!-- draw zoom buttons -->\n\
  115. var draw_zoom_buttons = function(){\
  116. var obj;var canvas_type =%d;\
  117. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){\
  118.  obj = document.getElementById(\"wims_canvas%d\"+canvas_type);\
  119. }\
  120. else\
  121. {\
  122.  obj = create_canvas%d(canvas_type,xsize,ysize);\
  123. };\
  124. var ctx = obj.getContext(\"2d\");\
  125. ctx.font =\"18px Ariel\";\
  126. ctx.textAlign = \"right\";\
  127. ctx.fillStyle=\"rgba(\"+%s+\",\"+%f+\")\";\
  128. ctx.fillText(\"+\",xsize,ysize);\
  129. ctx.fillText(\"\\u2212\",xsize - 15,ysize);\
  130. ctx.fillText(\"\\u2192\",xsize - 30,ysize-2);\
  131. ctx.fillText(\"\\u2190\",xsize - 45,ysize-2);\
  132. ctx.fillText(\"\\u2191\",xsize - 60,ysize-2);\
  133. ctx.fillText(\"\\u2193\",xsize - 75,ysize-2);\
  134. ctx.fillText(\"\\u00D7\",xsize - 90,ysize-2);\
  135. ctx.stroke();\
  136. };\ndraw_zoom_buttons();",BG_CANVAS,canvas_root_id,canvas_root_id,canvas_root_id,stroke_color,stroke_opacity);    
  137. }
  138.  
  139. 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){
  140. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  141. var num = %d;\
  142. userdraw_radius[0] = %d;\
  143. var line_width = %d;\
  144. var stroke_color = \"%s\";\
  145. var stroke_opacity = %f;\
  146. var use_filled = %d;\
  147. var fill_color = \"%s\";\
  148. var fill_opacity = %f;\
  149. var use_dashed = %d;\
  150. var dashtype1 = %d;\
  151. var dashtype0 = %d;\
  152. var click_cnt = 0;\
  153. var x0,y0,x1,y1;\
  154. var canvas_rect;\
  155. function user_draw(evt){\
  156. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  157. y0 = evt.clientY - canvas_rect.top;\
  158. if(y0 < ysize + 1){\
  159.  x0 = evt.clientX - canvas_rect.left;\
  160.  if( x_use_snap_to_grid == 1 ){\
  161.   x0 = snap_to_x(x0);\
  162.  };\
  163.  if( y_use_snap_to_grid == 1 ){\
  164.   y0 = snap_to_y(y0);\
  165.  };\
  166.  if(evt.which == 1){\
  167.   if( click_cnt == 0 ){\
  168.    userdraw_x[xy_cnt] = x0;\
  169.    userdraw_y[xy_cnt] = y0;\
  170.    userdraw_radius[xy_cnt] = line_width;\
  171.    click_cnt = 1;\
  172.    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);\
  173.   }\
  174.   else\
  175.   {\
  176.    click_cnt = 0;\
  177.    if( num != 1 ){ xy_cnt++; }\
  178.   }\
  179.  }\
  180.  else\
  181.  {\
  182.    canvas_remove(x0,y0);\
  183.  }\
  184. }\
  185. };\
  186. function user_drag(evt){\
  187. if( click_cnt == 1 ){\
  188.    canvas_rect = canvas_userdraw.getBoundingClientRect();\
  189.    y1 = evt.clientY - canvas_rect.top;\
  190.    x1 = evt.clientX - canvas_rect.left;\
  191.    if( x_use_snap_to_grid == 1 ){\
  192.     x0 = snap_to_x(x0);\
  193.    };\
  194.    if( y_use_snap_to_grid == 1 ){\
  195.     y0 = snap_to_y(y0);\
  196.    };\
  197.    userdraw_radius[xy_cnt] = parseInt(Math.sqrt( (x1-x0)*(x1-x0) + (y1-y0)*(y1-y0) ));\
  198.    userdraw_x[xy_cnt] = x0;\
  199.    userdraw_y[xy_cnt] = y0;\
  200.    context_userdraw.clearRect(0,0,xsize,ysize);\
  201.    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);\
  202.  }\
  203. };\
  204. function canvas_remove(x,y){\
  205. var marge = 10*line_width;\
  206. var diff1;var diff2;\
  207. for(var p = 0;p < userdraw_x.length ; p++){\
  208.  diff1 = (x-userdraw_x[p])*(x - userdraw_x[p]) + (y - userdraw_y[p])*(y - userdraw_y[p]) - userdraw_radius[p]*userdraw_radius[p];\
  209.  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);\
  210.  if( diff1 < 0 && diff2 > 0 ){\
  211.   if(confirm(\"remove circle ?\")){\
  212.    if( num == 1 ){ userdraw_x = [];userdraw_y = []; userdraw_radius = [];xy_cnt = 0;context_userdraw.clearRect(0,0,xsize,ysize); return;}\
  213.    else\
  214.    {\
  215.     userdraw_x.splice(p,1);\
  216.     userdraw_y.splice(p,1);\
  217.     userdraw_radius.splice(p,1);\
  218.     xy_cnt--;\
  219.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  220.     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);\
  221.    };\
  222.   };\
  223.   return;\
  224.  }\
  225. }\
  226. };",draw_type,num,radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);
  227. }
  228.  
  229. 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){
  230. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on currect active canvas -->\n\
  231. var num = %d;\
  232. var crosshair_size = parseInt(0.5*%d);\
  233. var canvas_rect;\
  234. var line_width = %d;\
  235. var stroke_color = \"%s\";\
  236. var stroke_opacity = %f;\
  237. context_userdraw.lineWidth = line_width;\
  238. context_userdraw.strokeStyle=\"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  239. function user_drag(evt){return;}\
  240. function user_draw(evt){\
  241. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  242. var x = evt.clientX - canvas_rect.left;\
  243. var y = evt.clientY - canvas_rect.top;\
  244. if( x_use_snap_to_grid == 1 ){\
  245.  x = snap_to_x(x);\
  246. };\
  247. if( y_use_snap_to_grid == 1 ){\
  248.  y = snap_to_y(y);\
  249. };\
  250. var x1,y1,x2,y2;\
  251. if(evt.which == 1){\
  252.   userdraw_x[xy_cnt] = x;\
  253.   userdraw_y[xy_cnt] = y;\
  254.   x1 = x - crosshair_size;\
  255.   x2 = x + crosshair_size;\
  256.   y1 = y - crosshair_size;\
  257.   y2 = y + crosshair_size;\
  258.   if( num != 1 ){ xy_cnt++;\
  259.    for(var p = 0; p < xy_cnt - 1 ;p++){\
  260.     if(x1 < userdraw_x[p] && x2 > userdraw_x[p]){\
  261.      if(y1 < userdraw_y[p] && y2 > userdraw_y[p]){\
  262.       canvas_remove(x,y);\
  263.       context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");\
  264.      }\
  265.     }\
  266.    }\
  267.   };\
  268.   context_userdraw.beginPath();\
  269.   context_userdraw.moveTo(x1,y1);\
  270.   context_userdraw.lineTo(x2,y2);\
  271.   context_userdraw.closePath();\
  272.   context_userdraw.stroke();\
  273.   context_userdraw.beginPath();\
  274.   context_userdraw.moveTo(x2,y1);\
  275.   context_userdraw.lineTo(x1,y2);\
  276.   context_userdraw.closePath();\
  277.   context_userdraw.stroke();\
  278.   context_userdraw.clearRect(0,0,xsize,ysize);\
  279.   draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  280. }\
  281. else\
  282. {\
  283. canvas_remove(x,y);\
  284. }\
  285. }\
  286. function canvas_remove(x,y){\
  287. var marge = 2*crosshair_size;\
  288. for(var p = 0;p < userdraw_x.length ; p++){\
  289.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  290.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  291.    userdraw_x.splice(p,1);userdraw_y.splice(p,1);\
  292.    context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);xy_cnt--;\
  293.    draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  294.    return;\
  295.   }\
  296.  }\
  297. }\
  298. };",draw_type,num,crosshair_size,line_width,stroke_color,stroke_opacity);
  299. }
  300.  
  301. 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){
  302. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on currect active canvas -->\n\
  303. var canvas_rect;\
  304. var roundrect = %d;\
  305. var line_width = %d;\
  306. var stroke_color = \"%s\";\
  307. var stroke_opacity = %f;\
  308. var use_filled = %d;\
  309. var fill_color = \"%s\";\
  310. var fill_opacity = %f;\
  311. var use_dashed = %d;\
  312. var dashtype0 = %d;\
  313. var dashtype1 = %d;\
  314. var num = %d;\
  315. var use_rotate = 0;\
  316. var angle = 0;\
  317. var closed_path = 1;\
  318. var clickcnt = 0;\
  319. xy_cnt = 0;\
  320. var x0,y0,x1,y1;\
  321. var marge = 10*line_width;\
  322. function user_draw(evt){\
  323. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  324. y0 = evt.clientY - canvas_rect.top;\
  325. if( y0  < ysize + 1 ){\
  326.  x0 = evt.clientX - canvas_rect.left;\
  327.  if( x_use_snap_to_grid == 1 ){\
  328.   x0 = snap_to_x(x0);\
  329.  };\
  330.  if( y_use_snap_to_grid == 1 ){\
  331.   y0 = snap_to_y(y0);\
  332.  };\
  333.  if( evt.which == 1 ){\
  334.   if(clickcnt == 0 ){\
  335.    clickcnt = 1;\
  336.    userdraw_x[xy_cnt] = x0;userdraw_y[xy_cnt] = y0;xy_cnt++;\
  337.   }\
  338.   else\
  339.   {\
  340.    clickcnt = 0;\
  341.    if(roundrect == 0 ){\
  342.     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]);\
  343.    }\
  344.    else\
  345.    {\
  346.     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]);\
  347.    }\
  348.    if( num != 1 ){ xy_cnt++; }else{xy_cnt--;}\
  349.   }\
  350.  }\
  351.  else\
  352.  {\
  353.   canvas_remove(x0,y0);\
  354.  };\
  355. };\
  356. };\
  357. function user_drag(evt){\
  358. if( clickcnt == 1 ){\
  359.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  360.  y1 = evt.clientY - canvas_rect.top;\
  361.  x1 = evt.clientX - canvas_rect.left;\
  362.  if( x_use_snap_to_grid == 1 ){\
  363.  x1 = snap_to_x(x1);\
  364.  };\
  365.  if( y_use_snap_to_grid == 1 ){\
  366.  y1 = snap_to_y(y1);\
  367.  };\
  368.  userdraw_x[xy_cnt] = x1;\
  369.  userdraw_y[xy_cnt] = y1;\
  370.  context_userdraw.clearRect(0,0,xsize,ysize);\
  371.  if( roundrect == 0 ){\
  372.   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]);\
  373.  }\
  374.  else\
  375.  {\
  376.   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]);\
  377.  };\
  378. };\
  379. };\
  380. function canvas_remove(x,y){\
  381. for(var p = 0;p < userdraw_x.length ; p++){\
  382.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  383.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  384.    if( confirm(\"remove rectangle ?\" )){\
  385.     if( p%%2 == 0 ){\
  386.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  387.     }\
  388.     else\
  389.     {\
  390.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  391.     }\
  392.     xy_cnt--;\
  393.     context_userdraw.clearRect(0,0,xsize,ysize);\
  394.     if(xy_cnt < 2){xy_cnt = 0;click_cnt = 0;userdraw_x = [];userdraw_y = [];return;};\
  395.     if( roundrect == 0 ){\
  396.      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]);\
  397.     }\
  398.     else\
  399.     {\
  400.      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]);\
  401.     }\
  402.     return;\
  403.    };\
  404.   };\
  405.  };\
  406. };\
  407. };",draw_type,roundrect,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,num);
  408. }
  409.  
  410. 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){
  411. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on currect active canvas -->\n\
  412. var canvas_rect;\
  413. var num = %d;\
  414. var line_width = %d;\
  415. var stroke_color = \"%s\";\
  416. var stroke_opacity = %f;\
  417. var use_filled = %d;\
  418. var fill_color = \"%s\";\
  419. var fill_opacity = %f;\
  420. var use_dashed = %d;\
  421. var dashtype0 = %d;\
  422. var dashtype1 = %d;\
  423. var use_rotate = 0;\
  424. var angle = 0;\
  425. var use_translate = 0;\
  426. var vector=[0,0];\
  427. var closed_path = 1;\
  428. var done = 1;\
  429. var x,y;\
  430. var marge = 10*line_width;\
  431. function user_draw(evt){\
  432. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  433. y = evt.clientY - canvas_rect.top;\
  434. if( y < ysize + 1 ){\
  435.  x = evt.clientX - canvas_rect.left;\
  436.  if( x_use_snap_to_grid == 1 ){\
  437.   x = snap_to_x(x);\
  438.  };\
  439.  if( y_use_snap_to_grid == 1 ){\
  440.   y = snap_to_y(y);\
  441.  };\
  442.  if( evt.which == 1){\
  443.   if( num == -1 && xy_cnt > 2 ){\
  444.    if( x - marge < userdraw_x[0] && x + marge > userdraw_x[0]){\
  445.     if( y - marge < userdraw_y[0] && y + marge > userdraw_y[0]){\
  446.      userdraw_x.splice(xy_cnt,1);userdraw_y.splice(xy_cnt,1);\
  447.      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]);\
  448.      done = 1;return;\
  449.     };\
  450.    };\
  451.   }\
  452.   else\
  453.   {\
  454.    if( xy_cnt == num - 1){\
  455.     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]);\
  456.     done = 1;return;\
  457.    };\
  458.   };\
  459.   done = 0;\
  460.   userdraw_x[xy_cnt] = x;userdraw_y[xy_cnt] = y;xy_cnt++;\
  461.   user_drag(evt);\
  462.  }\
  463.  else\
  464.  {\
  465.   canvas_remove(x,y);\
  466.   return;\
  467.  }\
  468. };\
  469. };\
  470. function user_drag(evt){\
  471. if( done == 0 ){\
  472.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  473.  x = evt.clientX - canvas_rect.left;\
  474.  y = evt.clientY - canvas_rect.top;\
  475.  if( x_use_snap_to_grid == 1 ){\
  476.   x = snap_to_x(x);\
  477.  };\
  478.  if( y_use_snap_to_grid == 1 ){\
  479.   y = snap_to_y(y);\
  480.  };\
  481.  context_userdraw.clearRect(0,0,xsize,ysize);\
  482.  userdraw_x[xy_cnt] = x;userdraw_y[xy_cnt] = y;\
  483.  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]);\
  484. }\
  485. }\
  486. function canvas_remove(x,y){\
  487. for(var p = 0;p < userdraw_x.length ; p++){\
  488.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  489.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  490.    if( confirm(\"remove polygone ?\" )){\
  491.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  492.     xy_cnt = 0;userdraw_x = [];userdraw_y = [];done = 1;\
  493.    }\
  494.    return;\
  495.   }\
  496.  }\
  497. }\
  498. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);
  499. }
  500.  
  501. /*  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);*/
  502. 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){
  503. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  504. var num = %d;\
  505. var canvas_rect;\
  506. userdraw_radius[0] = %d;\
  507. var line_width = %d;\
  508. var stroke_color = \"%s\";\
  509. var stroke_opacity = %f;\
  510. var use_filled = %d;\
  511. var fill_color = \"%s\";\
  512. var fill_opacity = %f;\
  513. var use_dashed = %d;\
  514. var dashtype0 = %d;\
  515. var dashtype1 = %d;\
  516. function user_drag(evt){return;};\
  517. function user_draw(evt){\
  518. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  519. var y = evt.clientY - canvas_rect.top;\
  520. if( y < ysize + 1 ){\
  521.  var lu = userdraw_x.length;\
  522.  var x = evt.clientX - canvas_rect.left;\
  523.  if( x_use_snap_to_grid == 1 ){\
  524.   x = snap_to_x(x);\
  525.  };\
  526.  if( y_use_snap_to_grid == 1 ){\
  527.   y = snap_to_y(y);\
  528.  };\
  529.  if(evt.which == 1){\
  530.   if( num == 1 ){\
  531.   userdraw_x[0] = x;\
  532.   userdraw_y[0] = y;\
  533.   }\
  534.   else\
  535.   {\
  536.   userdraw_x[lu] = x;\
  537.   userdraw_y[lu] = y;\
  538.   userdraw_radius[lu] = userdraw_radius[0];\
  539.   };\
  540.   context_userdraw.clearRect(0,0,xsize,ysize);\
  541.   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);\
  542.  }\
  543.  else\
  544.  {\
  545.  canvas_remove(x,y);\
  546.  }\
  547. }\
  548. };\
  549. function canvas_remove(x,y){\
  550. var marge = 4*line_width;\
  551. for(var p = 0;p < userdraw_x.length ; p++){\
  552.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  553.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  554.    userdraw_x.splice(p,1);userdraw_y.splice(p,1);\
  555.    context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  556.    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);\
  557.    return;\
  558.   }\
  559.  }\
  560. }\
  561. };",draw_type,num,radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);
  562.  
  563. }
  564. 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){
  565. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  566. var canvas_rect;\
  567. var cnt = 0;\
  568. var line_width = %d;\
  569. var stroke_color = \"%s\";\
  570. var stroke_opacity = %f;\
  571. var use_dashed = %d;\
  572. var dashtype0 = %d;\
  573. var dashtype1 = %d;\
  574. function user_draw(evt){\
  575. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  576. var x = evt.clientX - canvas_rect.left;\
  577. var y = evt.clientY - canvas_rect.top;\
  578. var lu = userdraw_x.length;\
  579. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  580. if( x_use_snap_to_grid == 1 ){\
  581.  x = snap_to_x(x);\
  582. };\
  583. if( y_use_snap_to_grid == 1 ){\
  584.  y = snap_to_y(y);\
  585. };\
  586. if( evt.which == 1 ){\
  587.  userdraw_x[lu] = x;userdraw_y[lu] = y;\
  588.  if( cnt == 0 ){\
  589.   user_drag(evt);\
  590.   cnt = 1;\
  591.  }\
  592.  else\
  593.  {\
  594.    cnt = 0;\
  595.    draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  596.  }\
  597. }\
  598. else\
  599. {\
  600.  canvas_remove(x,y);\
  601. }\
  602. };\
  603. function user_drag(evt){\
  604. if( cnt == 0){\
  605.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  606.  var x = evt.clientX - canvas_rect.left;\
  607.  var y = evt.clientY - canvas_rect.top;\
  608.  if( x_use_snap_to_grid == 1 ){\
  609.   x = snap_to_x(x);\
  610.  };\
  611.  if( y_use_snap_to_grid == 1 ){\
  612.   y = snap_to_y(y);\
  613.  };\
  614.  var lu = userdraw_x.length;\
  615.  if( lu > 0 ){\
  616.   userdraw_x[lu - 1] = x; userdraw_y[lu - 1] = y;\
  617.   draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  618.  };\
  619. }\
  620. };\
  621. function canvas_remove(x,y){\
  622. if( confirm(\"remove line ?\" )){\
  623.  context_userdraw.clearRect(0,0,xsize,ysize);\
  624.  userdraw_x = [];userdraw_y = [];cnt = 1;\
  625.  return;\
  626. }\
  627. };",draw_type,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  628. }
  629.  
  630. 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){
  631. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  632. var canvas_rect;\
  633. var num = %d;\
  634. var line_width = %d;\
  635. var stroke_color = \"%s\";\
  636. var stroke_opacity = %f;\
  637. var use_dashed = %d;\
  638. var dashtype0 = %d;\
  639. var dashtype1 = %d;\
  640. var x0,y0;\
  641. function user_draw(evt){\
  642. var lu = userdraw_x.length;\
  643. if( lu != 0 && lu%%2 == 0){\
  644.  draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  645. }\
  646. var y = evt.clientY - canvas_rect.top;\
  647. if( y < ysize + 1){\
  648.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  649.  var x = evt.clientX - canvas_rect.left;\
  650.  if( x_use_snap_to_grid == 1 ){\
  651.   x = snap_to_x(x);\
  652.  };\
  653.  if( y_use_snap_to_grid == 1 ){\
  654.   y = snap_to_y(y);\
  655.  };\
  656.  if( evt.which == 1 ){\
  657.   if( lu%%2 == 0){\
  658.    x0 = x;y0 = y;\
  659.    if(num == 1){ userdraw_x = [];userdraw_y = [];userdraw_x[0] = x0;userdraw_y[0] = y0;} else {userdraw_x[lu] = x0;userdraw_y[lu] = y0;}\
  660.    draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  661.    user_drag(evt);\
  662.   }\
  663.   else\
  664.   {\
  665.    if( num == 1 ){ userdraw_x[1] = x;userdraw_y[1] = y;} else {userdraw_x[lu] = x;userdraw_y[lu] = y;};\
  666.    draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  667.   }\
  668.  }\
  669.  else\
  670.  {\
  671.   canvas_remove(x,y);\
  672.  }\
  673. }\
  674. };\
  675. function user_drag(evt){\
  676. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  677. var x = evt.clientX - canvas_rect.left;\
  678. var y = evt.clientY - canvas_rect.top;\
  679. var lu = userdraw_x.length;\
  680. if( x_use_snap_to_grid == 1 ){\
  681.   x = snap_to_x(x);\
  682. };\
  683. if( y_use_snap_to_grid == 1 ){\
  684.   y = snap_to_y(y);\
  685. };\
  686. if( lu%%2 != 0 ){\
  687.  context_userdraw.clearRect(0,0,xsize,ysize);\
  688.  draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  689.  draw_circles(context_userdraw,[x],[y],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  690.  draw_segments(context_userdraw,[x0,x],[y0,y],line_width,stroke_color,stroke_opacity);\
  691.  if( lu > 0){\
  692.   draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  693.  }\
  694. }\
  695. };\
  696. function canvas_remove(x,y){\
  697. var marge = 10*line_width;\
  698. for(var p = 0;p < userdraw_x.length ; p++){\
  699.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  700.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  701.    if( confirm(\"remove line ?\" )){\
  702.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  703.     if( p%%2 == 0 ){\
  704.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  705.     }\
  706.     else\
  707.     {\
  708.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  709.     }\
  710.     if(userdraw_x.length < 2){ userdraw_x = [];userdraw_y = [];return;};\
  711.     draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  712.    }\
  713.    return;\
  714.   }\
  715.  }\
  716. }\
  717. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  718. }
  719.  
  720. /*
  721. num=1 single horizontal line
  722. num=2 multiple horizontal lines
  723. num=3 single vertical line
  724. num=4 multiple vertical lines
  725. */
  726. 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){
  727. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  728. var canvas_rect;\
  729. var num = %d;\
  730. var line_width = %d;\
  731. var stroke_color = \"%s\";\
  732. var stroke_opacity = %f;\
  733. var use_dashed = %d;\
  734. var dashtype0 = %d;\
  735. var dashtype1 = %d;\
  736. var x0,y0;\
  737. function user_draw(evt){\
  738. if( evt.which == 1 ){\
  739.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  740.  var y = evt.clientY - canvas_rect.top;\
  741.  var x = evt.clientX - canvas_rect.left;\
  742.  if( x_use_snap_to_grid == 1 ){\
  743.   x = snap_to_x(x);\
  744.  };\
  745.  if( y_use_snap_to_grid == 1 ){\
  746.   y = snap_to_y(y);\
  747.  };\
  748.  var lu = userdraw_x.length;\
  749.  switch(num){\
  750.   case 1: userdraw_x[0] = x;userdraw_x[1] = xmax;userdraw_y[0] = y; userdraw_y[1] = y;break;\
  751.   case 2: userdraw_x[lu] = x;userdraw_x[lu+1] = xmax;userdraw_y[lu] = y;userdraw_y[lu+1] = y;break;\
  752.   case 3: userdraw_x[0] = x;userdraw_x[1] = x;userdraw_y[0] = y; userdraw_y[1] = ymax;break;\
  753.   case 4: userdraw_x[lu] = x;userdraw_x[lu+1] = x;userdraw_y[lu] = y;userdraw_y[lu+1] = ymax;break;\
  754.  };\
  755.  context_userdraw.clearRect(0,0,xsize,ysize);\
  756.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  757. }\
  758. else\
  759. {\
  760.  userdraw_x = [];userdraw_y = [];context_userdraw.clearRect(0,0,xsize,ysize);return;\
  761. };\
  762. };\
  763. function user_drag(evt){ return evt; };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  764. }
  765.  
  766.  
  767. 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){
  768. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  769. var canvas_rect;\
  770. var num = %d;\
  771. var line_width = %d;\
  772. var stroke_color = \"%s\";\
  773. var stroke_opacity = %f;\
  774. var use_dashed = %d;\
  775. var dashtype0 = %d;\
  776. var dashtype1 = %d;\
  777. var x0,y0;\
  778. function user_draw(evt){\
  779. var lu = userdraw_x.length;\
  780. if( lu != 0 && lu%%2 == 0){\
  781.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  782. }\
  783. var y = evt.clientY - canvas_rect.top;\
  784. if( y < ysize + 1){\
  785.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  786.  var x = evt.clientX - canvas_rect.left;\
  787.  if( x_use_snap_to_grid == 1 ){\
  788.   x = snap_to_x(x);\
  789.  };\
  790.  if( y_use_snap_to_grid == 1 ){\
  791.   y = snap_to_y(y);\
  792.  };\
  793.  if( evt.which == 1 ){\
  794.   if( lu%%2 == 0){\
  795.    x0 = x;y0 = y;\
  796.    if(num == 1){ userdraw_x = [];userdraw_y = [];userdraw_x[0] = x0;userdraw_y[0] = y0;} else {userdraw_x[lu] = x0;userdraw_y[lu] = y0;}\
  797.    draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  798.    user_drag(evt);\
  799.   }\
  800.   else\
  801.   {\
  802.    if( num == 1 ){ userdraw_x[1] = x;userdraw_y[1] = y;} else {userdraw_x[lu] = x;userdraw_y[lu] = y;};\
  803.    draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  804.   };\
  805.  }\
  806.  else\
  807.  {\
  808.   canvas_remove(x,y);\
  809.  };\
  810. };\
  811. };\
  812. function user_drag(evt){\
  813. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  814. var x = evt.clientX - canvas_rect.left;\
  815. var y = evt.clientY - canvas_rect.top;\
  816. var lu = userdraw_x.length;\
  817. if( x_use_snap_to_grid == 1 ){\
  818.   x = snap_to_x(x);\
  819. };\
  820. if( y_use_snap_to_grid == 1 ){\
  821.   y = snap_to_y(y);\
  822. };\
  823. if( lu%%2 != 0 ){\
  824.  context_userdraw.clearRect(0,0,xsize,ysize);\
  825.  draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  826.  draw_circles(context_userdraw,[x],[y],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  827.  draw_lines(context_userdraw,[x0,x],[y0,y],line_width,stroke_color,stroke_opacity);\
  828.  if( lu > 0){\
  829.   draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  830.  }\
  831. }\
  832. };\
  833. function canvas_remove(x,y){\
  834. var marge = 10*line_width;\
  835. for(var p = 0;p < userdraw_x.length ; p++){\
  836.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  837.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  838.    if( confirm(\"remove line ?\" )){\
  839.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  840.     if( p%%2 == 0 ){\
  841.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  842.     }\
  843.     else\
  844.     {\
  845.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  846.     }\
  847.     if(userdraw_x.length < 2){ userdraw_x = [];userdraw_y = [];return;};\
  848.     draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  849.    }\
  850.    return;\
  851.   }\
  852.  }\
  853. }\
  854. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  855. }
  856.  
  857. 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){
  858. /*
  859. constants in draw_arrows() ... for this moment: ;var use_rotate = 0;var angle = 0;var use_translate = 0 ;var vector = [0,0];\
  860.  
  861. */
  862. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  863. var canvas_rect;\
  864. var num = %d;\
  865. var line_width = %d;\
  866. var stroke_color = \"%s\";\
  867. var stroke_opacity = %f;\
  868. var use_dashed = %d;\
  869. var dashtype0 = %d;\
  870. var dashtype1 = %d;\
  871. var arrow_head = %d;\
  872. var x0,y0;\
  873. var type = %d;\
  874. var use_rotate = 0;var angle = 0;var use_translate = 0 ;var vector = [0,0];\
  875. function user_draw(evt){\
  876. var lu = userdraw_x.length;\
  877. if( lu != 0 && lu%%2 == 0){\
  878.  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]);\
  879. }\
  880. var y = evt.clientY - canvas_rect.top;\
  881. if( y < ysize + 1){\
  882.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  883.  var x = evt.clientX - canvas_rect.left;\
  884.  if( x_use_snap_to_grid == 1 ){\
  885.   x = snap_to_x(x);\
  886.  };\
  887.  if( y_use_snap_to_grid == 1 ){\
  888.   y = snap_to_y(y);\
  889.  };\
  890.  if( evt.which == 1 ){\
  891.   if( lu%%2 == 0){\
  892.    x0 = x;y0 = y;\
  893.    if(num == 1){ userdraw_x = [];userdraw_y = [];userdraw_x[0] = x0;userdraw_y[0] = y0;} else {userdraw_x[lu] = x0;userdraw_y[lu] = y0;}\
  894.    user_drag(evt);\
  895.   }\
  896.   else\
  897.   {\
  898.    if( num == 1 ){ userdraw_x[1] = x;userdraw_y[1] = y;} else {userdraw_x[lu] = x;userdraw_y[lu] = y;};\
  899.    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]);\
  900.   }\
  901.  }\
  902.  else\
  903.  {\
  904.   canvas_remove(x,y);\
  905.  }\
  906. }\
  907. };\
  908. function user_drag(evt){\
  909. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  910. var x = evt.clientX - canvas_rect.left;\
  911. var y = evt.clientY - canvas_rect.top;\
  912. var lu = userdraw_x.length;\
  913. if( x_use_snap_to_grid == 1 ){\
  914.   x = snap_to_x(x);\
  915. };\
  916. if( y_use_snap_to_grid == 1 ){\
  917.   y = snap_to_y(y);\
  918. };\
  919. if( lu%%2 != 0 ){\
  920.  context_userdraw.clearRect(0,0,xsize,ysize);\
  921.  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]);\
  922.  if( lu > 0){\
  923.    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]);\
  924.  }\
  925. }\
  926. };\
  927. function canvas_remove(x,y){\
  928. var marge = 10*line_width;\
  929. for(var p = 0;p < userdraw_x.length ; p++){\
  930.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  931.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  932.    if( confirm(\"remove line ?\" )){\
  933.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  934.     if( p%%2 == 0 ){\
  935.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  936.     }\
  937.     else\
  938.     {\
  939.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  940.     }\
  941.     if(userdraw_x.length < 2){ userdraw_x = [];userdraw_y = [];return;};\
  942.     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]);\
  943.    }\
  944.    return;\
  945.   }\
  946.  }\
  947. }\
  948. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,arrow_head,type);
  949.  
  950. }
  951.  
  952. 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){
  953. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  954. var path_cnt = 0;\
  955. temp_x = [];\
  956. temp_y = [];\
  957. var num = %d;\
  958. xy_cnt=0;\
  959. var line_width = %d;\
  960. var stroke_color = \"%s\";\
  961. var stroke_opacity = %f;\
  962. var fill_color = \"%s\";\
  963. var fill_opacity = %f;\
  964. var use_filled = %d;\
  965. var use_dashed = %d;\
  966. var dashtype0 = %d;\
  967. var dashtype1 = %d;\
  968. var closed_path = 0;\
  969. var click_cnt=0;\
  970. var x0,y0;\
  971. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  972. function user_draw(evt){\
  973. if(evt.which == 1 ){\
  974.  if( click_cnt == 0 ){\
  975.   click_cnt = 1;\
  976.   user_drag(evt);\
  977.  }\
  978.  else\
  979.  {\
  980.   userdraw_x[path_cnt] = new Array();\
  981.   userdraw_y[path_cnt] = new Array();\
  982.   userdraw_x[path_cnt] = temp_x;\
  983.   userdraw_y[path_cnt] = temp_y;\
  984.   path_cnt++;\
  985.   temp_x = [];\
  986.   temp_y = [];\
  987.   click_cnt = 0;\
  988.   xy_cnt = 0;\
  989.  };\
  990. }\
  991. else\
  992. {\
  993.   canvas_remove(evt.clientX - canvas_rect.left,evt.clientY - canvas_rect.top);\
  994. };\
  995. context_userdraw.clearRect(0,0,xsize,ysize);\
  996. for(var p=0; p < path_cnt; p++){\
  997.  if(userdraw_x[p] != null){\
  998.   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);\
  999.  };\
  1000. };\
  1001. };\
  1002. function user_drag(evt){\
  1003. if(click_cnt == 1 ){\
  1004.  temp_y[xy_cnt] = evt.clientY - canvas_rect.top;\
  1005.  if( temp_y[xy_cnt] < ysize + 1){\
  1006.   temp_x[xy_cnt] = evt.clientX - canvas_rect.left;\
  1007.   if( x_use_snap_to_grid == 1 ){\
  1008.    temp_x[xy_cnt] = snap_to_x(temp_x[xy_cnt]);\
  1009.   };\
  1010.   if( y_use_snap_to_grid == 1 ){\
  1011.    temp_y[xy_cnt] = snap_to_y(temp_y[xy_cnt]);\
  1012.   };\
  1013.   xy_cnt++;\
  1014.   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);\
  1015.  };\
  1016. };\
  1017. };\
  1018. function canvas_remove(x,y){\
  1019. var marge = 4*line_width;\
  1020. var tmpx = [];\
  1021. var tmpy = [];\
  1022. for(var i = 0 ; i < path_cnt; i++){\
  1023.  tmpx = userdraw_x[i];\
  1024.  if(tmpx != null){\
  1025.   tmpy = userdraw_y[i];\
  1026.   for(var p = 0;p<tmpx.length;p++){\
  1027.    if( x + marge > tmpx[p] &&  x - marge < tmpx[p] ){\
  1028.     if( y + marge > tmpy[p] &&  y - marge < tmpy[p] ){\
  1029.      if(confirm(\"Remove this drawing ?\")){\
  1030.       userdraw_x[i] = null;\
  1031.       userdraw_y[i] = null;\
  1032.       xy_cnt = 0;click_cnt = 0;\
  1033.       return;\
  1034.      };\
  1035.     };\
  1036.    };\
  1037.   };\
  1038.  };\
  1039. };\
  1040. };",draw_type,num,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1);
  1041. }
  1042.  
  1043. void add_js_tooltip(int canvas_root_id,char *tooltip_text,char *bgcolor,int xsize,int ysize){
  1044. fprintf(stdout,"\n<!-- begin command intooltip %d -->\n\
  1045. <script type=\"text/javascript\">\n\
  1046. var xsize = %d;\
  1047. var ysize = %d;\
  1048. var tooltip%d_obj_x = 0;\
  1049. var tooltip%d_obj_y = 0;\
  1050. var tooltip%d_flipflop = 0;\
  1051. var tooltip%d_obj = document.getElementById(\"canvas_div%d\");\
  1052. tooltip%d_obj.style.display=\"none\";\
  1053. tooltip%d_obj.style.position=\"absolute\";\
  1054. var tooltip%d_link = document.createElement(\"a\");\
  1055. tooltip%d_link.addEventListener(\"mousemove\",tooltip%d_drag,false);\
  1056. tooltip%d_link.setAttribute(\"onclick\",\"tooltip%d_show()\");\
  1057. tooltip%d_link.innerHTML  = \"%s\";\
  1058. var tooltip_placeholder = document.getElementById(\"tooltip_placeholder%d\");\
  1059. tooltip_placeholder.style.display=\"block\";\
  1060. tooltip_placeholder.style.position=\"absolute\";\
  1061. tooltip_placeholder.style.backgroundColor=\"%s\";\
  1062. tooltip_placeholder.appendChild(tooltip%d_link);\
  1063. function tooltip%d_drag(action){\
  1064. if(!action){ action = event; }\
  1065. if(action.clientX){\
  1066.  tooltip%d_obj.style.left = (tooltip%d_mouseX(action) + 10) +\"px\";\
  1067.  var ytop = tooltip%d_mouseY(action);\
  1068.  if(ytop + ysize < window.innerHeight){\
  1069.   tooltip%d_obj.style.top = (ytop - 10) +\"px\";\
  1070.  }\
  1071.  else\
  1072.  {\
  1073.   tooltip%d_obj.style.top = parseInt(ytop - 0.8*ysize) +\"px\";\
  1074.  }\
  1075. }\
  1076. else\
  1077. {\
  1078.  return null;\
  1079. }\
  1080. }\
  1081. function tooltip%d_mouseX(action){\
  1082. if(action.pageX){\
  1083.  return action.pageX;\
  1084. }\
  1085. else\
  1086. {\
  1087.  if(action.clientX){\
  1088.   return action.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);\
  1089.  }\
  1090.  else\
  1091.  {\
  1092.   return null;\
  1093.  }\
  1094. }\
  1095. }\
  1096. function tooltip%d_mouseY(action){\
  1097. if(action.pageY){\
  1098.  return action.pageY;\
  1099. }\
  1100. else\
  1101. {\
  1102.  if(action.clientY){\
  1103.   return action.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop :document.body.scrollTop);\
  1104.  }\
  1105.  else\
  1106.  {\
  1107.   return null;\
  1108.  }\
  1109. }\
  1110. }\
  1111. function tooltip%d_show(){\
  1112. if(tooltip%d_flipflop == 0){\
  1113.  tooltip%d_obj.style.display = \"block\";\
  1114.  tooltip%d_flipflop = 1;\
  1115. }\
  1116. else\
  1117. {\
  1118.  tooltip%d_flipflop = 0;\
  1119.  tooltip%d_obj.style.display = \"none\";\
  1120. }\
  1121. };\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);
  1122.  
  1123. }
  1124.  
  1125. 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){
  1126. fprintf(js_include_file,"\n<!-- begin userdraw \"arc\" on final canvas -->\n\
  1127. var canvas_rect = canvas_userdraw.getBoundingClientRect();\n\
  1128. function user_draw(evt){\
  1129. var num = %d;\
  1130. var x,xc,x1,x2,y,yc,y1,y2;var lu = userdraw_x.length;\
  1131. if( num == 1 && lu == 3 ){ userdraw_x = [];userdraw_y = [];userdraw_radius = [];};\
  1132. if(evt.which == 1){\
  1133.  x = evt.clientX - canvas_rect.left;\
  1134.  y = evt.clientY - canvas_rect.top;\
  1135.  if( x_use_snap_to_grid == 1 ){x = snap_to_x(x);};\
  1136.  if( y_use_snap_to_grid == 1 ){y = snap_to_y(y);};\
  1137.  if(num == 1 && lu == 3){userdraw_x = [];userdraw_y = [];userdraw_radius = [];};\
  1138.  lu = userdraw_x.push(x);userdraw_y.push(y);\
  1139.  if( lu != 0 && lu%%3 == 0){\
  1140.   context_userdraw.clearRect(0,0,xsize,ysize);\
  1141.   userdraw_radius = [];\
  1142.   for(var p = 0 ; p < lu; p = p + 3){\
  1143.     xc = userdraw_x[p];\
  1144.     yc = userdraw_y[p];\
  1145.     x1 = userdraw_x[p+1];\
  1146.     x2 = userdraw_x[p+2];\
  1147.     y1 = userdraw_y[p+1];\
  1148.     y2 = userdraw_y[p+2];\
  1149.     draw_userarc(context_userdraw,xc,yc,x1,y1,x2,y2,%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d);\
  1150.   };\
  1151.  };\
  1152. }\
  1153. else\
  1154. {\
  1155.  if( confirm(\"remove drawing ?\") ){\
  1156.   context_userdraw.clearRect(0,0,xsize,ysize);userdraw_x = [];userdraw_y = [];userdraw_radius = [];return;\
  1157.  };\
  1158. };\
  1159. };\
  1160. function user_drag(evt){ \
  1161. var lu = userdraw_x.length;\
  1162. if( (lu+1)%%3 == 0) {\
  1163.  var x2 = evt.clientX - canvas_rect.left;\
  1164.  var y2 = evt.clientY - canvas_rect.top;\
  1165.  var xc = userdraw_x[lu-2];\
  1166.  var yc = userdraw_y[lu-2];\
  1167.  var x1 = userdraw_x[lu-1];\
  1168.  var y1 = userdraw_y[lu-1];\
  1169.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1170.  draw_userarc(context_userdraw,xc,yc,x1,y1,x2,y2,1,\"255,0,0\",0.6,\"255,255,0\",0.4,0,2,2);\
  1171. };\
  1172. return;\
  1173. };\
  1174. 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){\
  1175. ctx.save();\
  1176. if( use_dashed == 1){if(ctx.setLineDash){ctx.setLineDash([dashtype0,dashtype1]);}else{if(ctx.mozDash){ ctx.mozDash = [dashtype0,dashtype1];};};};\
  1177. ctx.lineWidth = line_width;\
  1178. ctx.strokeStyle =  \"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  1179. ctx.fillStyle = \"rgba(\"+fill_color+\",\"+fill_opacity+\")\";\
  1180. var alpha = find_angle(xc,yc,x1,y1,x2,y2);\
  1181. if( %d == 1 ){userdraw_radius[0] = alpha;ctx.clearRect(0,0,xsize,ysize);}else{userdraw_radius.push(alpha);};\
  1182. var r = Math.sqrt(Math.pow(xc-x2,2)+Math.pow(yc-y2,2));\
  1183. var start;var tmp;var beta;\
  1184. if( x1 > x2 ){\
  1185.  tmp = x2; x2 = x1 ; x1 = tmp;\
  1186.  tmp = y2; y2 = y1 ; y1 = tmp;\
  1187. };\
  1188. if( y1 < yc ){\
  1189.  beta = find_angle(xc,yc,x1,yc,x1,y1);\
  1190.   if( x1 < xc ){\
  1191.    start = Math.PI + beta;\
  1192.   }\
  1193.   else\
  1194.   {\
  1195.    start = 2*Math.PI - beta;\
  1196.   }\
  1197. }\
  1198. else\
  1199. {\
  1200.  beta = find_angle(xc,yc,x2,yc,x2,y2);\
  1201.  if(x2 > xc){\
  1202.   start = beta;\
  1203.  }\
  1204.  else\
  1205.  {\
  1206.   start = Math.PI - beta;\
  1207.  }\
  1208. };\
  1209. ctx.translate(xc,yc);\
  1210. ctx.rotate(start);\
  1211. ctx.beginPath();\
  1212. ctx.arc(0,0,r,0,alpha,false);\
  1213. ctx.lineTo(0,0);\
  1214. ctx.closePath();\
  1215. ctx.fill();\
  1216. ctx.stroke();\
  1217. ctx.restore();\
  1218. };\
  1219. function find_angle(xc,yc,x1,y1,x2,y2){\
  1220. var a = Math.sqrt(Math.pow(xc-x1,2)+Math.pow(yc-y1,2));\
  1221. var b = Math.sqrt(Math.pow(xc-x2,2)+Math.pow(yc-y2,2));\
  1222. var c = Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2));\
  1223. return Math.acos((b*b+a*a-c*c)/(2*b*a));\
  1224. };",num,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,num);
  1225. }
  1226.  
  1227. void add_js_text(FILE *js_include_file,int canvas_root_id,int font_size,char *font_family,char *font_color,double stroke_opacity){
  1228. fprintf(js_include_file,"\n<!-- begin command userdraw text -->\n\
  1229. canvas_div.addEventListener(\"keydown\",user_text,false);\
  1230. var context_userdraw = canvas_userdraw.getContext(\"2d\");\
  1231. var font_color = \"%s\";\
  1232. var font_opacity = %f;\
  1233. var font_size = %d;\
  1234. var font_family = \"%s\";\
  1235. context_userdraw.fillStyle = \"rgba(\"+font_color+\",\"+font_opacity+\")\";\
  1236. context_userdraw.font = font_family;\
  1237. var userdraw_text = new Array();\
  1238. var txt_cnt = 0;\
  1239. var txt=\"\";\
  1240. var x_txt = 0;\
  1241. var y_txt = 0;\
  1242. var w_txt = 0;\
  1243. var typing = 0;\
  1244. var canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1245. function user_draw(evt){\
  1246. y_txt = evt.clientY - canvas_rect.top;\
  1247. x_txt = evt.clientX - canvas_rect.left;\
  1248. if( x_use_snap_to_grid == 1 ){\
  1249.   x_txt = snap_to_x(x_txt);\
  1250. };\
  1251. if( y_use_snap_to_grid == 1 ){\
  1252.   y_txt = snap_to_y(y_txt);\
  1253. };\
  1254. return;\
  1255. };\
  1256. function user_drag(evt){\
  1257. return;\
  1258. };\
  1259. function user_text(evt){\
  1260. var kc = evt.keyCode;var w;\
  1261. if( kc== 8 || kc == 27 || kc == 46 ){\
  1262.  if(typing == 1 ){\
  1263.    w = context_userdraw.measureText(txt).width;\
  1264.    context_userdraw.clearRect(x_txt-2,y_txt-font_size-2,w+2,font_size+2);\
  1265.    txt = \"\";\
  1266.  }\
  1267.  else\
  1268.  {\
  1269.   for( var p=0 ; p < txt_cnt; p++){\
  1270.    var tmp = (userdraw_text[p]).split(\":\");\
  1271.    w = context_userdraw.measureText(tmp[0]).width;\
  1272.    var y1 = y_txt - font_size;\
  1273.    var y2 = y_txt + font_size;\
  1274.    if( tmp[1] < y2 && tmp[1] > y1){\
  1275.     var x1 = x_txt - font_size;\
  1276.     var x2 = x_txt + w;\
  1277.     if( tmp[0] < x2 && tmp[0] > x1){\
  1278.      if (confirm(\"delete this text : \"+tmp[2]+\"?\")){\
  1279.       context_userdraw.clearRect(x1,y1,x2,y2);\
  1280.       userdraw_text.splice(p,1);\
  1281.       txt_cnt--;\
  1282.       return;\
  1283.      };\
  1284.     };\
  1285.    };\
  1286.   };\
  1287.  };\
  1288. }\
  1289. else\
  1290. {\
  1291.  if( kc < 126 && kc > 40 ){\
  1292.   typing = 1;\
  1293.   txt=txt+String.fromCharCode(kc);\
  1294.   w = context_userdraw.measureText(txt).width;\
  1295.   context_userdraw.save();\
  1296.   context_userdraw.fillStyle = \"lightblue\";\
  1297.   context_userdraw.beginPath();\
  1298.   context_userdraw.rect(x_txt,y_txt-font_size,w,font_size);\
  1299.   context_userdraw.closePath();\
  1300.   context_userdraw.fill();\
  1301.   context_userdraw.restore();\
  1302.   context_userdraw.fillText(txt,x_txt,y_txt);\
  1303.  }\
  1304.  else\
  1305.  {\
  1306.   if(kc == 13 ){\
  1307.    w = context_userdraw.measureText(txt).width;\
  1308.    if(w < 1){alert(\"nothing typed...try again\");return;};\
  1309.    context_userdraw.clearRect(x_txt,y_txt-font_size,w,font_size);\
  1310.    context_userdraw.fillText(txt,x_txt,y_txt);\
  1311.    userdraw_text[txt_cnt] = Math.round(x_txt)+\":\"+Math.round(y_txt)+\":\"+txt;\
  1312.    txt=\"\";\
  1313.    w = 0;\
  1314.    txt_cnt++;\
  1315.    typing = 0;\
  1316.    return;\
  1317.   };\
  1318.  };\
  1319. };\
  1320. };",font_color,stroke_opacity,font_size,font_family);
  1321.  
  1322. }
  1323.  
  1324. /*
  1325.  
  1326. type = 0 : x-values only [command mousex]
  1327. type = 1 : y-values only [command mousey]
  1328. type = 2 : (x:y)         [command mouse]
  1329. type = 3 : degrees       [command mouse_degree]
  1330. */
  1331. 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){
  1332. fprintf(js_include_file,"\n<!-- begin command mouse on current canvas -->\n\
  1333. function use_mouse_coordinates(){\
  1334. var type = %d;\
  1335. var current_canvas = create_canvas%d(%d,xsize,ysize);\
  1336. var current_context = current_canvas.getContext(\"2d\");\
  1337. current_context.clearRect(0,0,xsize,ysize);\
  1338. current_canvas.addEventListener(\"mousemove\",show_coordinate%d,false);\
  1339. current_canvas.addEventListener(\"touchmove\",show_coordinate%d,false);\
  1340. var prec = Math.log(%d)/(Math.log(10));\
  1341. function show_coordinate%d(evt){\
  1342.  var canvas_rect = (current_canvas).getBoundingClientRect();\
  1343.  var x = evt.clientX - canvas_rect.left;\
  1344.  var y = evt.clientY - canvas_rect.top;\
  1345.  var m_data = \"\";var l = userdraw_x.length;\
  1346.  switch(type){\
  1347.   case 0: m_data = \" \"+(px2x(x)).toFixed(prec)+\" \"+unit_x;break;\
  1348.   case 1: m_data = \" \"+(px2y(y)).toFixed(prec)+\" \"+unit_y;break;\
  1349.   case 2: m_data = \"(\"+(px2x(x)).toFixed(prec)+\":\"+(px2y(y)).toFixed(prec)+\")\";break;\
  1350.   case 3: m_data = \" \"+( ( Math.atan( ((xmax - xmin)*(px2y(y))) / ((ymax - ymin)*(px2x(x))) ) )/(Math.PI/180) ).toFixed(prec)+\" \\u00B0 \";break;\
  1351.   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;\
  1352.   default:break;\
  1353.  };\
  1354.  var s = parseInt(0.8*%d*(m_data.toString()).length);\
  1355.  current_context.font = \"%dpx Ariel\";\
  1356.  current_context.fillStyle = \"rgba(%s,%f)\";\
  1357.  current_context.clearRect(0,0,s,1.2*%d);\
  1358.  current_context.fillText(m_data,0,%d);\
  1359. };\
  1360. };",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);
  1361. }
  1362. /* to avoid easy js-code injection...but is it a real problem ? */
  1363. void add_safe_eval(FILE *js_include_file){
  1364. fprintf(js_include_file," \nfunction safe_eval(exp){\
  1365. if(exp.indexOf('^') != -1){\
  1366.  exp = exp.replace(/[a-zA-Z]/g,' ');\
  1367.  exp = exp.replace(/\\*10\\^-/g,'e-');\
  1368.  exp = exp.replace(/\\*10\\^/g,'e+');\
  1369.  exp = exp.replace(/10\\^-/g,'1e-');exp = exp.replace(/10\\^/g,'1e+');\
  1370.  exp = eval(exp);\
  1371.  if(isNaN(exp)){alert(\"invalid input\\ntry just a real number \\ne.g. no calculations...\");return null;}\
  1372.  return exp;\
  1373. };\
  1374. var reg = /(?:[a-z$_][a-z0-9$_]*)|(?:[;={}\\[\\]\"'!&<>^\\\\?:])/ig;\
  1375. var valid = true;\
  1376. exp = exp.replace(reg,function($0){\
  1377.  if(Math.hasOwnProperty($0)){\
  1378.   return \"Math.\"+$0;\
  1379.  }\
  1380.  else\
  1381.  {\
  1382.   valid = false;\
  1383.  }\
  1384. }\
  1385. );\
  1386. if( !valid ){\
  1387.  alert(\"hmmm \"+exp+\" ?\"); exp = null;\
  1388. }\
  1389. else\
  1390. {\
  1391.  try{ exp = eval(exp); } catch(e){alert(\"Invalid arithmetic expression\"); exp = null;};\
  1392. };\
  1393. return exp;\
  1394. };");
  1395. }
  1396.  
  1397. /*
  1398. add display of slider value in mouse context
  1399. use_slider_display = 1 : x or x/y
  1400. use_slider_display = 2 : angle in degrees
  1401. use_slider_display = 3 : angle in radians
  1402. */
  1403. void add_slider_display(FILE *js_include_file,int canvas_root_id,int precision,int font_size,char *font_color,double stroke_opacity){
  1404. fprintf(js_include_file,"<!-- begin add_slider_display -->\n\
  1405. function show_slider_value(value,use_slider_display){\
  1406. var current_canvas = create_canvas%d(%d,xsize,ysize);\
  1407. var current_context = current_canvas.getContext(\"2d\");\
  1408. current_context.clearRect(0,0,xsize,ysize);\
  1409. var prec = Math.log(%d)/(Math.log(10));\
  1410. var string;\
  1411. if(value.length == 2){\
  1412.  string = \" \"+value[0].toFixed(prec)+\" \"+unit_x+\":\"+value[1].toFixed(prec)+\" \"+unit_y;\
  1413. }else{\
  1414.  if(use_slider_display == 2){\
  1415.   value[0] = value[0]*180/Math.PI;\
  1416.   string = \" \"+value[0].toFixed(prec)+\"\\u00B0\";\
  1417.  }else{\
  1418.   if(use_slider_display == 3){\
  1419.    string = \" \"+value[0].toFixed(prec)+\"\\u03C0 rad\";\
  1420.   };\
  1421.  };\
  1422. };\
  1423. var s = parseInt(1.2*%d*(string).length);\
  1424. current_context.font = \"%dpx Ariel\";\
  1425. current_context.strokeStyle = \"rgba(%s,%.2f)\";\
  1426. current_context.clearRect(0,0,s,1.2*%d);\
  1427. current_context.fillText(string,0,%d);\
  1428. };\n",canvas_root_id,MOUSE_CANVAS,precision,font_size,font_size,font_color,stroke_opacity,font_size,font_size);
  1429. }
  1430. /*
  1431. add slider
  1432. return value is array : value[0] is the actual value between value_1 and value_2
  1433. */
  1434. 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){
  1435. fprintf(js_include_file,"\n<!-- begin add_slider no. %d -->\n\
  1436. function add_slider_%d(){\
  1437. if( wims_status == \"done\" ){return;};\
  1438. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1439. var slider_type = %d;\
  1440. var span = document.createElement(\"span\");\
  1441. span.style= \"font:%s;color:%s\";\
  1442. var title = document.createTextNode(\" %s \");\
  1443. var br = document.createElement(\"br\");\
  1444. span.appendChild(title);\
  1445. span.appendChild(br);\
  1446. tooltip_div.appendChild(span);\
  1447. var slider_fillcolor = \"%s\";\
  1448. var slider_strokecolor = \"%s\";\
  1449. var slider_linewidth = \"%d\";\
  1450. var slider_canvas = document.createElement(\"canvas\");\
  1451. slider_canvas.id = \"slider_canvas%d\";\
  1452. tooltip_div.appendChild(slider_canvas);\
  1453. br = document.createElement(\"br\");\
  1454. tooltip_div.appendChild(br);\
  1455. var slider_width = %d;\
  1456. var slider_height = %d;\
  1457. var slider_center = %d;\
  1458. var slider_radius = 4*slider_linewidth;\
  1459. var slider_opacity = %f;\
  1460. slider_canvas.width = slider_width;\
  1461. slider_canvas.height = slider_height;\
  1462. var canvas_rect = (slider_canvas).getBoundingClientRect();\
  1463. var slider_ctx = slider_canvas.getContext(\"2d\");\
  1464. slider_ctx.font = \"%s\";\
  1465. slider_ctx.strokeStyle = \"rgba(\"+slider_strokecolor+\",\"+slider_opacity+\")\";\
  1466. slider_ctx.fillStyle = \"rgba(\"+slider_fillcolor+\",\"+slider_opacity+\")\";\
  1467. slider_ctx.lineWidth = slider_linewidth;\
  1468. slider_ctx.beginPath();\
  1469. slider_ctx.arc(10,slider_center,slider_radius,0,2*Math.PI,false);\
  1470. slider_ctx.moveTo(10,slider_center);\
  1471. slider_ctx.lineTo(slider_width-10,slider_center);\
  1472. slider_ctx.rect(0,0,slider_width,slider_height);\
  1473. slider_ctx.closePath();\
  1474. slider_ctx.fill();\
  1475. slider_ctx.stroke();\
  1476. slider_canvas.addEventListener(\"mousemove\",slider_%d,false);\
  1477. function slider_%d(evt){\
  1478. var value_1 = %f;\
  1479. var value_2 = %f;\
  1480. slider_ctx.clearRect(0,0,slider_width,slider_height);\
  1481. var x = evt.clientX - canvas_rect.left;\
  1482. var value = x*(value_2 - value_1)/slider_width + value_1;\
  1483. slider_ctx.beginPath();\
  1484. slider_ctx.arc(x,slider_center,slider_radius,0,2*Math.PI,false);\
  1485. slider_ctx.moveTo(10,slider_center);\
  1486. slider_ctx.lineTo(slider_width-10,slider_center);\
  1487. slider_ctx.rect(0,0,slider_width,slider_height);\
  1488. slider_ctx.closePath();\
  1489. slider_ctx.fill();\
  1490. slider_ctx.stroke();\
  1491. dragstuff.Slide( [value] , %d );\
  1492. if(%d != 0 ){show_slider_value([value],%d);}\
  1493. return;\
  1494. };\
  1495. };\
  1496. add_slider_%d();",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);
  1497. }
  1498.  
  1499.  
  1500. /*
  1501. add xyslider
  1502.  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
  1503. */
  1504. 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){
  1505. fprintf(js_include_file,"\n<!-- begin add_slider no. %d -->\n\
  1506. function add_slider_%d(){\
  1507. if( wims_status == \"done\" ){return;};\
  1508. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1509. var slider_type = %d;\
  1510. var span = document.createElement(\"span\");\
  1511. span.style= \"font:%s;color:%s\";\
  1512. var title = document.createTextNode(\" %s \");\
  1513. var br = document.createElement(\"br\");\
  1514. span.appendChild(title);\
  1515. span.appendChild(br);\
  1516. tooltip_div.appendChild(span);\
  1517. var slider_fillcolor = \"%s\";\
  1518. var slider_click = 0;\
  1519. var slider_strokecolor = \"%s\";\
  1520. var slider_linewidth = \"%d\";\
  1521. var slider_canvas = document.createElement(\"canvas\");\
  1522. slider_canvas.id = \"slider_canvas%d\";\
  1523. tooltip_div.appendChild(slider_canvas);\
  1524. br = document.createElement(\"br\");\
  1525. tooltip_div.appendChild(br);\
  1526. var slider_width = %d;\
  1527. var slider_height = %d;\
  1528. var slider_center = %d;\
  1529. var slider_radius = 4*slider_linewidth;\
  1530. var slider_opacity = %f;\
  1531. slider_canvas.width = slider_width;\
  1532. slider_canvas.height = slider_height;\
  1533. var canvas_rect = (slider_canvas).getBoundingClientRect();\
  1534. var slider_ctx = slider_canvas.getContext(\"2d\");\
  1535. slider_ctx.font = \"%s\";\
  1536. slider_ctx.strokeStyle = \"rgba(\"+slider_strokecolor+\",\"+slider_opacity+\")\";\
  1537. slider_ctx.fillStyle = \"rgba(\"+slider_fillcolor+\",\"+slider_opacity+\")\";\
  1538. slider_ctx.lineWidth = slider_linewidth;\
  1539. slider_ctx.beginPath();\
  1540. slider_ctx.arc(10,slider_center,slider_radius,0,2*Math.PI,false);\
  1541. slider_ctx.fill();\
  1542. slider_ctx.closePath();\
  1543. slider_ctx.rect(0,0,slider_width,slider_height);\
  1544. slider_ctx.stroke();\
  1545. slider_canvas.addEventListener(\"mousemove\",sliderdrag_%d,false);\
  1546. slider_canvas.addEventListener(\"mousedown\",sliderclick_%d,false);\
  1547. function sliderdrag_%d(evt){\
  1548. if(slider_click == 1){\
  1549.  var value_1 = %f;\
  1550.  var value_2 = %f;\
  1551.  var canvas_rect = (slider_canvas).getBoundingClientRect();\
  1552.  slider_ctx.clearRect(0,0,slider_width,slider_height);\
  1553.  var x = evt.clientX - canvas_rect.left;\
  1554.  var y = evt.clientY - canvas_rect.top;\
  1555.  var value_x = x*(value_2 - value_1)/slider_width + value_1;\
  1556.  var value_y = y*(value_2 - value_1)/slider_height + value_1;\
  1557.  slider_ctx.beginPath();\
  1558.  slider_ctx.arc(x,y,slider_radius,0,2*Math.PI,false);\
  1559.  slider_ctx.fill();\
  1560.  slider_ctx.rect(0,0,slider_width,slider_height);\
  1561.  slider_ctx.closePath();\
  1562.  slider_ctx.stroke();\
  1563.  dragstuff.Slide( [value_x,1-1*value_y] , %d );\
  1564.  if(%d != 0 ){show_slider_value([value_x,value_y],%d);}\
  1565. };\
  1566. };\
  1567. function sliderclick_%d(evt){\
  1568.  if(slider_click == 1){slider_click = 0;}else{slider_click = 1;};\
  1569. };\
  1570. };\
  1571. add_slider_%d();",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,slider_cnt,v1,v2,slider_cnt,use_slider_display,use_slider_display,slider_cnt,slider_cnt);
  1572. }
  1573.  
  1574.  
  1575. /*
  1576. adds inputfield for x-value: returns the js-calculated y-value after click on 'OK' button
  1577. draws a non-configurable crosshair on this calculated location
  1578. */
  1579. void add_calc_y(FILE *js_include_file,int canvas_root_id,char *jsmath){
  1580. fprintf(js_include_file,"\n<!-- begin add_calc_y -->\n\
  1581. use_jsmath=1;\
  1582. function add_calc_y(){\
  1583. if( wims_status == \"done\" ){return;};\
  1584. var fun = to_js_math(\"%s\");if(fun == null){return;};\
  1585. function eval_jsmath(x){return parseFloat(eval(fun));};\
  1586. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1587. var calc_div = document.createElement('div');\
  1588. calc_div.id = \"calc_div\";\
  1589. tooltip_div.appendChild(calc_div);\
  1590. var label_x = \"x\";var label_y = \"y\";\
  1591. if( typeof xaxislabel !== 'undefined' ){label_x = xaxislabel;}\
  1592. if( typeof yaxislabel !== 'undefined' ){label_y = yaxislabel;}\
  1593. calc_div.innerHTML=\"<br /><span style='font-style:italic;font-size:10px'>\"+label_x+\" : <input type='text' size='4' value='' id='calc_input_x' style='text-align:center;color:blue;background-color:orange;' />&nbsp;\"+ label_y+\" : <input type='text' size='6' value='' id='calc_output_y' style='text-align:center;color:blue;background-color:lightgreen;' readonly' /><input id='calc_button' type='button' value='OK' onclick=''  style='color:red;background-color:lightblue;' /></span> \";\
  1594. var calc_button = document.getElementById(\"calc_button\");\
  1595. calc_button.addEventListener(\"mousedown\",function(e){var x_value=document.getElementById(\"calc_input_x\").value;\
  1596. var y_value = eval_jsmath(x_value);\
  1597. document.getElementById(\"calc_output_y\").value = y_value;\
  1598. if(isNaN(y_value)){return;};\
  1599. var canvas = create_canvas%d(123,xsize,ysize);\
  1600. var ctx = canvas.getContext(\"2d\");\
  1601. draw_crosshairs(ctx,[x2px(x_value)],[y2px(y_value)],1,5,\"#000000\",1,0,0,0,[0,0]);return;},false);\
  1602. };add_calc_y();",jsmath,canvas_root_id,canvas_root_id);
  1603. }
  1604. /*
  1605.  x-value of the mouse will be used to calculate via javascript the corresponding y-value using the verbatim js-math function
  1606.  a configurable crosshair and vertical/horizontal crosshair lines will be drawn
  1607.  function is called "use_mouse_coordinates() and thus can not be combined with command 'mouse'
  1608. */
  1609. 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){
  1610. fprintf(js_include_file,"\n<!-- begin command add_trace_jsmath  trace_canvas -->\n\
  1611. use_jsmath=1;\
  1612. function use_trace_jsmath(){\
  1613. if( wims_status == \"done\" ){return;};\
  1614. var label_x = \"x\";var label_y = \"y\";\
  1615. if( typeof xaxislabel !== 'undefined' ){label_x = xaxislabel;}\
  1616. if( typeof yaxislabel !== 'undefined' ){label_y = yaxislabel;}\
  1617. var trace_canvas = create_canvas%d(%d,xsize,ysize);\
  1618. var trace_context = trace_canvas.getContext(\"2d\");\
  1619. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1620. var trace_div = document.createElement('div');\
  1621. trace_div.id = \"trace_div\";\
  1622. tooltip_div.appendChild(trace_div);\
  1623. trace_div.innerHTML = \"<br /><span style='font-style:italic;font-size:10px'>\"+label_x+\" : <input type='text' size='4' value='' id='trace_input_x' style='text-align:center;color:blue;background-color:lightgreen;' />\"+label_y+\" : <input type='text' size='6' value='' id='trace_input_y' style='text-align:center;color:blue;background-color:lightgreen;' readonly' /></span> \";\
  1624. canvas_div.addEventListener(\"mousemove\",trace,false);\
  1625. canvas_div.addEventListener(\"touchmove\",trace,false);\
  1626. var fun = to_js_math(\"%s\");if(fun == null){return;};\
  1627. function eval_jsmath(x){return parseFloat(eval(fun));};\
  1628. function trace(evt){\
  1629.  var canvas_rect = (trace_canvas).getBoundingClientRect();\
  1630.  var x_px = evt.clientX - canvas_rect.left;\
  1631.  var x = px2x(x_px);\
  1632.  var y = eval_jsmath(x);\
  1633.  if(isNaN(y)){return;};\
  1634.  var y_px = y2px(y);\
  1635.  trace_context.clearRect(0,0,xsize,ysize);\
  1636.  draw_crosshairs(trace_context,[x_px],[y_px],%d,%d,\"%s\",%f,0,0,0,[0,0]);\
  1637.  document.getElementById(\"trace_input_x\").value = x;\
  1638.  document.getElementById(\"trace_input_y\").value = y;\
  1639. };\
  1640. return;\
  1641. };use_trace_jsmath();",canvas_root_id,canvas_cnt,canvas_root_id,jsmath,line_width,crosshair_size,stroke_color,stroke_opacity);
  1642. }
  1643.  
  1644. /*
  1645. add a table with 2 textarea's labeled 'x' 'y' ( or 'xlabel' 'ylabel' if defined)
  1646. add two buttons: OK and NOK (OK draws; NOK will delete last item pair from userdraw_x / userdraw_y array's
  1647. */
  1648. void add_textarea_xy(FILE *js_include_file, int canvas_root_id){
  1649. fprintf(js_include_file,"\n<!-- begin add_textarea_xy -->\n\
  1650. function add_textarea_xy(){\
  1651. if( wims_status == \"done\" ){return;};\
  1652. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1653. var textarea_div = document.createElement('div');\
  1654. textarea_div.id = \"textarea_div\";\
  1655. tooltip_div.appendChild(textarea_div);\
  1656. var label_x = \"x\";var label_y = \"y\";\
  1657. if( typeof xaxislabel !== 'undefined' ){label_x = xaxislabel;}\
  1658. if( typeof yaxislabel !== 'undefined' ){label_y = yaxislabel;}\
  1659. textarea_div.innerHTML=\"\
  1660. <table style=\'border:1px solid black;background-color:#ffffa0\' >\
  1661. <tr>\
  1662. <td><input id='textarea_ok_button' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;'/></td>\
  1663. <td><input id='textarea_nok_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'/></td>\
  1664. </tr>\
  1665. <tr>\
  1666. <td><em>\"+label_x+\"</em></td>\
  1667. <td><em>\"+label_y+\"</em></td>\
  1668. </tr>\
  1669. <tr>\
  1670. <td><textarea rows='5' cols='2' id='userinput_x' style='text-align:center;color:blue;background-color:orange;' ></textarea></td>\
  1671. <td><textarea rows='5' cols='2' id='userinput_y' style='text-align:center;color:blue;background-color:orange;' ></textarea></td>\
  1672. </tr>\
  1673. </table>\";\
  1674. var textarea_ok_button = document.getElementById(\"textarea_ok_button\");\
  1675. var textarea_nok_button = document.getElementById(\"textarea_nok_button\");\
  1676. textarea_ok_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  1677. textarea_nok_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);\
  1678. return;\
  1679. };add_textarea_xy();",canvas_root_id);
  1680. }
  1681.  
  1682. /*
  1683.  
  1684. */
  1685. void add_setlimits(FILE *js_include_file, int canvas_root_id){
  1686. fprintf(js_include_file,"\n<!-- begin add_setlimits -->\n\
  1687. use_pan_and_zoom = 1;\
  1688. function use_setlimits(){\
  1689. if( wims_status == \"done\" ){return;};\
  1690. var label_x = \"x\";var label_y = \"y\";\
  1691. if( typeof xaxislabel !== 'undefined' ){label_x = xaxislabel;}\
  1692. if( typeof yaxislabel !== 'undefined' ){label_y = yaxislabel;}\
  1693. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1694. var setlim_div = document.createElement('div');\
  1695. setlim_div.id = \"setlim_div\";\
  1696. tooltip_div.appendChild(setlim_div);\
  1697. setlim_div.innerHTML=\"<br /><span style='font-style:italic;font-size:10px'>\"+label_x+\"min = <input type='text' size='4' value='\"+xmin+\"' id='userinput_xmin' style='text-align:center;color:blue;background-color:orange;' /> \"+label_x+\"max = <input type='text' size='4' value='\"+xmax+\"' id='userinput_xmax' style='text-align:center;color:blue;background-color:orange;' /><br />\"+label_y+\"min = <input type='text' size='4' value='\"+ymin+\"' id='userinput_ymin' style='text-align:center;color:blue;background-color:orange;' /> \"+label_y+\"max = <input type='text' size='4' value='\"+ymax+\"' id='userinput_ymax' style='text-align:center;color:blue;background-color:orange;' /><br /><input id='set_limits' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;' />\";\
  1698. var setlimit_button = document.getElementById(\"set_limits\");\
  1699. function set_limits(e){\
  1700. xmin = safe_eval(document.getElementById('userinput_xmin').value);\
  1701. xmax = safe_eval(document.getElementById('userinput_xmax').value);\
  1702. ymin = safe_eval(document.getElementById('userinput_ymin').value);\
  1703. ymax = safe_eval(document.getElementById('userinput_ymax').value);\
  1704. if(xmin > xmax || ymin > ymax){alert(\"your limits are not correct...\");return;}\
  1705. try{start_canvas%d(1234)}catch(e){};try{dragstuff.Zoom(xmin,xmax,ymin,ymax)}catch(e){};return;};\
  1706. setlimit_button.addEventListener(\"mousedown\",function(e){set_limits();},false);\
  1707. };use_setlimits();",canvas_root_id,canvas_root_id);
  1708. }
  1709. /*
  1710. adds 2 inputfields (x:y) and 'ok' | 'nok' button
  1711. these are used for user drawing with inputfields...
  1712. */
  1713.  
  1714. void add_input_xy(FILE *js_include_file, int canvas_root_id){
  1715. fprintf(js_include_file,"\n<!-- begin add_input_xy -->\n\
  1716. function add_input_xy(){\
  1717. if( wims_status == \"done\" ){return;};\
  1718. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1719. var input_xy_div = document.createElement('div');\
  1720. input_xy_div.id = \"input_xy_div\";\
  1721. tooltip_div.appendChild(input_xy_div);\
  1722. var label_x = \"x\";var label_y = \"y\";\
  1723. input_xy_div.innerHTML=\"<br /><span style='font-style:italic;font-size:10px'><b>( <input type='text' size='6' value='' id='userinput_x' style='text-align:center;color:blue;background-color:orange;' /> : <input type='text' size='6' value='' id='userinput_y' style='text-align:center;color:blue;background-color:orange;' /> )</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> \";\
  1724. var update_button = document.getElementById(\"update_button\");\
  1725. var delete_button = document.getElementById(\"delete_button\");\
  1726. update_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  1727. delete_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);\
  1728. };add_input_xy();",canvas_root_id);
  1729. }
  1730.  
  1731. /* adds 4 inputfields (x1:y1) --- (x2:y2) and 'ok' + 'nok' button */
  1732. void add_input_x1y1x2y2(FILE *js_include_file, int canvas_root_id){
  1733. fprintf(js_include_file,"\n<!-- begin add_input_x1y1x2y2 -->\n\
  1734. function add_input_x1y1x2y2(){\
  1735. if( wims_status == \"done\" ){return;};\
  1736. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1737. var input_x1y1x2y2_div = document.createElement('div');\
  1738. input_x1y1x2y2_div.id = \"input_x1y1x2y2_div\";\
  1739. tooltip_div.appendChild(input_x1y1x2y2_div);\
  1740. input_x1y1x2y2_div.innerHTML=\"<br /><span><b>( <input type='text' size='6' value='' id='userinput_x1' style='text-align:center;color:blue;background-color:orange;' /> : <input type='text' size='6' value='' id='userinput_y1' style='text-align:center;color:blue;background-color:orange;' /> ) ----- ( <input type='text' size='6' value='' id='userinput_x2' style='text-align:center;color:blue;background-color:orange;' /> : <input type='text' size='6' value='' id='userinput_y2' style='text-align:center;color:blue;background-color:orange;'/> )</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> \";\
  1741. var update_button = document.getElementById(\"update_button\");\
  1742. var delete_button = document.getElementById(\"delete_button\");\
  1743. update_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  1744. delete_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);\
  1745. };add_input_x1y1x2y2();",canvas_root_id);
  1746. }
  1747.  
  1748. /* adds 3 inputfields Center (x:y) Radius r and 'ok'+'nok' buttons */
  1749. void add_input_xyr(FILE *js_include_file, int canvas_root_id){
  1750. fprintf(js_include_file,"\n<!-- begin add_input_xyr -->\n\
  1751. function add_input_xyr(){\
  1752. if( wims_status == \"done\" ){return;};\
  1753. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1754. var input_xyr_div = document.createElement('div');\
  1755. input_xyr_div.id = \"input_xyr_div\";\
  1756. tooltip_div.appendChild(input_xyr_div);\
  1757. input_xyr_div.innerHTML=\"<br /><span style='font-style:italic;font-size:10px'><b>Center : ( <input type='text' size='6' value='' id='userinput_x' style='text-align:center;color:blue;background-color:orange;' /> : <input type='text' size='6' value='' id='userinput_y' style='text-align:center;color:blue;background-color:orange;' /> ) Radius : <input type='text' size='6' value='' id='userinput_r' style='text-align:center;color:blue;background-color:orange;' /></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> \";\
  1758. var update_button = document.getElementById(\"update_button\");\
  1759. var delete_button = document.getElementById(\"delete_button\");\
  1760. update_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  1761. delete_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);\
  1762. };add_input_xyr();",canvas_root_id);
  1763. }
  1764.  
  1765. /* THESE JS-FUNCTIONS COULD BE MADE LESS COPY & PASTE "PROGRAMMING" */
  1766.  
  1767. /* draw circle(s) / point(s) via 3 inputfields */
  1768. void add_input_circle(FILE *js_include_file,int type,int num){
  1769. /*
  1770. type = 0 : a point ...radius is fixed
  1771. type = 1 : a circle ... read inputfield userinput_r
  1772. num = 1 : a single point / circle
  1773. num = 2 : multiple points / circles
  1774. */
  1775. fprintf(js_include_file,"\n<!-- begin add_input_circle -->\n\
  1776. function user_redraw(t){\
  1777. var type = %d;\
  1778. var num = %d;\
  1779. var lu = userdraw_x.length;\
  1780. if( t == -1 && lu > 0){\
  1781.  userdraw_x.splice(lu-1,1);\
  1782.  userdraw_y.splice(lu-1,1);\
  1783.  if(type == 1){\
  1784.    userdraw_radius.splice(lu-1,1);\
  1785.  };\
  1786.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1787.  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);\
  1788.  return;\
  1789. };\
  1790. var add_x = safe_eval( document.getElementById(\"userinput_x\").value );\
  1791. var add_y = safe_eval( document.getElementById(\"userinput_y\").value );\
  1792. if( add_x != null && add_y != null ){\
  1793.  if( type == 2 ){\
  1794.   var add_r = safe_eval( document.getElementById(\"userinput_r\").value );if( add_r == null ){alert(\"illegal radius input \");return;}\
  1795.   if( num == 1 ){\
  1796.    userdraw_radius[0] = parseInt(Math.abs(xsize*(add_r)/(xmax - xmin)));\
  1797.   }\
  1798.   else\
  1799.   {\
  1800.    userdraw_radius[lu] = parseInt(Math.abs(xsize*(add_r)/(xmax - xmin)));\
  1801.   };\
  1802.  }\
  1803.  else\
  1804.  {\
  1805.    userdraw_radius[lu] = userdraw_radius[0];\
  1806.  };\
  1807.  if( num == 1 ){\
  1808.  userdraw_x[0] = x2px(add_x);\
  1809.  userdraw_y[0] = y2px(add_y);\
  1810.  }\
  1811.  else\
  1812.  {\
  1813.    userdraw_x[lu] = x2px(add_x);\
  1814.    userdraw_y[lu] = y2px(add_y);\
  1815.    xy_cnt++;\
  1816.  };\
  1817.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1818.  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);\
  1819. };\
  1820. return;\
  1821. };",type,num);
  1822. }
  1823. /* draw crosshairs via inputfields x/y */
  1824. void add_input_crosshair(FILE *js_include_file,int num){
  1825. fprintf(js_include_file,"\n<!-- begin add_input_crosshair -->\n\
  1826. function user_redraw(t){\
  1827. var lu = userdraw_x.length;\
  1828. if( t == -1 && lu > 0){\
  1829.  userdraw_x.splice(lu-1,1);\
  1830.  userdraw_y.splice(lu-1,1);\
  1831.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1832.  draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  1833.  return;\
  1834. };\
  1835. var add_x = safe_eval( document.getElementById(\"userinput_x\").value );\
  1836. var add_y = safe_eval( document.getElementById(\"userinput_y\").value );\
  1837. if( add_x != null && add_y != null ){\
  1838.  if( %d == 1 ){\
  1839.   userdraw_x[0] = x2px(add_x);\
  1840.   userdraw_y[0] = y2px(add_y);\
  1841.  }\
  1842.  else\
  1843.  {\
  1844.    userdraw_x[lu] = x2px(add_x);\
  1845.    userdraw_y[lu] = y2px(add_y);\
  1846.    xy_cnt++;\
  1847.  };\
  1848.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1849.  draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  1850. };\
  1851. return;\
  1852. };",num);
  1853. }
  1854.  
  1855. /* draw arrows via inputfields x/y */
  1856. void add_input_arrow(FILE *js_include_file,int num){
  1857. fprintf(js_include_file,"\n<!-- begin add_input_arrow -->\n\
  1858. function user_redraw(t){\
  1859. var lu = userdraw_x.length;\
  1860. if( t == -1 && lu > 1 ){\
  1861.  userdraw_x.splice(lu-2,2);\
  1862.  userdraw_y.splice(lu-2,2);\
  1863.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1864.  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]);\
  1865.  return;\
  1866. };\
  1867. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  1868. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  1869. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  1870. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  1871. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  1872.  if( %d == 2 ){\
  1873.    var s = userdraw_x.length;\
  1874.    userdraw_x[lu] = x2px(add_x1);\
  1875.    userdraw_y[lu] = y2px(add_y1);\
  1876.    userdraw_x[lu+1] = x2px(add_x2);\
  1877.    userdraw_y[lu+1] = y2px(add_y2);\
  1878.  }\
  1879.  else\
  1880.  {\
  1881.   userdraw_x[0] = x2px(add_x1);\
  1882.   userdraw_y[0] = y2px(add_y1);\
  1883.   userdraw_x[1] = x2px(add_x2);\
  1884.   userdraw_y[1] = y2px(add_y2);\
  1885.  };\
  1886.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1887.  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]);\
  1888. };\
  1889. return;\
  1890. };",num);
  1891. }
  1892.  
  1893. /* draw line via inputfields x/y */
  1894. void add_input_line(FILE *js_include_file,int num){
  1895. fprintf(js_include_file,"\n<!-- begin line via inputfields  -->\n\
  1896. function user_redraw(t){\
  1897. var lu = userdraw_x.length;\
  1898. if( t == -1 && lu > 1){\
  1899.  userdraw_x.splice(lu-2,2);\
  1900.  userdraw_y.splice(lu-2,2);\
  1901.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1902.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,1,0,0);\
  1903.  return;\
  1904. };\
  1905. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  1906. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  1907. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  1908. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  1909. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  1910.  if( %d == 2 ){\
  1911.    userdraw_x[lu] = x2px(add_x1);\
  1912.    userdraw_y[lu] = y2px(add_y1);\
  1913.    userdraw_x[lu+1] = x2px(add_x2);\
  1914.    userdraw_y[lu+1] = y2px(add_y2);\
  1915.  }\
  1916.  else\
  1917.  {\
  1918.   userdraw_x[0] = x2px(add_x1);\
  1919.   userdraw_y[0] = y2px(add_y1);\
  1920.   userdraw_x[1] = x2px(add_x2);\
  1921.   userdraw_y[1] = y2px(add_y2);\
  1922.  };\
  1923.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1924.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,1,0,0);\
  1925. };\
  1926. return;\
  1927. };",num);
  1928. }
  1929.  
  1930.  
  1931. /* draw polyline via inputfields x/y */
  1932. void add_input_polyline(FILE *js_include_file){
  1933. fprintf(js_include_file,"\n<!-- begin polyline_segment via inputfields -->\n\
  1934. function user_redraw(t){\
  1935. var lu = userdraw_x.length;\
  1936. cnt = 1;\
  1937. if( t == -1 && lu > 0){\
  1938.  userdraw_x.splice(lu-1,1);\
  1939.  userdraw_y.splice(lu-1,1);\
  1940.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1941.  draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1942.  return;\
  1943. };\
  1944. var add_x = safe_eval( document.getElementById(\"userinput_x\").value );\
  1945. var add_y = safe_eval( document.getElementById(\"userinput_y\").value );\
  1946. if(add_x != null && add_y != null ){\
  1947.  userdraw_x.push(x2px(add_x));\
  1948.  userdraw_y.push(y2px(add_y));\
  1949.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1950.  draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1951. };\
  1952. return;\
  1953. };");
  1954. }
  1955. /* draw segment(s) via inputfields x/y */
  1956. void add_input_segment(FILE *js_include_file,int num){
  1957. fprintf(js_include_file,"\n<!-- begin add_input_segment -->\n\
  1958. function user_redraw(t){\
  1959. var lu = userdraw_x.length;\
  1960. if( t == -1 && lu > 1){\
  1961.  userdraw_x.splice(lu-2,2);\
  1962.  userdraw_y.splice(lu-2,2);\
  1963.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1964.  draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1965.  return;\
  1966. };\
  1967. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  1968. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  1969. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  1970. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  1971. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  1972.  if( %d == 2 ){\
  1973.    var s = userdraw_x.length;\
  1974.    userdraw_x[s] = x2px(add_x1);\
  1975.    userdraw_y[s] = y2px(add_y1);\
  1976.    userdraw_x[s+1] = x2px(add_x2);\
  1977.    userdraw_y[s+1] = y2px(add_y2);\
  1978.  }\
  1979.  else\
  1980.  {\
  1981.   userdraw_x[0] = x2px(add_x1);\
  1982.   userdraw_y[0] = y2px(add_y1);\
  1983.   userdraw_x[1] = x2px(add_x2);\
  1984.   userdraw_y[1] = y2px(add_y2);\
  1985.  };\
  1986.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1987.  draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1988. };\
  1989. return;\
  1990. };",num);
  1991. }
  1992.  
  1993. /* draw polygon via 2 textarea's x/y : split into lines ! */
  1994. void add_textarea_polygon(FILE *js_include_file){
  1995. fprintf(js_include_file,"\n<!-- begin polygon via 2 textareas x / y -->\n\
  1996. function user_redraw(t){\
  1997. var lu = userdraw_x.length;\
  1998. if( t == -1 && lu > 0){\
  1999.  if( lu < 3 ){\
  2000.   userdraw_x = [];\
  2001.   userdraw_y = [];\
  2002.  }\
  2003.  else\
  2004.  {\
  2005.  userdraw_x.splice(lu-1,1);\
  2006.  userdraw_y.splice(lu-1,1);\
  2007.  };\
  2008.  context_userdraw.clearRect(0,0,xsize,ysize);\
  2009.  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]);\
  2010.  cnt = 1; return;\
  2011. };\
  2012. var add_x_values = (document.getElementById(\"userinput_x\").value).split('\\n');\
  2013. var add_y_values = (document.getElementById(\"userinput_y\").value).split('\\n');\
  2014. var lx = add_x_values.length;\
  2015. var ly = add_y_values.length;\
  2016. 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}};\
  2017. var add_x;var add_y;\
  2018. for(var p = 0 ; p < lx ; p++){\
  2019.  add_x = safe_eval( add_x_values[p] );\
  2020.  add_y = safe_eval( add_y_values[p] );\
  2021.  if( add_x == null || add_y == null ){return;};\
  2022.  userdraw_x[lu+p] = x2px(add_x);\
  2023.  userdraw_y[lu+p] = y2px(add_y);\
  2024.  if(p>100){alert(\"hmmmm\");return;};\
  2025. };\
  2026. 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]);\
  2027. cnt = 1;\
  2028. return;\
  2029. };");
  2030. }
  2031.  
  2032. void add_jsplot(FILE *js_include_file,int canvas_root_id){
  2033. fprintf(js_include_file,"\n<!-- begin jsplot() -->\n\
  2034. var jsplot = function(canvas_type,f,linewidth,color,opacity,use_dashed,dashtype0,dashtype1){\
  2035. var obj;\
  2036. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){\
  2037.  obj = document.getElementById(\"wims_canvas%d\"+canvas_type);\
  2038. }\
  2039. else\
  2040. {\
  2041.  obj = create_canvas%d(canvas_type,xsize,ysize);\
  2042. };\
  2043. var ctx = obj.getContext(\"2d\");\
  2044. ctx.clearRect(0,0,xsize,ysize);\
  2045. function eval_jsmath(x){return parseFloat(eval(fun));};\
  2046. var fun = to_js_math(f);if(fun == null){return;};\
  2047. ctx.lineWidth = linewidth;\
  2048. ctx.strokeStyle=\"rgba(\"+color+\",\"+opacity+\")\";\
  2049. if(use_dashed == 1){if(ctx.setLineDash){ctx.setLineDash([dashtype0,dashtype1]);}else{ctx.mozDash =[dashtype0,dashtype1];}};\
  2050. var y1;var x1;var y2;var x2;\
  2051. ctx.beginPath();\
  2052. for(var p=0 ; p<xsize;p++){\
  2053.  x1 = px2x(p);\
  2054.  y1 = y2px(parseFloat(eval_jsmath(x1)));\
  2055.  x2 = px2x(p+1);\
  2056.  y2 = y2px(parseFloat(eval_jsmath(x2)));\
  2057.  if(Math.abs(y2-y1) < ysize ){\
  2058.    ctx.moveTo(p,y1);\
  2059.    ctx.lineTo(p+1,y2);\
  2060.  };\
  2061. };\
  2062. ctx.closePath();\
  2063. ctx.stroke();\
  2064. };",canvas_root_id,canvas_root_id,canvas_root_id);
  2065. }
  2066.  
  2067. void add_to_js_math(FILE *js_include_file){
  2068. fprintf(js_include_file,"\n<!-- begin to_js_math() -->\n\
  2069. var to_js_math = function(math_fun){\
  2070. var infun=[\"sqrt\",\"^\",\"asin\",\"acos\",\"atan\",\"log\",\"pi\",\"abs\",\"sin\",\"cos\",\"tan\",\"e\"];\
  2071. 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)\"];\
  2072. var len = infun.length;var in_fun;var In_Fun;var out_fun;var w_cnt;\
  2073. for(var p=0 ; p < len ; p++){\
  2074.  in_fun = infun[p];In_Fun = in_fun.toUpperCase();out_fun = outfun[p];w_cnt=0;\
  2075.  if(math_fun.indexOf(in_fun) != -1){\
  2076.   if(in_fun == \"^\"){\
  2077.    var tab = [];var small_trick = \"___small_trick___\";\
  2078.    while (math_fun.indexOf(\"(\") != -1){\
  2079.     math_fun = math_fun.replace(/(\\([^\\(\\)]*\\))/g, function(m, t){tab.push(t);return (small_trick + (tab.length - 1));});\
  2080.     w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  2081.    };\
  2082.    tab.push(math_fun);w_cnt = 0;math_fun = small_trick + (tab.length - 1);\
  2083.    while (math_fun.indexOf(small_trick) != -1){\
  2084.     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)\");});\
  2085.     w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  2086.    };\
  2087.   }\
  2088.   else\
  2089.   {\
  2090.    while( math_fun.indexOf(in_fun) != -1 ){\
  2091.     math_fun = math_fun.replace(in_fun,out_fun);\
  2092.     math_fun = math_fun.replace(in_fun,In_Fun);\
  2093.     w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  2094.    };\
  2095.   };\
  2096.  };\
  2097. };\
  2098. for(var p=0 ; p < len ; p++){\
  2099.  in_fun = infun[p];In_Fun = in_fun.toUpperCase();w_cnt = 0;\
  2100.  if(math_fun.indexOf(In_Fun) != -1 ){\
  2101.   while(math_fun.indexOf(In_Fun) != -1){\
  2102.    math_fun = math_fun.replace(In_Fun,in_fun);\
  2103.    w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  2104.   };\
  2105.  };\
  2106. };\
  2107. return math_fun;\
  2108. };\n");
  2109. }
  2110.  
  2111. void add_clear_button(FILE *js_include_file,int canvas_root_id,char *input_style,char *button_text){
  2112. fprintf(js_include_file,"\n<!-- add clear button -->\n\
  2113. clear_draw_area = function(){\
  2114. if(confirm(\"remove all drawings ? \")){\n\
  2115.  var canvas_userdraw = create_canvas%d(%d,xsize,ysize);\n\
  2116.  var context_userdraw = canvas_userdraw.getContext(\"2d\");\n\
  2117.  context_userdraw.clearRect(0,0,xsize,ysize);\n\
  2118.  userdraw_x = [];userdraw_y = [];userdraw_radius = [];\n\
  2119.  return;\n\
  2120. };\n\
  2121. };\n\
  2122. function add_clear_button(){\n\
  2123. var tooltip_placeholder_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  2124. var button = document.createElement('input');\n\
  2125. button.type = \"button\";\n\
  2126. button.style = \"%s\";\n\
  2127. button.value = \"%s\";\n\
  2128. button.setAttribute(\"onclick\",\"clear_draw_area()\");\n\
  2129. tooltip_placeholder_div.appendChild(button);\n\
  2130. };\
  2131. add_clear_button();\n\
  2132. ",canvas_root_id,DRAW_CANVAS,canvas_root_id,input_style,button_text);
  2133. }
  2134.  
  2135.  
  2136. /* GNU libmatheval library for evaluating mathematical functions. */
  2137. char *eval(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int plotsteps,int precision){
  2138.     void *f;
  2139.     double x;
  2140.     double y;
  2141.     int xv;
  2142.     int i = 0;
  2143.     int xstep =(int)(xsize/plotsteps);
  2144.     if( xstep == 0 ){xstep = 1;}
  2145.     double a = (xmax - xmin)/xsize;
  2146.     f = eval_create(fun);
  2147.     assert (f);
  2148.     if( f == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;}
  2149.     /* we supply the true x/y values...draw_curve() will convert these (x:y) to pixels : used for pan/scale */
  2150.     double xydata[MAX_BUFFER+1];/* hmmm */
  2151.     int lim_ymin =(int)( ymin - 4*abs(ymin));
  2152.     int lim_ymax =(int)( ymax + 4*abs(ymax));
  2153.     for ( xv = 0 ;xv < xsize ; xv = xv+xstep ){
  2154.         x = (double) (xv*a + xmin);
  2155.         if( i < MAX_BUFFER - 2){
  2156.             y = eval_x(f, x);
  2157.             if(y < lim_ymax && y > lim_ymin ){
  2158.                 xydata[i++] = x;
  2159.                 xydata[i++] = y;
  2160.             }
  2161.         }
  2162.         else
  2163.         {
  2164.             canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps or some other means to reduce the amount of data... ");
  2165.         }
  2166.     }
  2167.     eval_destroy(f);
  2168.     return double_xy2js_array(xydata,i,find_number_of_digits(precision));
  2169. }
  2170. /* plot a very primitive (!) levelcurve : not to be compared with "flydraw levelcurve" */
  2171. char *eval_levelcurve(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int plotsteps,int precision,double level){
  2172.     void *f = eval_create(fun);
  2173.     assert (f);
  2174.     if( f == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;}
  2175.     double a = (double)((xmax - xmin)/plotsteps);
  2176.     double b = (double)((ymax - ymin)/plotsteps);
  2177.     double x;double y;double diff;
  2178.     double xydata[MAX_BUFFER+1];
  2179.     int i = 0;
  2180.     ymin = ymin - 1;
  2181.     xmin = xmin - 1;
  2182.     ymax = ymax + 1;
  2183.     xmax = xmax + 1;
  2184.     for( x = xmin ;x < xmax ; x = x + a ){
  2185.         for ( y = ymin ;y < ymax ; y = y + b ){
  2186.             if( i < MAX_BUFFER - 2){
  2187.                 diff = level - eval_x_y(f, x,y);
  2188.                 if(diff < 0.1 && diff > -0.1){
  2189.                     xydata[i++] = x;
  2190.                     xydata[i++] = y;
  2191.                 }
  2192.             }
  2193.             else
  2194.             {
  2195.                 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... ");
  2196.             }
  2197.         }
  2198.     }
  2199.     eval_destroy(f);
  2200.     return double_xy2js_array(xydata,i,find_number_of_digits(precision));
  2201. }
  2202.  
  2203. /* plot parametric function */
  2204. char *eval_parametric(int xsize,int ysize,char *fun1,char* fun2,double xmin,double xmax,double ymin,double ymax,        
  2205.  double tmin,double tmax,int plotsteps,int precision){
  2206.     void *fx;
  2207.     void *fy;
  2208.     double t;
  2209.     int i = 0;
  2210.     double tstep = (tmax-tmin)/plotsteps;
  2211.     if( tstep == 0 ){canvas_error("zero step for t variable : reduce plotsteps or inrease trange");}
  2212.     fx = eval_create(fun1);
  2213.     fy = eval_create(fun2);
  2214.     assert(fx);
  2215.     assert(fy);
  2216.     if( fx == NULL || fy == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;}
  2217.     /* we supply the true x/y values...draw_curve() will convert these (x:y) to pixels : used for pan/scale */
  2218.     double xydata[MAX_BUFFER+1];/* hmmm */
  2219.     double x; /* real x-values */
  2220.     double y; /* real y-values */
  2221.     int lim_ymin =(int)( ymin - 4*abs(ymin));
  2222.     int lim_ymax =(int)( ymax + 4*abs(ymax));
  2223.     for( t = tmin ;t <= tmax ; t = t + tstep ){
  2224.         if( i < MAX_BUFFER - 2 ){
  2225.             y = eval_t(fy, t);
  2226.             if(y > lim_ymin && y < lim_ymax){
  2227.                 x = eval_t(fx, t);
  2228.                 xydata[i++] = x;
  2229.                 xydata[i++] = y;
  2230.             }
  2231.         }
  2232.         else
  2233.         {
  2234.             canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps or some other means to reduce the amount of data... ");
  2235.         }
  2236.     }
  2237.     eval_destroy(fx);
  2238.     eval_destroy(fy);
  2239.     return double_xy2js_array(xydata,i,find_number_of_digits(precision));
  2240. }
  2241.  
  2242. char *double_xy2js_array(double xy[],int len,int decimals){
  2243.  /*
  2244.     1,2,3,4,5,6,7,8 --> [1,3,5,7],[2,4,6,8]
  2245.     int xy[] is already checked for errors or overflow in "get_real()"
  2246.     just to be sure we double check the size of "temp"
  2247. */
  2248.     char temp[2*MAX_BUFFER], *string;
  2249.     char *tmp = my_newmem(16);/* <= 9999999999999999  */
  2250.     memset(temp,'\0',2*MAX_BUFFER);/* clear memory */
  2251.     int i;int space_left;
  2252.     temp[0] = '[';/* start js-array */
  2253.     for(i = 0; i < len;i = i + 2){ /*  x_points[] */
  2254.         if(i == len - 2){sprintf(tmp, "%.*f",decimals, xy[i]);}else{sprintf(tmp, "%.*f,",decimals,xy[i]);}
  2255.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  2256.         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 ");}
  2257.     }
  2258.     strncat(temp,"],[",3); /* close js x_values array and start new */
  2259.     for(i = 1; i < len;i = i + 2){ /* y_points */
  2260.         if(i == len - 1){ sprintf(tmp, "%.*f",decimals,xy[i]);}else{sprintf(tmp, "%.*f,",decimals,xy[i]);}
  2261.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  2262.         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");}
  2263.     }
  2264.     strncat(temp,"]",1);
  2265.     string=(char *)my_newmem(sizeof(temp));
  2266.     snprintf(string,sizeof(temp),"%s",temp);
  2267.     return string;
  2268. }
  2269.  
  2270. char *xy2js_array(int xy[],int len){
  2271.  /*
  2272.     1,2,3,4,5,6,7,8 --> [1,3,5,7],[2,4,6,8]
  2273.     int xy[] is already checked for errors or overflow in "get_real()"
  2274.     just to be sure we double check the size of "temp"
  2275. */
  2276.     char temp[MAX_BUFFER], *string;
  2277.     char *tmp = my_newmem(16);/* <= 9999999999999999  */
  2278.     memset(temp,'\0',MAX_BUFFER);/* clear memory */
  2279.     int i;int space_left;
  2280.     temp[0] = '[';/* start js-array */
  2281.     for(i = 0; i < len;i = i + 2){ /*  x_points[] */
  2282.         if(i == len - 2){sprintf(tmp, "%d", xy[i]);}else{sprintf(tmp, "%d,", xy[i]);}
  2283.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  2284.         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 ");}
  2285.     }
  2286.     strncat(temp,"],[",3); /* close js x_values array and start new */
  2287.     for(i = 1; i < len;i = i + 2){ /* y_points */
  2288.         if(i == len - 1){ sprintf(tmp, "%d", xy[i]);}else{sprintf(tmp, "%d,", xy[i]);}
  2289.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  2290.         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");}
  2291.     }
  2292.     strncat(temp,"]",1);
  2293.     string=(char *)my_newmem(sizeof(temp));
  2294.     snprintf(string,sizeof(temp),"%s",temp);
  2295.     return string;
  2296. }
  2297.  
  2298. char *data2js_array(int data[],int len){
  2299.  /*
  2300.     1,2,3,4,5,6,7,8 --> [1,2,3,4,5,6,7,8]
  2301.     int data[] is already checked for errors or overflow in "get_real()"
  2302.     just to be sure we double check the size of "temp"
  2303. */
  2304.     char temp[MAX_BUFFER], *string;
  2305.     char *tmp = my_newmem(16);/* <= 9999999999999999  */
  2306.     memset(temp,'\0',MAX_BUFFER);/* clear memory */
  2307.     int i;int space_left;
  2308.     temp[0] = '[';/* start js-array */
  2309.     for(i = 0; i < len; i++){
  2310.         if(i == len - 1){sprintf(tmp, "%d", data[i]);}else{sprintf(tmp, "%d,", data[i]);}
  2311.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  2312.         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 ");}
  2313.     }
  2314.     strncat(temp,"]",1);
  2315.     string=(char *)my_newmem(sizeof(temp));
  2316.     snprintf(string,sizeof(temp),"%s",temp);
  2317.     return string;
  2318. }
  2319.  
  2320.  
  2321. void *my_newmem(size_t size){
  2322.         void    *p;
  2323.         if ((p = malloc(size +1)) == NULL){canvas_error("canvasdraw: ran out of memory\n");}
  2324.         return p;
  2325. }
  2326.  
  2327. int find_number_of_digits(int i){
  2328.     if(i < 0 ){ i = -1*i;}
  2329.     int digits = 0;
  2330.     while ( i > 0){
  2331.         digits++;
  2332.         i = i/10;
  2333.     }
  2334.     return digits;
  2335. }
  2336. /* change this when colornames / numbers are added to struct */
  2337. #define NUMBER_OF_COLORNAMES    140
  2338. struct {
  2339.     char *hex;
  2340.     char *name;
  2341.     char *rgb;
  2342. } colors[]={
  2343.  {"#FF0000","red","255,0,0"},
  2344.  {"#00FF00","lime","0,255,0"},
  2345.  {"#0000FF","blue","0,0,255"},
  2346.  {"#FFA500","orange","255,165,0"},
  2347.  {"#E9967A","darksalmon","233,150,122"},
  2348.  {"#F0FFFF","azure","240,255,255"},
  2349.  {"#CD5C5C","indianred","205,92,92"},
  2350.  {"#E0FFFF","lightcyan","224,255,255"},
  2351.  {"#FFE4E1","mistyrose","255,228,225"},
  2352.  {"#DC143C","crimson","220,20,60"},
  2353.  {"#FFC0CB","pink","255,192,203"},
  2354.  {"#FFD700","gold","255,215,0"},
  2355.  {"#E6E6FA","lavender","230,230,250"},
  2356.  {"#808080","gray","128,128,128"},
  2357.  {"#F0F8FF","aliceblue","240,248,255"},
  2358.  {"#C71585","mediumvioletred","199,21,133"},
  2359.  {"#FFF0F5","lavenderblush","255,240,245"},
  2360.  {"#DAA520","goldenrod","218,165,32"},
  2361.  {"#FFB6C1","lightpink","255,182,193"},
  2362.  {"#00FFFF","aqua","0,255,255"},
  2363.  {"#FF69B4","hotpink","255,105,180"},
  2364.  {"#00FFFF","cyan","0,255,255"},
  2365.  {"#FF1493","deeppink","255,20,147"},
  2366.  {"#7FFFD4","aquamarine","127,255,212"},
  2367.  {"#FA8072","salmon","250,128,114"},
  2368.  {"#DEB887","burlywood","222,184,135"},
  2369.  {"#DB7093","palevioletred","219,112,147"},
  2370.  {"#D2B48C","tan","210,180,140"},
  2371.  {"#BDB76B","darkkhaki","189,183,107"},
  2372.  {"#B22222","firebrick","178,34,34"},
  2373.  {"#FF4500","orangered","255,69,0"},
  2374.  {"#8B4513","saddlebrown","139,69,19"},
  2375.  {"#FF8C00","darkorange","255,140,0"},
  2376.  {"#FFFFE0","lightyellow","255,255,224"},
  2377.  {"#FFFF00","yellow","255,255,0"},
  2378.  {"#FFFACD","lemonchiffon","255,250,205"},
  2379.  {"#F5F5DC","beige","245,245,220"},
  2380.  {"#FFEFD5","papayawhip","255,239,213"},
  2381.  {"#FAFAD2","lightgoldenrodyellow","250,250,210"},
  2382.  {"#FFE4B5","moccasin","255,228,181"},
  2383.  {"#B8860B","darkgoldenrod","184,134,11"},
  2384.  {"#FFF8DC","cornsilk","255,248,220"},
  2385.  {"#FFEBCD","blanchedalmond","255,235,205"},
  2386.  {"#FFE4C4","bisque","255,228,196"},
  2387.  {"#FFDEAD","navajowhite","255,222,173"},
  2388.  {"#F5DEB3","wheat","245,222,179"},
  2389.  {"#CD853F","peru","205,133,63"},
  2390.  {"#D2691E","chocolate","210,105,30"},
  2391.  {"#A0522D","sienna","160,82,45"},
  2392.  {"#A52A2A","brown","165,42,42"},
  2393.  {"#BC8F8F","rosybrown","188,143,143"},
  2394.  {"#F08080","lightcoral","240,128,128"},
  2395.  {"#FFA07A","lightsalmon","255,160,122"},
  2396.  {"#8B0000","darkred","139,0,0"},
  2397.  {"#800000","maroon","128,0,0"},
  2398.  {"#FAA460","sandybrown","250,164,96"},
  2399.  {"#FF7F50","coral","255,127,80"},
  2400.  {"#FF6347","tomato","255,99,71"},
  2401.  {"#FFDAB9","peachpuff","255,218,185"},
  2402.  {"#EEE8AA","palegoldenrod","238,232,170"},
  2403.  {"#F0E68C","khaki","240,230,140"},
  2404.  {"#D8BFD8","thistle","216,191,216"},
  2405.  {"#DDA0DD","plum","221,160,221"},
  2406.  {"#FF00FF","fuchsia","255,0,255"},
  2407.  {"#FF00FF","magenta","255,0,255"},
  2408.  {"#EE82EE","violet","238,130,238"},
  2409.  {"#DA70D6","orchid","218,112,214"},
  2410.  {"#BA55D3","mediumorchid","186,85,211"},
  2411.  {"#9370DB","mediumpurple","147,112,219"},
  2412.  {"#8A2BE2","blueviolet","138,43,226"},
  2413.  {"#9400D3","darkviolet","148,0,211"},
  2414.  {"#9932CC","darkorchid","153,50,204"},
  2415.  {"#8B008B","darkmagenta","139,0,139"},
  2416.  {"#800080","purple","128,0,128"},
  2417.  {"#4B0082","indigo","75,0,130"},
  2418.  {"#483D8B","darkslateblue","72,61,139"},
  2419.  {"#6A5ACD","slateblue","106,90,205"},
  2420.  {"#7B68EE","mediumslateblue","123,104,238"},
  2421.  {"#98FB98","palegreen","152,251,152"},
  2422.  {"#ADFF2F","greenyellow","173,255,47"},
  2423.  {"#7FFF00","chartreuse","127,255,0"},
  2424.  {"#7CFC00","lawngreen","124,252,0"},
  2425.  {"#00FF7F","springgreen","0,255,127"},
  2426.  {"#00FA9A","mediumspringgreen","0,250,154"},
  2427.  {"#90EE90","lightgreen","144,238,144"},
  2428.  {"#32CD32","limegreen","50,205,50"},
  2429.  {"#3CB371","mediumseagreen","60,179,113"},
  2430.  {"#2E8B57","seagreen","46,139,87"},
  2431.  {"#228B22","forestgreen","34,139,34"},
  2432.  {"#008000","green","0,128,0"},
  2433.  {"#006400","darkgreen","0,100,0"},
  2434.  {"#9ACD32","yellowgreen","154,205,50"},
  2435.  {"#6B8E23","olivedrab","107,142,35"},
  2436.  {"#808000","olive","128,128,0"},
  2437.  {"#556B2F","darkolivegreen","85,107,47"},
  2438.  {"#8FBC8F","darkseagreen","143,188,143"},
  2439.  {"#66CDAA","mediumaquamarine","102,205,170"},
  2440.  {"#20B2AA","lightseagreen","32,178,170"},
  2441.  {"#008B8B","darkcyan","0,139,139"},
  2442.  {"#008080","teal","0,128,128"},
  2443.  {"#AFEEEE","paleturquoise","175,238,238"},
  2444.  {"#40E0D0","turquoise","64,224,208"},
  2445.  {"#48D1CC","mediumturquoise","72,209,204"},
  2446.  {"#00CED1","darkturquoise","0,206,209"},
  2447.  {"#5F9EA0","cadetblue","95,158,160"},
  2448.  {"#4682B4","steelblue","70,130,180"},
  2449.  {"#B0C4DE","lightsteelblue","176,196,222"},
  2450.  {"#B0E0E6","powderblue","176,224,230"},
  2451.  {"#ADD8E6","lightblue","173,216,230"},
  2452.  {"#87CEEB","skyblue","135,206,235"},
  2453.  {"#87CEFA","lightskyblue","135,206,250"},
  2454.  {"#00BFFF","deepskyblue","0,191,255"},
  2455.  {"#1E90FF","dodgerblue","30,144,255"},
  2456.  {"#6495ED","cornflowerblue","100,149,237"},
  2457.  {"#4169E1","royalblue","65,105,225"},
  2458.  {"#0000CD","mediumblue","0,0,205"},
  2459.  {"#00008B","darkblue","0,0,139"},
  2460.  {"#000080","navy","0,0,128"},
  2461.  {"#191970","midnightblue","25,25,112"},
  2462.  {"#DCDCDC","gainsboro","220,220,220"},
  2463.  {"#D3D3D3","lightgrey","211,211,211"},
  2464.  {"#808080","grey","128,128,128"},
  2465.  {"#C0C0C0","silver","192,192,192"},
  2466.  {"#A9A9A9","darkgray","169,169,169"},
  2467.  {"#778899","lightslategray","119,136,153"},
  2468.  {"#708090","slategray","112,128,144"},
  2469.  {"#696969","dimgray","105,105,105"},
  2470.  {"#2F4F4F","darkslategray","47,79,79"},
  2471.  {"#000000","black","0,0,0"},
  2472.  {"#F5FFFA","mintcream","245,255,250"},
  2473.  {"#FFFFFF","white","255,255,255"},
  2474.  {"#F0FFF0","honeydew","240,255,240"},
  2475.  {"#F5F5F5","whitesmoke","245,245,245"},
  2476.  {"#F8F8FF","ghostwhite","248,248,255"},
  2477.  {"#FFFFF0","ivory","255,255,240"},
  2478.  {"#FFFAFA","snow","255,250,250"},
  2479.  {"#FFFAF0","floralwhite","255,250,240"},
  2480.  {"#FFF5EE","seashell","255,245,238"},
  2481.  {"#FDF5E6","oldlace","253,245,230"},
  2482.  {"#FAF0E6","linen","250,240,230"},
  2483.  {"#FAEBD7","antiquewhite","250,235,215"},
  2484.  };
  2485.  
  2486.  
  2487. void add_drag_code(FILE *js_include_file,int canvas_cnt,int canvas_root_id){
  2488. /* in drag& drop / onclick library:
  2489.     obj_type = 1 == rect
  2490.     obj_type = 2 == point / points (do not scale with zoom)
  2491.     obj_type = 3 == ellipse
  2492.     obj_type = 4 == polyline / segment /line / vline / hline
  2493.     obj_type = 5 == closed path (polygon)
  2494.     obj_type = 6 == roundrect
  2495.     obj_type = 7 == crosshair / crosshairs
  2496.     obj_type = 8 == arrow
  2497.     obj_type = 9 == curve
  2498.     obj_type = 10== arrow2
  2499.     obj_type = 11== parallel  (no drag or onclick)
  2500.     obj_type = 12== arc : radius is in pixels , so no zooming in/out
  2501.     obj_type = 13== circle (will scale on zoom)
  2502.     obj_type = 14== text (will not scale or pan on zoom)
  2503.     obj_type = 15== animated point on curve
  2504.     obj_type = 16== pixels
  2505.     obj_type = 17== new arc [command angle] :radius in x-range, so will scale on zooming in/out
  2506. */
  2507. fprintf(js_include_file,"\n<!-- begin drag_drop_onclick shape library -->\n\
  2508. if( typeof dragdrop_precision == 'undefined' ){var dragdrop_precision = 100;};\
  2509. 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){\
  2510. this.slider = slider || 0;\
  2511. this.slider_cnt = slider_cnt || 0;\
  2512. this.text = text || 0;\
  2513. this.font_size = font_size || 12;\
  2514. if( font_family.indexOf('px') > 0 ){this.font_family = font_family;}else{this.font_family = this.font_size+'px Ariel';};\
  2515. this.use_rotate = use_rotate || 0;\
  2516. this.angle = angle*(Math.PI/180) || 0;\
  2517. this.use_affine = use_affine || 0;\
  2518. this.affine_matrix = affine_matrix || [1,0,0,1,0,0];\
  2519. this.click_cnt = click_cnt || 1;\
  2520. this.onclick = onclick || 0;\
  2521. this.direction = direction || 0;\
  2522. this.type = type || 1;\
  2523. this.xorg = x;\
  2524. this.yorg = y;\
  2525. this.x = [x.length];\
  2526. this.y = [x.length];\
  2527. this.w = [x.length];\
  2528. this.h = [x.length];\
  2529. for(var p=0;p<x.length;p++){\
  2530.  this.x[p] = x2px(x[p]-xstart);\
  2531.  this.y[p] = y2px(y[p]-ystart);\
  2532.  if( p > w.length){\
  2533.    this.w[p] = w[0];\
  2534.    this.h[p] = h[0];\
  2535.  }\
  2536.  else\
  2537.  {\
  2538.    this.w[p] = w[p];\
  2539.    this.h[p] = h[p];\
  2540.  }\
  2541. };\
  2542. this.line_width = line_width || 30;\
  2543. this.stroke_opacity = stroke_opacity || 1.0;\
  2544. this.stroke_color = \"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\" || '#FF0000';\
  2545. this.fill_opacity = fill_opacity || 1.0;\
  2546. this.fill_color = \"rgba(\"+fill_color+\",\"+fill_opacity+\")\" || '#FF0000';\
  2547. this.use_filled = use_filled || 0;\
  2548. this.use_dashed = use_dashed || 0;\
  2549. this.dashtype0 = dashtype0 || 4;\
  2550. this.dashtype1 = dashtype1 || 4;\
  2551. };\
  2552. Shape.prototype.draw = function(ctx)\
  2553. {\
  2554. ctx.lineWidth = this.line_width;\
  2555. ctx.strokeStyle = this.stroke_color;\
  2556. ctx.fillStyle = this.fill_color;\
  2557. ctx.lineJoin = \"round\";\
  2558. ctx.save();\
  2559. if(this.use_rotate == 1){\
  2560.  var x_c = x2px(0);\
  2561.  var y_c = y2px(0);\
  2562.  ctx.translate(x_c,y_c);\
  2563.  ctx.rotate(this.angle);ctx.translate(-x_c,-y_c);\
  2564. };\
  2565. if( this.use_affine == 1 ){\
  2566.  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]);\
  2567. };\
  2568. ctx.beginPath();\
  2569. switch(this.type){\
  2570.  case 1: ctx.rect(this.x[0], this.y[0], this.x[1]-this.x[0], this.y[2] - this.y[0]);break;\
  2571.  case 2: ctx.arc(this.x[0],this.y[0],this.w[0],0,2*Math.PI,false);break;\
  2572.  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;\
  2573.  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;\
  2574.  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;\
  2575.  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;\
  2576.  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;\
  2577.  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();};break;\
  2578.  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;\
  2579.  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],-1*this.w[0]);ctx.lineTo(-1*this.w[0],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.5*this.w[0]);ctx.lineTo(this.w[0], 0.5*this.w[0]);ctx.closePath();ctx.lineCap = \"round\";ctx.fill(); break;\
  2580.  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;\
  2581.  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 r = 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;\
  2582.  case 13: ctx.arc(this.x[0],this.y[0],scale_x_radius(this.w[0]),0,2*Math.PI,false);break;\
  2583.  case 14: ctx.font = this.font_family ;ctx.fillText(this.text,this.x[0],this.y[0]);break;\
  2584.  case 15: break;\
  2585.  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;\
  2586.  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;\
  2587.  default: alert(\"draw primitive unknown\");break;\
  2588. };\
  2589. if(this.use_filled == 1){ ctx.fill();}\
  2590. if(this.use_dashed == 1 ){if( ctx.setLineDash ){ ctx.setLineDash([this.dashtype0,this.dashtype1]);}else{ ctx.mozDash = [this.dashtype0,this.dashtype1];};};\
  2591. ctx.stroke();\
  2592. ctx.restore();\
  2593. };\
  2594. Shape.prototype.contains = function(mx, my){\
  2595. var marge = 2*this.line_width;\
  2596. switch(this.type){\
  2597.  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;\
  2598.  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] + marge ){return p;break;};};break;\
  2599.  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;\
  2600.  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;\
  2601.  case 6: 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;\
  2602.  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;\
  2603.  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;\
  2604.  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;\
  2605.  case 11: break;\
  2606.  case 12: break;\
  2607.  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;\
  2608.  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;\
  2609.  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;\
  2610. };\
  2611. return -1;\
  2612. };\
  2613. var reply = [];\
  2614. function CanvasState(canvas,container_div){\
  2615. this.canvas = canvas;\
  2616. this.width = canvas.width;\
  2617. this.height = canvas.height;\
  2618. var ctx = canvas.getContext(\"2d\");\
  2619. this.ctx = ctx;\
  2620. this.valid = false;\
  2621. this.shapes = [];\
  2622. this.moved = [];\
  2623. this.dragging = false;\
  2624. this.selection = null;\
  2625. var myState = this;\
  2626. container_div.addEventListener( 'mouseup'    , mouseup,false);\
  2627. container_div.addEventListener( 'mousemove'  , mousemove,false);\
  2628. container_div.addEventListener( 'mousedown'  , mousedown,false);\
  2629. container_div.addEventListener( 'touchend'   , mouseup,false);\
  2630. container_div.addEventListener( 'selectstart', function(e) { e.preventDefault(); return false; }, false);\
  2631. container_div.addEventListener( 'touchstart' , mousedown,false);\
  2632. container_div.addEventListener( 'touchmove'  , mousemove,false);\
  2633. function mousedown(e){\
  2634.  var mouse = myState.getMouse(e);\
  2635.  var mx = mouse.x;\
  2636.  var my = mouse.y;\
  2637.  if( use_pan_and_zoom == 1 && my > ysize - 15){\
  2638.   check_zoom_or_pan(mx);\
  2639.  }\
  2640.  else\
  2641.  {\
  2642.   var shapes = myState.shapes;\
  2643.   var l = shapes.length;\
  2644.   var chk = -1;\
  2645.   for(var i=0;i<l;i++){\
  2646.    chk = shapes[i].contains(mx, my);\
  2647.    if ( chk != -1 ){\
  2648.     if( myState.moved[shapes[i].click_cnt] != 1){\
  2649.      myState.moved[shapes[i].click_cnt] = 1;\
  2650.      myState.x_start = shapes[i].x[chk];\
  2651.      myState.y_start = shapes[i].y[chk];\
  2652.     };\
  2653.     var org_line_width = shapes[i].line_width;\
  2654.     var org_font_family = shapes[i].font_family;\
  2655.     var org_stroke_opacity = shapes[i].stroke_opacity;\
  2656.     myState.chk = chk;\
  2657.     myState.selection = shapes[i];\
  2658.     myState.valid = false;\
  2659.     switch(shapes[i].onclick){\
  2660.      case 0: myState.dragging = false;break;\
  2661.      case 1: myState.selection.line_width = 3*org_line_width;myState.selection.font_family = \"bold italic \"+myState.selection.font_size+\"px Courier\";myState.dragging = false;myState.draw();reply[0] = myState.selection.click_cnt;myState.selection.line_width = org_line_width;myState.selection.font_family = org_font_family;break;\
  2662.      case 2: myState.dragging = true;break;\
  2663.      default:break;\
  2664.     };\
  2665.     return;\
  2666.    };\
  2667.   };\
  2668.  };\
  2669.  myState.selection = null;\
  2670.  myState.valid = true;\
  2671.  return;\
  2672. };\
  2673. function mouseup(e){;\
  2674.  if(myState.selection != null ){\
  2675.   if(myState.selection.onclick == 2 ){\
  2676.    if( x_use_snap_to_grid == 1 || y_use_snap_to_grid == 1){\
  2677.     var mouse = myState.getMouse(e);\
  2678.     var dx=mouse.x;\
  2679.     var dy=mouse.y;\
  2680.     if( x_use_snap_to_grid == 1 && y_use_snap_to_grid == 1 ){ \
  2681.      dx = snap_to_x(dx) - myState.selection.x[myState.chk];\
  2682.      dy = snap_to_y(dy) - myState.selection.y[myState.chk];\
  2683.     }else{\
  2684.      if( x_use_snap_to_grid == 1 ){ \
  2685.       dx = snap_to_x(dx) - myState.selection.x[myState.chk];\
  2686.       dy = 0;\
  2687.      }else{\
  2688.       dx = 0;\
  2689.       dy = snap_to_y(dy) - myState.selection.y[myState.chk];\
  2690.      };\
  2691.     };\
  2692.     switch(myState.selection.direction){\
  2693.      case 0: myState.selection = move(myState.selection,dx,dy);break;\
  2694.      case 1: myState.selection = move(myState.selection,dx,0);break;\
  2695.      case 2: myState.selection = move(myState.selection,0,dy); break;\
  2696.     };\
  2697.    };\
  2698.    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;\
  2699.   };\
  2700.   myState.valid = false;\
  2701.   myState.draw();\
  2702.   myState.valid = true;\
  2703.  };\
  2704.  myState.dragging = false;\
  2705. };\
  2706. function mousemove(e){\
  2707.  if(myState.dragging){\
  2708.   var mouse = myState.getMouse(e);\
  2709.   var dx=mouse.x - myState.selection.x[myState.chk];\
  2710.   var dy=mouse.y - myState.selection.y[myState.chk];\
  2711.   switch(myState.selection.direction){\
  2712.    case 0: myState.selection = move(myState.selection,dx,dy);break;\
  2713.    case 1: myState.selection = move(myState.selection,dx,0);break;\
  2714.    case 2: myState.selection = move(myState.selection,0,dy); break;\
  2715.    default:break;\
  2716.   };\
  2717.   myState.valid = false;\
  2718.  };\
  2719. };\
  2720. function check_zoom_or_pan(x){\
  2721.  var key = -1;\
  2722.  for(var p = 15 ; p < 106 ; p = p+15){\
  2723.    key++;\
  2724.    if(x > xsize - p){start_canvas%d(key);return;}\
  2725.  }\
  2726.  return;\
  2727. };\
  2728. this.interval = 30;\
  2729. setInterval(function() { myState.draw(); }, myState.interval);\
  2730. };\
  2731. CanvasState.prototype.addShape = function(shape){\
  2732. this.shapes.push(shape);\
  2733. this.valid = false;\
  2734. };\
  2735. CanvasState.prototype.clear = function(){\
  2736. this.ctx.clearRect(0, 0, this.width, this.height);\
  2737. };\
  2738. CanvasState.prototype.draw = function(){\
  2739. if(this.valid == false ){\
  2740.  var shapes = this.shapes;\
  2741.  this.clear();\
  2742.  var l = shapes.length;var shape;\
  2743.  for(var i = 0; i < l; i++){\
  2744.   shape = shapes[i];\
  2745.   shape.draw(this.ctx);\
  2746.  };\
  2747.  this.valid = true;\
  2748. }\
  2749. };\
  2750. CanvasState.prototype.Slide = function(slider_value,slider_count){\
  2751. this.ctx.clearRect(0,0,xsize,ysize);\
  2752. var what;var len = this.shapes.length;var shape;var lu;\
  2753. for(var i = 0; i < len ; i++){\
  2754.  if( this.shapes[i] ){\
  2755.   shape = this.shapes[i];\
  2756.   if( shape.slider != 0 ){\
  2757.    if(shape.slider_cnt == slider_count ){\
  2758.     what = shape.slider;\
  2759.     lu = shape.x.length;\
  2760.     reply[shape.click_cnt] = shape.click_cnt+\":\"+slider_value;\
  2761.     switch(what){\
  2762.      case 1: slide(shape,slider_value[0],0);break;\
  2763.      case 2: slide(shape,0,slider_value[0]);break;\
  2764.      case 3: if(shape.type == 12 || shape.type == 17){shape.h[1] = 180*slider_value[0]/Math.PI;}else{shape.use_rotate = 1;shape.angle = -1*slider_value[0];};break;\
  2765.      case 4: slide(shape,slider_value[0],slider_value[1]);break;\
  2766.      default:break;\
  2767.     };\
  2768.    };\
  2769.   };\
  2770.   this.valid = false;\
  2771.   shape.draw(this.ctx);\
  2772.  };\
  2773. };\
  2774. };\
  2775. CanvasState.prototype.Zoom = function(xmin,xmax,ymin,ymax){\
  2776. (this.ctx).clearRect(0,0,this.width,this.height);\
  2777. var len = this.shapes.length;var shape;\
  2778. for(var i = 0; i < len ; i++){\
  2779.  shape = this.shapes[i];\
  2780.  for(var p = 0 ; p < shape.x.length;p++){\
  2781.   shape.x[p] = x2px(shape.xorg[p]);\
  2782.   shape.y[p] = y2px(shape.yorg[p]);\
  2783.  }\
  2784.  this.valid = false;\
  2785.  shape.draw(this.ctx);\
  2786. };\
  2787. reply = new Array();\
  2788. };\
  2789. CanvasState.prototype.getMouse = function(e){\
  2790. var element = this.canvas, offsetX = 0,offsetY = 0;\
  2791. while( ( element = element.offsetParent) ){\
  2792. offsetX += element.offsetLeft;\
  2793. offsetY += element.offsetTop;\
  2794. }\
  2795. var mx = e.clientX - offsetX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);\
  2796. var my = e.clientY - offsetY + (document.documentElement.scrollTop ? document.documentElement.scrollTop :document.body.scrollTop);\
  2797. return {x: mx, y: my};\
  2798. };\
  2799. CanvasState.prototype.read_dragdrop = function(){\
  2800. var moved_objects = new Array();\
  2801. var c = 0;\
  2802. for(var p = 0 ; p < reply.length ; p++){\
  2803.  if( reply[p] != null ){\
  2804.   moved_objects[c] = reply[p];\
  2805.   c++;\
  2806.  };\
  2807. }\
  2808. return moved_objects;\
  2809. };\
  2810. var obj = create_canvas%d(%d,xsize,ysize);\
  2811. var container_div = document.getElementById(\"canvas_div%d\");\
  2812. var dragstuff = new CanvasState(obj,container_div);\
  2813. read_dragdrop = dragstuff.read_dragdrop;",canvas_root_id,canvas_root_id,DRAG_CANVAS,canvas_root_id);
  2814. }
  2815.  
  2816. /*
  2817. #define BG_CANVAS 0 may be used for floodfill
  2818. #define STATIC_CANVAS 1 may be used for floodfill
  2819. #define MOUSE_CANVAS 2 xx
  2820. #define GRID_CANVAS 3 may be used for floodfill
  2821. #define DRAG_CANVAS 4 default for floodfill
  2822. #define DRAW_CANVAS 5 may be used for floodfill
  2823.  
  2824. */
  2825.  
  2826.  
  2827. void add_js_floodfill(FILE *js_include_file,int canvas_root_id){
  2828. fprintf(js_include_file,"\n<!-- begin command floodfill -->\n\
  2829. var floodfill = function(interaction,xs,ys,color){\
  2830. var canvas = document.getElementById(\"wims_canvas%d%d\");\
  2831. if( ! canvas ){ return; };\
  2832. var ctx = canvas.getContext(\"2d\");\
  2833. ctx.save();\
  2834. if(interaction == 1 ){\
  2835.  if( ys > ysize - 15){return;}\
  2836. }\
  2837. else\
  2838. {\
  2839.  xs = x2px(xs);\
  2840.  ys = y2px(ys);\
  2841. };\
  2842. var image = ctx.getImageData(0, 0, xsize, ysize);\
  2843. var imageData = image.data;\
  2844. var pixelStack = [[xs, ys]];\
  2845. var px1;\
  2846. var newPos;\
  2847. var pixelPos;\
  2848. var found_left_border;\
  2849. var found_right_border;\
  2850. function _getPixel(pixelPos){\
  2851.  return {r:imageData[pixelPos], g:imageData[pixelPos+1], b:imageData[pixelPos+2], a:imageData[pixelPos+3]};\
  2852. };\
  2853. function _setPixel(pixelPos){\
  2854.  imageData[pixelPos] = color.r;\
  2855.  imageData[pixelPos+1] = color.g;\
  2856.  imageData[pixelPos+2] = color.b;\
  2857.  imageData[pixelPos+3] = color.a;\
  2858. };\
  2859. function _comparePixel(px2){\
  2860.  return (px1.r === px2.r && px1.g === px2.g && px1.b === px2.b && px1.a === px2.a);\
  2861. };\
  2862. px1 = _getPixel(((ys * xsize) + xs) * 4);\
  2863. color = {\
  2864.  r: parseInt(color[0], 10),\
  2865.  g: parseInt(color[1], 10),\
  2866.  b: parseInt(color[2], 10),\
  2867.  a: parseInt(color[3] || 255, 10)\
  2868. };\
  2869. if( _comparePixel(color) ) { return true; }\
  2870. while (pixelStack.length) {\
  2871.  newPos = pixelStack.pop();\
  2872.  xs = newPos[0];ys = newPos[1];\
  2873.  pixelPos = (ys*xsize + xs) * 4;\
  2874.  while(ys-- >= 0 && _comparePixel(_getPixel(pixelPos))){\
  2875.   pixelPos -= xsize * 4;\
  2876.  }\
  2877.  pixelPos += xsize * 4;\
  2878.  ++ys;\
  2879.  found_left_border = false;\
  2880.  found_right_border = false;\
  2881.  while( ys++ < ysize-1 && _comparePixel(_getPixel(pixelPos)) ){\
  2882.   _setPixel(pixelPos);\
  2883.   if( xs > 0 ){\
  2884.    if( _comparePixel(_getPixel(pixelPos - 4)) ){\
  2885.    if( !found_left_border ){\
  2886.     pixelStack.push( [xs - 1, ys] );\
  2887.     found_left_border = true;\
  2888.    }\
  2889.   }\
  2890.   else if( found_left_border ){\
  2891.     found_left_border = false;\
  2892.    }\
  2893.   }\
  2894.   if( xs < xsize-1 ){\
  2895.    if( _comparePixel(_getPixel(pixelPos + 4)) ){\
  2896.     if( !found_right_border){\
  2897.      pixelStack.push( [xs + 1, ys] );\
  2898.      found_right_border = true;\
  2899.     }\
  2900.    }\
  2901.    else if(found_right_border){\
  2902.      found_right_border = false;\
  2903.     }\
  2904.    }\
  2905.   pixelPos += xsize * 4;\
  2906.  }\
  2907. };\
  2908. ctx.putImageData(image, 0, 0);\
  2909. ctx.restore();\
  2910. };",canvas_root_id,DRAG_CANVAS);
  2911.  
  2912. }
  2913.  
  2914. void add_js_filltoborder(FILE *js_include_file,int canvas_root_id){
  2915. fprintf(js_include_file,"\n<!-- begin command filltoborder -->\n\
  2916. var filltoborder = function(xs,ys,bordercolor,color){\
  2917. var xs = x2px(xs);\
  2918. var ys = y2px(ys);\
  2919. var canvas = document.getElementById(\"wims_canvas%d\"+4);\
  2920. var ctx = canvas.getContext(\"2d\");ctx.save();\
  2921. var image = ctx.getImageData(0, 0, xsize, ysize);\
  2922. var imageData = image.data;\
  2923. var pixelStack = [[xs, ys]];\
  2924. var px1;\
  2925. var newPos;\
  2926. var pixelPos;\
  2927. var found_left_border;\
  2928. var found_right_border;\
  2929. function _getPixel(pixelPos){\
  2930.  return {r:imageData[pixelPos], g:imageData[pixelPos+1], b:imageData[pixelPos+2], a:imageData[pixelPos+3]};\
  2931. };\
  2932. function _setPixel(pixelPos){\
  2933.  imageData[pixelPos] = color.r;\
  2934.  imageData[pixelPos+1] = color.g;\
  2935.  imageData[pixelPos+2] = color.b;\
  2936.  imageData[pixelPos+3] = color.a;\
  2937. };\
  2938. function _comparePixel(px2){\
  2939.  return (px1.r === px2.r && px1.g === px2.g && px1.b === px2.b);\
  2940. };\
  2941. function _checkBorder(px2){\
  2942.  return (bordercolor.r === px2.r && bordercolor.g === px2.g && bordercolor.b === px2.b);\
  2943. };\
  2944. px1 = _getPixel(((ys * xsize) + xs) * 4);\
  2945. bordercolor = {\
  2946.  r: parseInt(bordercolor[0], 10),\
  2947.  g: parseInt(bordercolor[1], 10),\
  2948.  b: parseInt(bordercolor[2], 10),\
  2949.  a: parseInt(bordercolor[3] || 255, 10)\
  2950. };\
  2951. color = {\
  2952.  r: parseInt(color[0], 10),\
  2953.  g: parseInt(color[1], 10),\
  2954.  b: parseInt(color[2], 10),\
  2955.  a: parseInt(color[3] || 255, 10)\
  2956. };\
  2957. if( _comparePixel(color) ) { return true; }\
  2958. while (pixelStack.length) {\
  2959.  newPos = pixelStack.pop();\
  2960.  xs = newPos[0];ys = newPos[1];\
  2961.  pixelPos = (ys*xsize + xs) * 4;\
  2962.  while(ys-- >= 0 && _comparePixel(_getPixel(pixelPos)) ){\
  2963.   pixelPos -= xsize * 4;\
  2964.  }\
  2965.  pixelPos += xsize * 4;\
  2966.  ++ys;\
  2967.  found_left_border = false;\
  2968.  found_right_border = false;\
  2969.  while( ys++ < ysize-1 &&  _comparePixel(_getPixel(pixelPos)) && ! _checkBorder(_getPixel(pixelPos)) ){\
  2970.   _setPixel(pixelPos);\
  2971.   if( xs > 0 ){\
  2972.    if( _comparePixel(_getPixel(pixelPos - 4)) ){\
  2973.    if( !found_left_border ){\
  2974.     pixelStack.push( [xs - 1, ys] );\
  2975.     found_left_border = true;\
  2976.    }\
  2977.   }\
  2978.   else if( found_left_border ){\
  2979.     found_left_border = false;\
  2980.    }\
  2981.   }\
  2982.   if( xs < xsize-1 ){\
  2983.    if( _comparePixel(_getPixel(pixelPos + 4)) ){\
  2984.     if( !found_right_border){\
  2985.      pixelStack.push( [xs + 1, ys] );\
  2986.      found_right_border = true;\
  2987.     }\
  2988.    }\
  2989.    else if(found_right_border){\
  2990.      found_right_border = false;\
  2991.     }\
  2992.    }\
  2993.   pixelPos += xsize * 4;\
  2994.  }\
  2995. }\
  2996. ctx.putImageData(image, 0, 0);\
  2997. ctx.restore();\
  2998. };",canvas_root_id);
  2999.  
  3000. }
  3001.  
  3002.