Subversion Repositories wimsdev

Rev

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

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