Subversion Repositories wimsdev

Rev

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

  1. #include "canvasdraw.h"
  2.  
  3. void add_js_zoom_buttons(char *stroke_color,double stroke_opacity){
  4. fprintf(js_include_file,"\n/* draw zoom buttons */\
  5. var draw_zoom_buttons = function(){\
  6. var obj;var canvas_type =%d;\
  7. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){\
  8.  obj = document.getElementById(\"wims_canvas%d\"+canvas_type);\
  9. } else {\
  10.  obj = create_canvas%d(canvas_type,xsize,ysize);\
  11. };\
  12. var ctx = obj.getContext(\"2d\");\
  13. ctx.font =\"20px Arial\";\
  14. ctx.textAlign = \"right\";\
  15. ctx.fillStyle=\"rgba(%s,%f)\";\
  16. ctx.fillText(\"+\",xsize,ysize);\
  17. ctx.fillText(\"\\u2212\",xsize - 15,ysize-2);\
  18. ctx.fillText(\"\\u2192\",xsize - 30,ysize-2);\
  19. ctx.fillText(\"\\u2190\",xsize - 45,ysize-2);\
  20. ctx.fillText(\"\\u2191\",xsize - 60,ysize-2);\
  21. ctx.fillText(\"\\u2193\",xsize - 75,ysize-2);\
  22. ctx.fillText(\"\\u00D7\",xsize - 90,ysize-2);\
  23. ctx.stroke();\
  24. };draw_zoom_buttons();",BG_CANVAS,canvas_root_id,canvas_root_id,canvas_root_id,stroke_color,stroke_opacity);
  25. }
  26.  
  27. void add_js_popup(char *getfile_cmd){
  28.   fprintf(stdout,"\n<!-- begin command popup %d -->\n\
  29. <script>\n\
  30. if( wims_status != 'done'){\
  31. var popup = window.open('','','toolbar=no,scrollbars=yes,menubar=no,location=no,resizable=yes,top=4,left=4,status=no, width = %dpx, height = %dpx');\
  32. var popupHTML =\"<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'>\\n<html><head></head>\\n<body><div style='width:%dpx;height:%dpx;position:relative' id='canvas_div%d'></div><div id='tooltip_placeholder_div%d' style='display:block;position:relative;margin-left:auto;margin-right:auto;margin-bottom:4px;'><span id='tooltip_placeholder%d' style='display:none;'></span></div></body></html>\";\
  33. popup.document.write(popupHTML);\
  34. var s0 = popup.document.createElement(\"script\");\
  35. s0.text=\"var wims_status = window.opener.wims_status; var use_dragdrop_reply = window.opener.use_dragdrop_reply;window.opener.canvas_scripts.push('%d');\";\
  36. popup.document.getElementsByTagName(\"HEAD\")[0].appendChild(s0);\
  37. var s1 = popup.document.createElement(\"script\");\
  38. s1.src = \"%s\";\
  39. popup.document.getElementsByTagName(\"HEAD\")[0].appendChild(s1);\
  40. popup.document.close();\
  41. } else {\
  42.  var canvas_div = document.getElementById('canvas_div%d');\
  43.  canvas_div.style.display='block';\
  44. };\n</script>\n<!-- end command popup %d -->\n",
  45. canvas_root_id,
  46. xsize+40,ysize+40,
  47. xsize,ysize,
  48. canvas_root_id,
  49. canvas_root_id,
  50. canvas_root_id,
  51. canvas_root_id,
  52. getfile_cmd,
  53. canvas_root_id,
  54. canvas_root_id);
  55. }
  56.  
  57. void add_js_tooltip(char *tooltip_text,char *bgcolor){
  58.   fprintf(stdout,"\n<!-- begin command intooltip %d -->\n\
  59. <script>\n\
  60. var xsize = %d;\
  61. var ysize = %d;\
  62. var tooltip%d_obj_x = 0;\
  63. var tooltip%d_obj_y = 0;\
  64. var tooltip%d_flipflop = 0;\
  65. var tooltip%d_obj = document.getElementById(\"canvas_div%d\");\
  66. tooltip%d_obj.style.display=\"none\";\
  67. tooltip%d_obj.style.position=\"absolute\";\
  68. var tooltip%d_link = document.createElement(\"a\");\
  69. tooltip%d_link.addEventListener(\"mousemove\",tooltip%d_drag,false);\
  70. tooltip%d_link.setAttribute(\"onclick\",\"tooltip%d_show()\");\
  71. tooltip%d_link.innerHTML  = \"%s\";\
  72. var tooltip_placeholder = document.getElementById(\"tooltip_placeholder%d\");\
  73. tooltip_placeholder.style.display=\"block\";\
  74. tooltip_placeholder.style.position=\"absolute\";\
  75. tooltip_placeholder.style.backgroundColor=\"%s\";\
  76. tooltip_placeholder.appendChild(tooltip%d_link);\
  77. function tooltip%d_drag(action){\
  78. if(!action){ action = event; };\
  79. if(action.clientX){\
  80.  tooltip%d_obj.style.left = (tooltip%d_mouseX(action) + 10) +\"px\";\
  81.  var ytop = tooltip%d_mouseY(action);\
  82.  if(ytop + ysize < window.innerHeight){\
  83.   tooltip%d_obj.style.top = (ytop - 10) +\"px\";\
  84.  } else {\
  85.   tooltip%d_obj.style.top = parseInt(ytop - 0.8*ysize) +\"px\";\
  86.  };\
  87. } else {\
  88.  return null;\
  89. };\
  90. };\
  91. function tooltip%d_mouseX(action){\
  92. if(action.pageX){\
  93.  return action.pageX;\
  94. } else {\
  95.  if(action.clientX){\
  96.   return action.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);\
  97.  } else {\
  98.   return null;\
  99.  };\
  100. };\
  101. };\
  102. function tooltip%d_mouseY(action){\
  103. if(action.pageY){\
  104.  return action.pageY;\
  105. } else {\
  106.  if(action.clientY){\
  107.   return action.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop :document.body.scrollTop);\
  108.  } else {\
  109.   return null;\
  110.  };\
  111. };\
  112. };\
  113. function tooltip%d_show(){\
  114. if(tooltip%d_flipflop == 0){\
  115.  tooltip%d_obj.style.display = \"block\";\
  116.  tooltip%d_flipflop = 1;\
  117. } else {\
  118.  tooltip%d_flipflop = 0;\
  119.  tooltip%d_obj.style.display = \"none\";\
  120. };\
  121. };\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);
  122. }
  123.  
  124. /*
  125.  
  126. type = 0 : x-values only [command mousex]
  127. type = 1 : y-values only [command mousey]
  128. type = 2 : (x:y)         [command mouse]
  129. type = 3 : degree        [command mouse_degree]
  130. type = 4 : radian
  131. type = 5 : radius
  132.  
  133.   var mouse = getMouse(evt,canvas_div);\
  134.   var x = evt.clientX - mouse_canvas_rect.left;\
  135.   var y = evt.clientY - mouse_canvas_rect.top;\
  136.  
  137. */
  138. void add_js_mouse(int canvas_cnt,int precision,char *stroke_color,int font_size,double stroke_opacity,int type){
  139.   fprintf(js_include_file,"\n/* command mouse on mouse canvas */\
  140. function use_mouse_coordinates(){\
  141. var display_type = %d;\
  142. var canvas_type = %d;\
  143. var mouse_canvas = create_canvas%d(canvas_type,xsize,ysize);\
  144. var mouse_context = mouse_canvas.getContext(\"2d\");\
  145. mouse_canvas.addEventListener(\"mousemove\",show_coordinate%d,false);\
  146. mouse_canvas.addEventListener(\"touchmove\", function(e){ e.preventDefault();show_coordinate%d(e.changedTouches[0]);},false);\
  147. var prec = Math.log(%d)/(Math.log(10));\
  148. function show_coordinate%d(evt){\
  149.  var mouse = getMouse(evt,mouse_canvas);\
  150.  var x = mouse.x;\
  151.  var y = mouse.y;\
  152.  var m_data = \"\";\
  153.  switch(display_type){\
  154.   case 0: m_data = \" \"+(px2x(x)).toFixed(prec)+\" \"+unit_x;break;\
  155.   case 1: m_data = \" \"+(px2y(y)).toFixed(prec)+\" \"+unit_y;break;\
  156.   case 2: m_data = \"(\"+(px2x(x)).toFixed(prec)+\":\"+(px2y(y)).toFixed(prec)+\")\";break;\
  157.   case 3: if(userdraw_radius[0]){ m_data = \" \"+( ( userdraw_radius[0])/(Math.PI/180) ).toFixed(prec)+\" \\u00B0 \";};break;\
  158.   case 4: if(userdraw_radius[0]){ m_data = \" \"+(userdraw_radius[0]).toFixed(prec)+\" rad \";};break;\
  159.   case 5: if( userdraw_x.length > 0 ){var L = userdraw_x.length;m_data = \" R = \"+((xmax - xmin)*(distance(x,y,userdraw_x[L-1],userdraw_y[L-1]))/xsize).toFixed(prec)+\" \"+unit_x;};break;\
  160.   default:break;\
  161.  };\
  162.  var s = parseInt(0.8*%d*(m_data.toString()).length);\
  163.  mouse_context.font = \"%dpx Arial\";\
  164.  mouse_context.fillStyle = \"rgba(%s,%f)\";\
  165.  mouse_context.clearRect(0,0,s,1.2*%d);\
  166.  mouse_context.fillText(m_data,0,%d);\
  167. };\
  168. };",type,MOUSE_CANVAS,canvas_root_id,canvas_root_id,canvas_root_id,precision,canvas_root_id,font_size,font_size,stroke_color,stroke_opacity,font_size,font_size);
  169. }
  170.  
  171. /*
  172. Math.sin: angle in radians
  173. x1 = x*cos(a) - y*sin(a)
  174. y1 = y*cos(a) + x*sin(a)
  175. show_display = 0  nothing
  176. show_display = 1 delta X
  177. show_display = 2 delta Y
  178. show_display = 3 delta R radians
  179. show_display = 4 delta degrees
  180. show_display = 5 delta X:Y
  181.  
  182. */
  183. void add_slider_display(int precision,int font_size,char *font_color,double stroke_opacity){
  184.   fprintf(js_include_file,"\n/* add_slider_display */\
  185. var slider_prec = Math.log(%d)/(Math.log(10));\
  186. function show_slider_value(value,use_slider_display){\
  187. var current_canvas = create_canvas%d(%d,xsize,ysize);\
  188. var current_context = current_canvas.getContext(\"2d\");\
  189. current_context.clearRect(0,0,xsize,ysize);\
  190. var string;\
  191. switch(use_slider_display){\
  192.  case 0: return;\
  193.  case 1: string = '\\u0394 x = '+value.toFixed(slider_prec)+' '+unit_x;break;\
  194.  case 2: string = '\\u0394 y = '+value.toFixed(slider_prec)+' '+unit_y;break;\
  195.  case 3: string = '\\u2221 = '+value.toFixed(slider_prec)+'\\u03C0 rad';break;\
  196.  case 4: string = '\\u2221 = '+(value*(180/Math.PI)).toFixed(slider_prec)+'\\u00B0';break;\
  197.  case 5: string = 'not implemented';break;\
  198.  default: string = '['+value+']';break;\
  199. };\
  200. var s = parseInt(1.2*%d*(string).length);\
  201. current_context.font = '%dpx Arial';\
  202. current_context.strokeStyle = 'rgba(%s,%.2f)';\
  203. current_context.clearRect(0,0,s,1.2*%d);\
  204. current_context.fillText(string,0,%d);};",precision,canvas_root_id,MOUSE_CANVAS,font_size,font_size,font_color,stroke_opacity,font_size,font_size);
  205. }
  206.  
  207. void add_slider(int anim){
  208.   if(anim != 2 ){
  209.     fprintf(js_include_file,"\n/* add_slider aux*/\
  210. if( typeof( slidergroup) !== 'object'){var slidergroup = [];};\
  211. function rotateXY(obj,angle){\
  212. if( typeof(angle) === 'undefined' ){console.log('rotateXY() angle undefined');return obj;};\
  213. var len = obj.x.length;\
  214. if( typeof(len) === 'undefined' ){obj.angle = angle;return obj;};\
  215. var cos = Math.cos(angle - obj.angle);\
  216. var sin = Math.sin(angle - obj.angle);\
  217. obj.angle = angle;\
  218. var xc,yc;\
  219. if( obj.use_rotation_center == 0 ){\
  220.  xc = obj.x[0];\
  221.  yc = obj.y[0];\
  222. }else{\
  223.  xc = obj.rotation_center[0];\
  224.  yc = obj.rotation_center[1];\
  225. };\
  226. var x,y;\
  227. for(var p = 0 ; p < len ; p++ ){\
  228.  x = obj.x[p];\
  229.  y = obj.y[p];\
  230.  obj.x[p] = (cos * (x - xc)) + (sin * (y - yc)) + xc;\
  231.  obj.y[p] = (cos * (y - yc)) - (sin * (x - xc)) + yc;\
  232. };\
  233. return obj;\
  234. };\
  235. function rotateARC(obj,angle){\
  236. obj.h[0] = angle;\
  237. obj.angle = -1*angle;\
  238. return obj;\
  239. };\
  240. function slider_show_it(XYR,dx,value,slider_id){\
  241. if(slidergroup.length != 0){\
  242.  var len = slidergroup.length;var use_xml = false;\
  243.  for(var i = 0;i < len;i++){\
  244.   use_xml = false;var obj = slidergroup[i];\
  245.   if( obj !== null ){\
  246.    if( obj.use_slider[0] != -1 ){\
  247.     var sl = obj.use_slider.length;\
  248.     for(var s = 0 ; s < sl;s++ ){\
  249.      if(obj.use_slider[s] == slider_id ){\
  250.       if( typeof(obj.type) !== 'number' ){use_xml = true;};\
  251.       switch(XYR){\
  252.        case 'X' : obj = move(obj,dx,0);dragdrop_reply[obj.object_cnt].x = obj.x;break;\
  253.        case 'Y' : obj = move(obj,0,dx);dragdrop_reply[obj.object_cnt].y = obj.y;break;\
  254.        case 'R' : if(obj.type == 17 ){obj = rotateARC(obj,value);}else{obj = rotateXY(obj,value);};dragdrop_reply[obj.object_cnt].angle = obj.angle;break;\
  255.        default : break;\
  256.       };\
  257.      };\
  258.     };\
  259.    };\
  260.    if( use_xml ){ draw_xml(obj); }\
  261.    dragstuff.draw();dragstuff.valid = false;\
  262.   };\
  263.  };\
  264. };\
  265. return;\
  266. };\
  267. ");
  268.   }
  269.   if(anim == 0){fprintf(js_include_file,"\n/* add_slider */\
  270. if( typeof(unit_x) === 'undefined' ){var unit_x = ' ';};\
  271. if( typeof(unit_y) === 'undefined' ){var unit_y = ' ';};\
  272. function slider(XYR,text,slider_id ,width,height,linewidth,fillcolor,strokecolor,opacity,min,max,fontfamily,display){\
  273. if( wims_status == \"done\" ){return;};var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  274. var xcenter = 0.5*width;var rcenter = 0.5*width;fillcolor = 'rgba('+fillcolor+','+opacity[0]+')' || 'rgba(200,200,0,0.2)';\
  275. strokecolor = 'rgba('+strokecolor+','+opacity[1]+')';var title = document.createElement('SPAN');title.innerHTML = text;\
  276. var br = document.createElement('BR');tooltip_div.appendChild(br);tooltip_div.appendChild(title);\
  277. var slider_canvas = document.createElement('canvas');slider_canvas.id = 'canvas'+slider_id;tooltip_div.appendChild(slider_canvas);\
  278. slider_canvas.width = width;slider_canvas.height = height;var slider_ctx = slider_canvas.getContext(\"2d\");\
  279. slider_ctx.font = fontfamily;slider_ctx.strokeStyle = strokecolor;\
  280. slider_ctx.fillStyle = fillcolor;slider_ctx.lineWidth = linewidth;slider_ctx.save();\
  281. slider_ctx.beginPath();slider_ctx.moveTo(0,height-10);slider_ctx.lineTo(width,height-10);\
  282. slider_ctx.moveTo(xcenter-10,10);slider_ctx.lineTo(xcenter+10,10);slider_ctx.lineTo(xcenter,height-10);\
  283. slider_ctx.lineTo(xcenter-10,10);slider_ctx.closePath();slider_ctx.stroke();slider_ctx.fill();\
  284. slider_canvas.addEventListener( 'mousemove' ,slide_me,false);\
  285. slider_canvas.addEventListener( 'mouseup' ,stop_slide_me,false);\
  286. slider_canvas.addEventListener( 'mousedown' ,start_slide_me,false);\
  287. slider_canvas.addEventListener( 'touchstart', function(e){ e.preventDefault();start_slide_me(e.changedTouches[0]);},false);\
  288. slider_canvas.addEventListener( 'touchend',   function(e){ e.preventDefault();stop_slide_me(e.changedTouches[0]);},false);\
  289. slider_canvas.addEventListener( 'touchmove' ,function(e){ e.preventDefault();slide_me(e.changedTouches[0]);},false);\
  290. var slider_active = false;var value;\
  291. function stop_slide_me(evt){slider_active = false;};\
  292. function start_slide_me(evt){slider_active = true;};\
  293. function slide_me(evt){\
  294.  if( slider_active == false ){return;};\
  295.  var canvas_rect = slider_canvas.getBoundingClientRect();\
  296.  slider_ctx.clearRect(0,0,width,height);\
  297.  var px = parseInt(evt.clientX - canvas_rect.left);\
  298.  slider_ctx.beginPath();slider_ctx.moveTo(0,height-10);slider_ctx.lineTo(width,height-10);\
  299.  slider_ctx.moveTo(px-10,10);slider_ctx.lineTo(px+10,10);slider_ctx.lineTo(px,height-10);\
  300.  slider_ctx.lineTo(px-10,10);slider_ctx.closePath();slider_ctx.stroke();slider_ctx.fill();\
  301.  value = (px - rcenter)/width*(max - min);\
  302.  if( display > 0 ){show_slider_value(value,display);};\
  303.  var dx = px - xcenter;xcenter = px;\
  304.  slider_show_it(XYR,dx,value,slider_id);\
  305. };\
  306. };",canvas_root_id);
  307.   }
  308.   if( anim == 1){
  309.     fprintf(js_include_file,"\n/* add_anim_slider */\
  310. function animslider(XYR,text,slider_id ,width,height,linewidth,fillcolor,strokecolor,opacity,min,max,fontfamily,display)\
  311. {\
  312. document.addEventListener('readystatechange',function(event){\
  313.  if(event.target.readyState === 'complete'){\
  314.   var value= 0;\
  315.   var timer = setInterval(function(){\
  316.    value++;slider_show_it(XYR,value,value,slider_id);\
  317.    if( value > width ){clearInterval( timer );}\
  318.   },240);\
  319.  };\
  320. },false);\
  321. };");
  322.   }
  323.  
  324.   if( anim == 2 ){/* use mouse in stead of a X|Y slider... external images -via command 'copy' NOT supported !! need to add 'copy' to dragstuff library or introduce another command*/
  325.     fprintf(js_include_file,"\n/* add group move_ */\
  326. if( typeof( slidergroup) !== 'object'){var slidergroup = [];};\
  327. var move_group = function(num){\
  328. canvas_div.addEventListener( 'mousemove' ,slidegroup_m,false);\
  329. canvas_div.addEventListener( 'mousedown' ,slidegroup_d,false);\
  330. canvas_div.addEventListener( 'mouseup'   ,slidegroup_u,false);\
  331. canvas_div.addEventListener( 'touchstart', function(e){ e.preventDefault();slidegroup_d(e.changedTouches[0]);},false);\
  332. canvas_div.addEventListener( 'touchend',   function(e){ e.preventDefault();slidegroup_u(e.changedTouches[0]);},false);\
  333. canvas_div.addEventListener( 'touchmove' ,function(e){ e.preventDefault();slidegroup_m(e.changedTouches[0]);},false);\
  334. var slide_start = false;\
  335. function slidegroup_d(e){slide_start = true;};\
  336. function slidegroup_u(e){slide_start = false;};\
  337. function slidegroup_m(e){\
  338.  if(!slide_start){return;};\
  339.  var xy;var d_x;var d_y;var len = slidergroup.length;var use_xml = false;var once = 1;\
  340.  for(var i = 0;i < len;i++){\
  341.   use_xml = false;\
  342.   if( typeof(slidergroup[i]) === 'object' ){\
  343.    var obj = slidergroup[i];\
  344.    if( obj.use_slider == num ){\
  345.     if( typeof(obj.type) !== 'number' ){use_xml = true;};\
  346.     xy = getMouse(e,dragstuff.canvas);\
  347.     if( once == 1 ){ d_x = xy.x - obj.x[0];d_y = xy.y - obj.y[0];once = 0;};\
  348.     obj = move(obj,d_x,d_y);\
  349.     if(obj.use_snap != 0 ){var lx = (obj.x).length;for(var t = 0;t < lx;t++){var xy = multisnap_check(obj.x[t],obj.y[t],obj.use_snap);obj.x[t] = xy[0];obj.y[t] = xy[1];};};\
  350.     dragdrop_reply[obj.object_cnt].x = obj.x;dragdrop_reply[obj.object_cnt].y = obj.y;\
  351.     if( use_xml ){obj.onclick = 5;draw_xml(obj);}else{dragstuff.selection = null;dragstuff.draw();dragstuff.valid = false;};\
  352.    };\
  353.   };\
  354.  };\
  355.  dragstuff.valid = true;\
  356. };\
  357. };");
  358.   }
  359.  
  360. }
  361. /*      dragdrop_reply[obj.object_cnt] = obj;
  362. */
  363. /*
  364. adds inputfield for x-value: returns the js-calculated y-value after click on 'OK' button
  365. draws a non-configurable crosshair on this calculated location
  366. */
  367. void add_calc_y(char *jsmath,int font_size,char *css_class){
  368.   fprintf(js_include_file,"\n/* add_calc_y */\
  369. use_jsmath=1;\
  370. function add_calc_y(){\
  371. if( wims_status == \"done\" ){return;};\
  372. var fun = to_js_math(\"%s\");if(fun == null){return;};\
  373. function eval_jsmath(x){return parseFloat(eval(fun));};\
  374. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  375. var calc_div = document.createElement('div');\
  376. calc_div.id = \"calc_div\";\
  377. tooltip_div.appendChild(calc_div);\
  378. var label_x = \"x\";var label_y = \"y\";\
  379. if( typeof(xaxislabel) !== 'undefined' ){label_x = xaxislabel;}\
  380. if( typeof(yaxislabel) !== 'undefined' ){label_y = yaxislabel;}\
  381. calc_div.innerHTML=\"<br><span style='font-style:italic;font-size:%dpx'>\"+label_x+\" : <input type='text' size='4' value='' id='calc_input_x' style='%s'>&nbsp;\"+ label_y+\" : <input type='text' size='5' value='' id='calc_output_y' style='%s' readonly><input id='calc_button' type='button' value='OK' onclick=''  style='color:red;background-color:lightblue;'></span> \";\
  382. var calc_button = document.getElementById(\"calc_button\");\
  383. calc_button.addEventListener(\"mousedown\",show_it,false);\
  384. calc_button.addEventListener(\"touchstart\", function(e){ e.preventDefault();show_it(e.changedTouches[0]);},false);\
  385. function show_it(){\
  386.  var x_value=document.getElementById(\"calc_input_x\").value;\
  387.  var y_value = eval_jsmath(x_value);\
  388.  document.getElementById(\"calc_output_y\").value = y_value;\
  389.  if(isNaN(y_value)){return;};\
  390.  var canvas = create_canvas%d(123,xsize,ysize);\
  391.  var ctx = canvas.getContext(\"2d\");\
  392.  draw_crosshairs(ctx,[x2px(x_value)],[y2px(y_value)],1,5,\"#000000\",1,0,0,0,[0,0]);return;\
  393. };\
  394. };\
  395. ;add_calc_y();",jsmath,canvas_root_id,font_size,css_class,css_class,canvas_root_id);
  396. }
  397. /*
  398.  x-value of the mouse will be used to calculate via javascript the corresponding y-value using the verbatim js-math function
  399.  a configurable crosshair and vertical/horizontal crosshair lines will be drawn
  400.  function is called "use_mouse_coordinates() and thus can not be combined with command 'mouse'
  401. */
  402. void add_trace_js_mouse(int canvas_cnt, char *stroke_color, char *jsmath,
  403.   int font_size, double stroke_opacity, int line_width,
  404.   int crosshair_size,char *css_class){
  405.     fprintf(js_include_file,"\n/* add_trace_jsmath */\
  406. use_jsmath=1;\
  407. function use_trace_jsmath(){\
  408. if( wims_status == \"done\" ){return;};\
  409. var label_x = \"x\";var label_y = \"y\";\
  410. if( typeof(xaxislabel) !== 'undefined' ){label_x = xaxislabel;}\
  411. if( typeof(yaxislabel) !== 'undefined' ){label_y = yaxislabel;}\
  412. var trace_canvas = create_canvas%d(%d,xsize,ysize);\
  413. var trace_context = trace_canvas.getContext(\"2d\");\
  414. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  415. var trace_div = document.createElement('div');\
  416. trace_div.id = \"trace_div\";\
  417. tooltip_div.appendChild(trace_div);\
  418. trace_div.innerHTML = \"<br><span style='font-style:italic;font-size:%dpx'>\"+label_x+\" : <input type='text' size='4' value='' id='trace_input_x' style='%s'>\"+label_y+\" : <input type='text' size='5' value='' id='trace_input_y' style='%s' readonly></span> \";\
  419. canvas_div.addEventListener(\"mousemove\",trace,false);\
  420. canvas_div.addEventListener(\"touchmove\",function(e){ e.preventDefault();trace(e.changedTouches[0]);},false);\
  421. var fun = to_js_math(\"%s\");if(fun == null){return;};\
  422. function eval_jsmath(x){return parseFloat(eval(fun));};\
  423. function trace(evt){\
  424.  var mouse = getMouse(evt,trace_canvas);\
  425.  var x_px = mouse.x;\
  426.  var x = px2x(x_px);\
  427.  var y = eval_jsmath(x);\
  428.  if(isNaN(y)){return;};\
  429.  var y_px = y2px(y);\
  430.  trace_context.clearRect(0,0,xsize,ysize);\
  431.  draw_crosshairs(trace_context,[x_px],[y_px],%d,%d,\"%s\",%f,0,0,0,[0,0]);\
  432.  document.getElementById(\"trace_input_x\").value = x;\
  433.  document.getElementById(\"trace_input_y\").value = y;\
  434. };\
  435. return;\
  436. };use_trace_jsmath();",canvas_root_id,canvas_cnt,canvas_root_id,font_size,css_class,css_class,jsmath,line_width,crosshair_size,stroke_color,stroke_opacity);
  437.   }
  438.  
  439. /*
  440. add a table with 2 textarea's labeled 'x' 'y' ( or 'xlabel' 'ylabel' if defined)
  441. add two buttons: OK and NOK (OK draws; NOK will delete last item pair from userdraw_x / userdraw_y array's
  442. */
  443. void add_textarea_xy(char *css_class){
  444.   fprintf(js_include_file,"\n/* add_textarea_xy */\
  445. function add_textarea_xy(){\
  446. if( wims_status == \"done\" ){return;};\
  447. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  448. var textarea_div = document.createElement('div');\
  449. textarea_div.id = \"textarea_div\";\
  450. tooltip_div.appendChild(textarea_div);\
  451. var label_x = \"x\";var label_y = \"y\";\
  452. if( typeof(xaxislabel) !== 'undefined' ){label_x = xaxislabel;}\
  453. if( typeof(yaxislabel) !== 'undefined' ){label_y = yaxislabel;}\
  454. textarea_div.innerHTML=\"\
  455. <table style=\'border:1px solid black;background-color:#ffffa0\' >\
  456. <tr>\
  457. <td><input id='textarea_ok_button' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;'></td>\
  458. <td><input id='textarea_nok_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'></td>\
  459. </tr>\
  460. <tr>\
  461. <td><em>\"+label_x+\"</em></td>\
  462. <td><em>\"+label_y+\"</em></td>\
  463. </tr>\
  464. <tr>\
  465. <td><textarea rows='5' cols='2' id='userinput_x' style='%s' ></textarea></td>\
  466. <td><textarea rows='5' cols='2' id='userinput_y' style='%s' ></textarea></td>\
  467. </tr>\
  468. </table>\";\
  469. var textarea_ok_button = document.getElementById(\"textarea_ok_button\");\
  470. var textarea_nok_button = document.getElementById(\"textarea_nok_button\");\
  471. textarea_ok_button.addEventListener(\"mousedown\",function(e){redraw_userdraw();return;},false);\
  472. textarea_nok_button.addEventListener(\"mousedown\",function(e){remove_last();return;},false);\
  473. return;\
  474. };add_textarea_xy();",canvas_root_id,css_class,css_class);
  475.   }
  476.  
  477. /*
  478. */
  479. void add_setlimits(int font_size,char *css_class){
  480.   fprintf(js_include_file,"\n/* add_setlimits */\
  481. function use_setlimits(){\
  482. if( wims_status == \"done\" ){return;};\
  483. var label_x = \"x\";var label_y = \"y\";\
  484. if( typeof(xaxislabel) !== 'undefined' ){label_x = xaxislabel;}\
  485. if( typeof(yaxislabel) !== 'undefined' ){label_y = yaxislabel;}\
  486. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  487. var setlim_div = document.createElement('div');\
  488. setlim_div.id = \"setlim_div\";\
  489. tooltip_div.appendChild(setlim_div);\
  490. setlim_div.innerHTML=\"<br><span style='font-style:italic;font-size:%dpx'>\"+label_x+\"min = <input type='text' size='4' value='\"+xmin+\"' id='userinput_xmin' style='%s'> \"+label_x+\"max = <input type='text' size='4' value='\"+xmax+\"' id='userinput_xmax' style='%s'><br>\"+label_y+\"min = <input type='text' size='4' value='\"+ymin+\"' id='userinput_ymin' style='%s'> \"+label_y+\"max = <input type='text' size='4' value='\"+ymax+\"' id='userinput_ymax' style='%s'><br><input id='set_limits' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;'>\";\
  491. var setlimit_button = document.getElementById(\"set_limits\");\
  492. function set_limits(e){\
  493. xmin = safe_eval(document.getElementById('userinput_xmin').value);\
  494. xmax = safe_eval(document.getElementById('userinput_xmax').value);\
  495. ymin = safe_eval(document.getElementById('userinput_ymin').value);\
  496. ymax = safe_eval(document.getElementById('userinput_ymax').value);\
  497. if(xmin > xmax || ymin > ymax){alert(\"your limits are not correct...\");return;}\
  498. try{redraw_jsplot();}catch(e){console.log('redraw_jsplot failed:'+e);};\
  499. try{redraw_grid();}catch(e){console.log('redraw_grid failed:'+e);};\
  500. try{dragstuff.Zoom(xmin,xmax,ymin,ymax)}catch(e){console.log('zooming dragstuff failed:'+e);};return;};\
  501. setlimit_button.addEventListener(\"mousedown\",function(e){set_limits();},false);\
  502. };use_setlimits();",canvas_root_id,font_size,css_class,css_class,css_class,css_class);
  503. }
  504.  
  505. void add_input_jsfunction(char *css_class,char *input_label,int input_cnt,char *stroke_color,float stroke_opacity,int line_width,int use_dashed,int dashtype0,int dashtype1,int font_size){
  506.   fprintf(js_include_file,"\n/* add_input_jsfunction */\
  507. function clear_jsfunction(canvas_plot_id,input_field){\
  508. try{\
  509.  var canvas_plot = document.getElementById(\"wims_canvas%d\"+canvas_plot_id);\
  510.  var canvas_plot_ctx = canvas_plot.getContext(\"2d\");\
  511.  if( confirm(\"clear function plot?\") ){\
  512.   canvas_plot_ctx.clearRect(0,0,xsize,ysize);\
  513.   document.getElementById(input_field).value = \"\";\
  514.  };\
  515.  return;\
  516. }catch(e){alert(e+\"nothing to remove...\");};\
  517. return;\
  518. };\
  519. function add_input_jsfunction(input_cnt,css_class,input_label,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1){\
  520. var canvas_plot_id = %d+input_cnt;\
  521. var label = input_label[input_cnt];\
  522. if( typeof(multistrokecolors) === 'object'){ stroke_color = multistrokecolors[input_cnt];};\
  523. var input_field = \"canvas_input\"+input_cnt;\
  524. var update_button_id = \"update_button\"+input_cnt;\
  525. var delete_button_id = \"delete_button\"+input_cnt;\
  526. if( wims_status == \"done\" ){return;};\
  527. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  528. var input_jsfunction_div = document.createElement('div');\
  529. input_jsfunction_div.id = \"input_jsfunction_div\"+input_cnt;\
  530. tooltip_div.appendChild(input_jsfunction_div);\
  531. input_jsfunction_div.innerHTML+=\"<br><span style='font-style:italic;font-size:%dpx;color:rgb(\"+stroke_color+\")'><b>\"+label+\" <input type='text' size='16' value='' id='\"+input_field+\"' style='\"+css_class+\"'></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> \";\
  532. var update_button = document.getElementById(update_button_id);\
  533. var delete_button = document.getElementById(delete_button_id);\
  534. 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,0,0,300,0,1);return;},false);\
  535. delete_button.addEventListener(\"mousedown\",function(e){clear_jsfunction(canvas_plot_id,input_field);return;},false);\
  536. };\
  537. add_input_jsfunction(%d,\"%s\",%s,%d,\"%s\",%.2f,%d,%d,%d);",canvas_root_id,USERDRAW_JSPLOT,canvas_root_id,font_size,input_cnt,css_class,input_label,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  538. }
  539. /*
  540. adds 2 inputfields (x:y) and 'ok' | 'nok' button
  541. these are used for user drawing with inputfields...
  542. function update_me(){\
  543.  var x = safe_eval(document.getElementById('userinput_x').value);\
  544.  var y = safe_eval(document.getElementById('userinput_y').value);\
  545.  userdraw_x.push(x2px(x));userdraw_y.push(y2px(y));\
  546.  return;\
  547. };\
  548. */
  549. void add_input_xy(int font_size,char *css_class){
  550.   fprintf(js_include_file,"\n/* add_input_xy */\
  551. function add_input_xy(){\
  552. if( wims_status == \"done\" ){return;};\
  553. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  554. var input_xy_div = document.createElement('div');\
  555. input_xy_div.id = \"input_xy_div\";\
  556. tooltip_div.appendChild(input_xy_div);\
  557. var label_x = \"x\";var label_y = \"y\";\
  558. input_xy_div.innerHTML=\"<br><span style='font-style:italic;font-size:%dpx'><b>( <input type='text' size='5' value='' id='userinput_x' style='%s'> : <input type='text' size='5' value='' id='userinput_y' style='%s'> )</b><input id='update_button' type='button' value='OK' onclick=''  style='color:red;background-color:lightblue;'><input id='delete_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'></span> \";\
  559. var update_button = document.getElementById(\"update_button\");\
  560. var delete_button = document.getElementById(\"delete_button\");\
  561. update_button.addEventListener(\"mousedown\",function(e){update_me();redraw_userdraw();return;},false);\
  562. delete_button.addEventListener(\"mousedown\",function(e){remove_last();return;},false);\
  563. };add_input_xy();",canvas_root_id,font_size,css_class,css_class);
  564. }
  565.  
  566. /* adds 4 inputfields (x1:y1) --- (x2:y2) and 'ok' + 'nok' button */
  567. void add_input_x1y1x2y2(int font_size,char *css_class){
  568.   fprintf(js_include_file,"\n/* add_input_x1y1x2y2 */\
  569. function add_input_x1y1x2y2(){\
  570. if( wims_status == \"done\" ){return;};\
  571. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  572. var input_x1y1x2y2_div = document.createElement('div');\
  573. input_x1y1x2y2_div.id = \"input_x1y1x2y2_div\";\
  574. tooltip_div.appendChild(input_x1y1x2y2_div);\
  575. input_x1y1x2y2_div.innerHTML=\"<br><span style='font-size:%dpx'><b>( <input type='text' size='5' value='' id='userinput_x1' style='%s'> : <input type='text' size='5' value='' id='userinput_y1' style='%s'> ) ----- ( <input type='text' size='5' value='' id='userinput_x2' style='%s'> : <input type='text' size='5' value='' id='userinput_y2' style='%s'> )</b><input id='update_button' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;'><input id='delete_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'></span> \";\
  576. var update_button = document.getElementById(\"update_button\");\
  577. var delete_button = document.getElementById(\"delete_button\");\
  578. update_button.addEventListener(\"mousedown\",function(e){redraw_userdraw();return;},false);\
  579. delete_button.addEventListener(\"mousedown\",function(e){remove_last();return;},false);\
  580. };add_input_x1y1x2y2();",canvas_root_id,font_size,css_class,css_class,css_class,css_class);
  581. }
  582.  
  583. /* adds 3 inputfields Center (x:y) Radius r and 'ok'+'nok' buttons */
  584. void add_input_xyr(int font_size,char *css_class){
  585.   fprintf(js_include_file,"\n/* add_input_xyr */\
  586. function add_input_xyr(){\
  587. if( wims_status == \"done\" ){return;};\
  588. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  589. var input_xyr_div = document.createElement('div');\
  590. input_xyr_div.id = \"input_xyr_div\";\
  591. tooltip_div.appendChild(input_xyr_div);\
  592. input_xyr_div.innerHTML=\"<br><span style='font-style:italic;font-size:%dpx'><b>Center : ( <input type='text' size='5' value='' id='userinput_x' style='%s'> : <input type='text' size='5' value='' id='userinput_y' style='%s'> ) Radius : <input type='text' size='5' value='' id='userinput_r' style='%s'></b><input id='update_button' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;'><input id='delete_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'></span> \";\
  593. var update_button = document.getElementById(\"update_button\");\
  594. var delete_button = document.getElementById(\"delete_button\");\
  595. update_button.addEventListener(\"mousedown\",function(e){redraw_userdraw();return;},false);\
  596. delete_button.addEventListener(\"mousedown\",function(e){remove_last();return;},false);\
  597. };add_input_xyr();",canvas_root_id,font_size,css_class,css_class,css_class);
  598. }
  599.  
  600. /* THESE JS-FUNCTIONS COULD BE MADE LESS COPY & PASTE "PROGRAMMING" */
  601.  
  602. /* draw circle(s) / point(s) via 3 inputfields */
  603. void add_input_circle(int type,int num){
  604. /*
  605. type = 0 : a point ...radius is fixed
  606. type = 1 : a circle ... read inputfield userinput_r
  607. num = 1 : a single point / circle
  608. num = 2 : multiple points / circles
  609. */
  610.   fprintf(js_include_file,"\n/* add_input_circle */\
  611. function user_redraw(t){\
  612. var type = %d;\
  613. var num = %d;\
  614. var lu = userdraw_x.length;\
  615. if( t == -1 && lu > 0){userdraw_x.splice(lu-1,1);userdraw_y.splice(lu-1,1);if(type == 1){userdraw_radius.splice(lu-1,1);};context_userdraw.clearRect(0,0,xsize,ysize);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);xy_cnt = userdraw_x.length;return;};\
  616. var add_x = safe_eval( document.getElementById(\"userinput_x\").value );\
  617. var add_y = safe_eval( document.getElementById(\"userinput_y\").value );\
  618. if( add_x != null && add_y != null ){if( type == 1 ){var add_r = safe_eval( document.getElementById(\"userinput_r\").value );if( add_r == null ){alert(\"illegal radius input \");return;};if( num == 1 ){userdraw_radius[0] = parseInt(Math.abs(xsize*(add_r)/(xmax - xmin)));}else{userdraw_radius.push( parseInt(Math.abs(xsize*(add_r)/(xmax - xmin))) );};}else{userdraw_radius[lu] = userdraw_radius[0];};if( num == 1 ){userdraw_x[0] = x2px(add_x);userdraw_y[0] = y2px(add_y);xy_cnt=1;}else{userdraw_x.push(x2px(add_x));userdraw_y.push(y2px(add_y));xy_cnt = userdraw_x.length;};context_userdraw.clearRect(0,0,xsize,ysize);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);};\
  619. return;\
  620. };",type,num);
  621. }
  622. /* draw crosshairs via inputfields x/y */
  623. void add_input_crosshair(int num){
  624.   fprintf(js_include_file,"\n/* add_input_crosshair */\
  625. function user_redraw(t){\
  626. var lu = userdraw_x.length;\
  627. if( t == -1 && lu > 0){\
  628.  userdraw_x.splice(lu-1,1);\
  629.  userdraw_y.splice(lu-1,1);\
  630.  context_userdraw.clearRect(0,0,xsize,ysize);\
  631.  draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  632.  return;\
  633. };\
  634. var add_x = safe_eval( document.getElementById(\"userinput_x\").value );\
  635. var add_y = safe_eval( document.getElementById(\"userinput_y\").value );\
  636. if( add_x != null && add_y != null ){\
  637.  if( %d == 1 ){\
  638.   userdraw_x[0] = x2px(add_x);\
  639.   userdraw_y[0] = y2px(add_y);\
  640.  } else {\
  641.    userdraw_x[lu] = x2px(add_x);\
  642.    userdraw_y[lu] = y2px(add_y);\
  643.    xy_cnt++;\
  644.  };\
  645.  context_userdraw.clearRect(0,0,xsize,ysize);\
  646.  draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  647. };\
  648. return;\
  649. };",num);
  650. }
  651.  
  652. /* draw arrows via inputfields x/y */
  653. void add_input_arrow(int num){
  654.   fprintf(js_include_file,"\n/* add_input_arrow */\
  655. function user_redraw(t){\
  656. var lu = userdraw_x.length;\
  657. if( t == -1 && lu > 1 ){\
  658.  userdraw_x.splice(lu-2,2);\
  659.  userdraw_y.splice(lu-2,2);\
  660.  context_userdraw.clearRect(0,0,xsize,ysize);\
  661.  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]);\
  662.  return;\
  663. };\
  664. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  665. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  666. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  667. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  668. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  669.  if( %d == 2 ){\
  670.    var s = userdraw_x.length;\
  671.    userdraw_x[lu] = x2px(add_x1);\
  672.    userdraw_y[lu] = y2px(add_y1);\
  673.    userdraw_x[lu+1] = x2px(add_x2);\
  674.    userdraw_y[lu+1] = y2px(add_y2);\
  675.  } else {\
  676.   userdraw_x[0] = x2px(add_x1);\
  677.   userdraw_y[0] = y2px(add_y1);\
  678.   userdraw_x[1] = x2px(add_x2);\
  679.   userdraw_y[1] = y2px(add_y2);\
  680.  };\
  681.  context_userdraw.clearRect(0,0,xsize,ysize);\
  682.  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]);\
  683. };\
  684. return;\
  685. };",num);
  686. }
  687.  
  688. /* draw line via inputfields x/y */
  689. void add_input_line(int num){
  690.   fprintf(js_include_file,"\n/* line via inputfields  */\
  691. function user_redraw(t){\
  692. var lu = userdraw_x.length;\
  693. if( t == -1 && lu > 1){\
  694.  userdraw_x.splice(lu-2,2);\
  695.  userdraw_y.splice(lu-2,2);\
  696.  context_userdraw.clearRect(0,0,xsize,ysize);\
  697.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,1,0,0);\
  698.  return;\
  699. };\
  700. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  701. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  702. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  703. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  704. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  705.  if( %d == 2 ){\
  706.    userdraw_x[lu] = x2px(add_x1);\
  707.    userdraw_y[lu] = y2px(add_y1);\
  708.    userdraw_x[lu+1] = x2px(add_x2);\
  709.    userdraw_y[lu+1] = y2px(add_y2);\
  710.  } else {\
  711.   userdraw_x[0] = x2px(add_x1);\
  712.   userdraw_y[0] = y2px(add_y1);\
  713.   userdraw_x[1] = x2px(add_x2);\
  714.   userdraw_y[1] = y2px(add_y2);\
  715.  };\
  716.  context_userdraw.clearRect(0,0,xsize,ysize);\
  717.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,1,0,0);\
  718. };\
  719. return;\
  720. };",num);
  721. }
  722.  
  723.  
  724. /* draw polyline via inputfields x/y */
  725. void add_input_polyline(){
  726.   fprintf(js_include_file,"\n/* polyline_segment via inputfields */\
  727. function user_redraw(t){\
  728. var lu = userdraw_x.length;\
  729. cnt = 1;\
  730. if( t == -1 && lu > 0){\
  731.  userdraw_x.splice(lu-1,1);\
  732.  userdraw_y.splice(lu-1,1);\
  733.  context_userdraw.clearRect(0,0,xsize,ysize);\
  734.  draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  735.  return;\
  736. };\
  737. var add_x = safe_eval( document.getElementById(\"userinput_x\").value );\
  738. var add_y = safe_eval( document.getElementById(\"userinput_y\").value );\
  739. if(add_x != null && add_y != null ){\
  740.  userdraw_x.push(x2px(add_x));\
  741.  userdraw_y.push(y2px(add_y));\
  742.  context_userdraw.clearRect(0,0,xsize,ysize);\
  743.  draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  744. };\
  745. return;\
  746. };");
  747. }
  748. /* draw segment(s) via inputfields x/y */
  749. void add_input_segment(int num){
  750.   fprintf(js_include_file,"\n/* add_input_segment */\
  751. function user_redraw(t){\
  752. var lu = userdraw_x.length;\
  753. if( t == -1 && lu > 1){\
  754.  userdraw_x.splice(lu-2,2);\
  755.  userdraw_y.splice(lu-2,2);\
  756.  context_userdraw.clearRect(0,0,xsize,ysize);\
  757.  draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  758.  return;\
  759. };\
  760. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  761. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  762. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  763. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  764. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  765.  if( %d == 2 ){\
  766.    var s = userdraw_x.length;\
  767.    userdraw_x[s] = x2px(add_x1);\
  768.    userdraw_y[s] = y2px(add_y1);\
  769.    userdraw_x[s+1] = x2px(add_x2);\
  770.    userdraw_y[s+1] = y2px(add_y2);\
  771.  } else {\
  772.   userdraw_x[0] = x2px(add_x1);\
  773.   userdraw_y[0] = y2px(add_y1);\
  774.   userdraw_x[1] = x2px(add_x2);\
  775.   userdraw_y[1] = y2px(add_y2);\
  776.  };\
  777.  context_userdraw.clearRect(0,0,xsize,ysize);\
  778.  draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  779. };\
  780. return;\
  781. };",num);
  782. }
  783.  
  784. /* draw demilines(s) via inputfields x/y */
  785. void add_input_demiline(int num){
  786.   fprintf(js_include_file,"\n/* add_input_segment */\
  787. function user_redraw(t){\
  788. var lu = userdraw_x.length;\
  789. if( t == -1 && lu > 1){\
  790.  userdraw_x.splice(lu-2,2);\
  791.  userdraw_y.splice(lu-2,2);\
  792.  context_userdraw.clearRect(0,0,xsize,ysize);\
  793.  draw_demilines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  794.  return;\
  795. };\
  796. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  797. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  798. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  799. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  800. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  801.  if( %d == 2 ){\
  802.    var s = userdraw_x.length;\
  803.    userdraw_x[s] = x2px(add_x1);\
  804.    userdraw_y[s] = y2px(add_y1);\
  805.    userdraw_x[s+1] = x2px(add_x2);\
  806.    userdraw_y[s+1] = y2px(add_y2);\
  807.  } else {\
  808.   userdraw_x[0] = x2px(add_x1);\
  809.   userdraw_y[0] = y2px(add_y1);\
  810.   userdraw_x[1] = x2px(add_x2);\
  811.   userdraw_y[1] = y2px(add_y2);\
  812.  };\
  813.  context_userdraw.clearRect(0,0,xsize,ysize);\
  814.  draw_demilines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  815. };\
  816. return;\
  817. };",num);
  818. }
  819.  
  820. void add_clear_button(char *css_class,char *button_text){
  821. /* 25/11/2014 added clearing of reply array
  822. all members will be set to 0 eg reply[0] = 0 , reply[1] = 0 ...
  823. hope this does not interfere with existing work...
  824. */
  825. /*
  826. 5/2016 changed  to 'setAttribute()' because of trouble on Chromium/Safari/IE
  827. 10/2016 corrected contex-reset-flaw when using "userdraw text,color" and added inputs to the things we can remove
  828. 7/2017 added 'userdraw clickfill,color' to removable things...one user_filling per click
  829.  
  830. 7/2022: preserve all div's with html ('<' && '>') eg mathml,katex,html and all external objects placed with function 'place_image_on_canvas(id)'
  831. ...hope this does not interfere with other things
  832. https://wimsedu.info/?topic=geometrie-interactive-avec-canvasdraw
  833. */
  834.   fprintf(js_include_file,"\n/* add clear button */\
  835. clear_draw_area%d = function(){\
  836. if(typeof(fill_canvas_no) === 'number'){\
  837.  var chk = document.getElementById('wims_canvas%d'+fill_canvas_no);\
  838.  if( chk ){\
  839.   var fill_ctx = chk.getContext(\"2d\");fill_ctx.clearRect(0,0,xsize,ysize);\
  840.   fill_canvas_no--;userdraw_x.splice(p,1);userdraw_y.splice(p,1);userdraw_radius.splice(p,1);\
  841.   return;\
  842.  };\
  843. };\
  844. if( typeof(context_userdraw) === 'object' ){\
  845.  if(document.getElementById(canvas_div.lastChild.id).tagName == 'DIV'){\
  846.   var mathtxt = document.getElementById(canvas_div.lastChild.id).innerHTML;\
  847.   if(mathtxt.indexOf('<') == -1 && mathtxt.indexOf('>') == -1 || canvas_div.lastChild.id.indexOf('placed') != -1){\
  848.    document.getElementById(canvas_div.lastChild.id).innerHTML = null;\
  849.    canvas_div.removeChild(document.getElementById(canvas_div.lastChild.id));\
  850.   };\
  851.  };\
  852.  context_userdraw.clearRect(0,0,xsize,ysize);\
  853.  if( typeof(userdraw_text) !== 'undefined'){ userdraw_text = []; };\
  854.  if( document.getElementById(\"canvas_input0\") ){\
  855.   var p = 0;var inp;\
  856.   while( document.getElementById(\"canvas_input\"+p) ){\
  857.    inp = document.getElementById(\"canvas_input\"+p);\
  858.    canvas_div.removeChild(inp);\
  859.    p++;\
  860.   };\
  861.   input_cnt = 0;start_input_cnt = 0; \
  862.  };\
  863.  userdraw_x = [];userdraw_y = [];userdraw_radius = [];xy_cnt = 0;\
  864. };\
  865. if( typeof(external_ctx) === 'object'){\
  866.  external_ctx.clearRect(0,0,xsize,ysize);\
  867.  for(var p = 0 ; p < userdraw_x.length; p++){\
  868.   userdraw_x[p] = null;userdraw_y[p] = null;\
  869.  };\
  870. };\
  871. return;\
  872. };\
  873. function add_clear_button(){\
  874. var tooltip_placeholder_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  875. var button = document.createElement('input');\
  876. button.setAttribute(\"type\" , \"button\");\
  877. button.setAttribute(\"id\" , \"clearbutton%d\");\
  878. button.setAttribute(\"class\" , \"%s\");\
  879. button.setAttribute(\"value\" , \"%s\");\
  880. button.setAttribute(\"onclick\",\"clear_draw_area%d()\");\
  881. tooltip_placeholder_div.appendChild(button);\
  882. };\
  883. add_clear_button();",canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,css_class,button_text,canvas_root_id);
  884. }
  885.  
  886. void add_color_palette(char *css_class){
  887.   fprintf(js_include_file,"\n/* add color palette */\
  888. function add_color_palette(){\
  889. var tooltip_placeholder_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  890. var clen = palettecolors.length;\
  891. for( var p = 0 ; p < clen ; p++ ){\
  892.  var button = document.createElement('input');\
  893.  button.setAttribute('type', 'button');\
  894.  button.setAttribute('value', '  ');\
  895.  button.setAttribute('id',palettecolors[p]);\
  896.  button.setAttribute('style', \"%s\");\
  897.  button.setAttribute('style','background-color:rgb('+palettecolors[p]+')');\
  898.  button.setAttribute(\"backgroundColor\",palettecolors[p]);\
  899.  button.addEventListener('mousedown',function(e){var id = this.getAttribute('id');multifillcolors[0]=id;multifillcolors[1]=id;multifillcolors[2]=id;},false);\
  900.  tooltip_placeholder_div.appendChild(button);\
  901. };\
  902. };\
  903. add_color_palette();\
  904. ",canvas_root_id,css_class);
  905. }
  906.  
  907.  
  908. struct colors colors[]={
  909.  {"#FF0000","red","255,0,0"},
  910.  {"#00FF00","lime","0,255,0"},
  911.  {"#0000FF","blue","0,0,255"},
  912.  {"#FFA500","orange","255,165,0"},
  913.  {"#E9967A","darksalmon","233,150,122"},
  914.  {"#F0FFFF","azure","240,255,255"},
  915.  {"#CD5C5C","indianred","205,92,92"},
  916.  {"#E0FFFF","lightcyan","224,255,255"},
  917.  {"#FFE4E1","mistyrose","255,228,225"},
  918.  {"#DC143C","crimson","220,20,60"},
  919.  {"#FFC0CB","pink","255,192,203"},
  920.  {"#FFD700","gold","255,215,0"},
  921.  {"#E6E6FA","lavender","230,230,250"},
  922.  {"#808080","gray","128,128,128"},
  923.  {"#F0F8FF","aliceblue","240,248,255"},
  924.  {"#C71585","mediumvioletred","199,21,133"},
  925.  {"#FFF0F5","lavenderblush","255,240,245"},
  926.  {"#DAA520","goldenrod","218,165,32"},
  927.  {"#FFB6C1","lightpink","255,182,193"},
  928.  {"#00FFFF","aqua","0,255,255"},
  929.  {"#FF69B4","hotpink","255,105,180"},
  930.  {"#00FFFF","cyan","0,255,255"},
  931.  {"#FF1493","deeppink","255,20,147"},
  932.  {"#7FFFD4","aquamarine","127,255,212"},
  933.  {"#FA8072","salmon","250,128,114"},
  934.  {"#DEB887","burlywood","222,184,135"},
  935.  {"#DB7093","palevioletred","219,112,147"},
  936.  {"#D2B48C","tan","210,180,140"},
  937.  {"#BDB76B","darkkhaki","189,183,107"},
  938.  {"#B22222","firebrick","178,34,34"},
  939.  {"#FF4500","orangered","255,69,0"},
  940.  {"#8B4513","saddlebrown","139,69,19"},
  941.  {"#FF8C00","darkorange","255,140,0"},
  942.  {"#FFFFE0","lightyellow","255,255,224"},
  943.  {"#FFFF00","yellow","255,255,0"},
  944.  {"#FFFACD","lemonchiffon","255,250,205"},
  945.  {"#F5F5DC","beige","245,245,220"},
  946.  {"#FFEFD5","papayawhip","255,239,213"},
  947.  {"#FAFAD2","lightgoldenrodyellow","250,250,210"},
  948.  {"#FFE4B5","moccasin","255,228,181"},
  949.  {"#B8860B","darkgoldenrod","184,134,11"},
  950.  {"#FFF8DC","cornsilk","255,248,220"},
  951.  {"#FFEBCD","blanchedalmond","255,235,205"},
  952.  {"#FFE4C4","bisque","255,228,196"},
  953.  {"#FFDEAD","navajowhite","255,222,173"},
  954.  {"#F5DEB3","wheat","245,222,179"},
  955.  {"#CD853F","peru","205,133,63"},
  956.  {"#D2691E","chocolate","210,105,30"},
  957.  {"#A0522D","sienna","160,82,45"},
  958.  {"#A52A2A","brown","165,42,42"},
  959.  {"#BC8F8F","rosybrown","188,143,143"},
  960.  {"#F08080","lightcoral","240,128,128"},
  961.  {"#FFA07A","lightsalmon","255,160,122"},
  962.  {"#8B0000","darkred","139,0,0"},
  963.  {"#800000","maroon","128,0,0"},
  964.  {"#FAA460","sandybrown","250,164,96"},
  965.  {"#FF7F50","coral","255,127,80"},
  966.  {"#FF6347","tomato","255,99,71"},
  967.  {"#FFDAB9","peachpuff","255,218,185"},
  968.  {"#EEE8AA","palegoldenrod","238,232,170"},
  969.  {"#F0E68C","khaki","240,230,140"},
  970.  {"#D8BFD8","thistle","216,191,216"},
  971.  {"#DDA0DD","plum","221,160,221"},
  972.  {"#FF00FF","fuchsia","255,0,255"},
  973.  {"#FF00FF","magenta","255,0,255"},
  974.  {"#EE82EE","violet","238,130,238"},
  975.  {"#DA70D6","orchid","218,112,214"},
  976.  {"#BA55D3","mediumorchid","186,85,211"},
  977.  {"#9370DB","mediumpurple","147,112,219"},
  978.  {"#8A2BE2","blueviolet","138,43,226"},
  979.  {"#9400D3","darkviolet","148,0,211"},
  980.  {"#9932CC","darkorchid","153,50,204"},
  981.  {"#8B008B","darkmagenta","139,0,139"},
  982.  {"#800080","purple","128,0,128"},
  983.  {"#4B0082","indigo","75,0,130"},
  984.  {"#483D8B","darkslateblue","72,61,139"},
  985.  {"#6A5ACD","slateblue","106,90,205"},
  986.  {"#7B68EE","mediumslateblue","123,104,238"},
  987.  {"#98FB98","palegreen","152,251,152"},
  988.  {"#ADFF2F","greenyellow","173,255,47"},
  989.  {"#7FFF00","chartreuse","127,255,0"},
  990.  {"#7CFC00","lawngreen","124,252,0"},
  991.  {"#00FF7F","springgreen","0,255,127"},
  992.  {"#00FA9A","mediumspringgreen","0,250,154"},
  993.  {"#90EE90","lightgreen","144,238,144"},
  994.  {"#32CD32","limegreen","50,205,50"},
  995.  {"#3CB371","mediumseagreen","60,179,113"},
  996.  {"#2E8B57","seagreen","46,139,87"},
  997.  {"#228B22","forestgreen","34,139,34"},
  998.  {"#008000","green","0,128,0"},
  999.  {"#006400","darkgreen","0,100,0"},
  1000.  {"#9ACD32","yellowgreen","154,205,50"},
  1001.  {"#6B8E23","olivedrab","107,142,35"},
  1002.  {"#808000","olive","128,128,0"},
  1003.  {"#556B2F","darkolivegreen","85,107,47"},
  1004.  {"#8FBC8F","darkseagreen","143,188,143"},
  1005.  {"#66CDAA","mediumaquamarine","102,205,170"},
  1006.  {"#20B2AA","lightseagreen","32,178,170"},
  1007.  {"#008B8B","darkcyan","0,139,139"},
  1008.  {"#008080","teal","0,128,128"},
  1009.  {"#AFEEEE","paleturquoise","175,238,238"},
  1010.  {"#40E0D0","turquoise","64,224,208"},
  1011.  {"#48D1CC","mediumturquoise","72,209,204"},
  1012.  {"#00CED1","darkturquoise","0,206,209"},
  1013.  {"#5F9EA0","cadetblue","95,158,160"},
  1014.  {"#4682B4","steelblue","70,130,180"},
  1015.  {"#B0C4DE","lightsteelblue","176,196,222"},
  1016.  {"#B0E0E6","powderblue","176,224,230"},
  1017.  {"#ADD8E6","lightblue","173,216,230"},
  1018.  {"#87CEEB","skyblue","135,206,235"},
  1019.  {"#87CEFA","lightskyblue","135,206,250"},
  1020.  {"#00BFFF","deepskyblue","0,191,255"},
  1021.  {"#1E90FF","dodgerblue","30,144,255"},
  1022.  {"#6495ED","cornflowerblue","100,149,237"},
  1023.  {"#4169E1","royalblue","65,105,225"},
  1024.  {"#0000CD","mediumblue","0,0,205"},
  1025.  {"#00008B","darkblue","0,0,139"},
  1026.  {"#000080","navy","0,0,128"},
  1027.  {"#191970","midnightblue","25,25,112"},
  1028.  {"#DCDCDC","gainsboro","220,220,220"},
  1029.  {"#D3D3D3","lightgrey","211,211,211"},
  1030.  {"#808080","grey","128,128,128"},
  1031.  {"#C0C0C0","silver","192,192,192"},
  1032.  {"#A9A9A9","darkgray","169,169,169"},
  1033.  {"#778899","lightslategray","119,136,153"},
  1034.  {"#708090","slategray","112,128,144"},
  1035.  {"#696969","dimgray","105,105,105"},
  1036.  {"#2F4F4F","darkslategray","47,79,79"},
  1037.  {"#0a0a0a","black","10,10,10"},
  1038.  {"#F5FFFA","mintcream","245,255,250"},
  1039.  {"#FFFFFF","white","255,255,255"},
  1040.  {"#F0FFF0","honeydew","240,255,240"},
  1041.  {"#F5F5F5","whitesmoke","245,245,245"},
  1042.  {"#F8F8FF","ghostwhite","248,248,255"},
  1043.  {"#FFFFF0","ivory","255,255,240"},
  1044.  {"#FFFAFA","snow","255,250,250"},
  1045.  {"#FFFAF0","floralwhite","255,250,240"},
  1046.  {"#FFF5EE","seashell","255,245,238"},
  1047.  {"#FDF5E6","oldlace","253,245,230"},
  1048.  {"#FAF0E6","linen","250,240,230"},
  1049.  {"#FAEBD7","antiquewhite","250,235,215"},
  1050.  };
  1051. int NUMBER_OF_COLORNAMES=(sizeof(colors)/sizeof(colors[0]));
  1052.  
  1053. /*.
  1054.   The filling is done in the connex component whih contains (xs,ys)
  1055.   of the set of points which have the same color as (xs,ys)
  1056.   in the case where border=false and which are in a color different of border
  1057.   if not (that is when border is a color).
  1058. */
  1059. void add_js_filltoborder(int canvas_type){
  1060.   fprintf(js_include_file,"\n/* command filltoborder */\
  1061. function filltoborder(xs,ys,border,color,fill_canvas_no,use_special_filling,fill_ctx){\
  1062.  document.body.style.cursor = 'wait';\
  1063.  let canvas = document.getElementById(\"wims_canvas%d%d\");\
  1064.  if (!canvas) return;\
  1065.  document.body.style.cursor = 'wait';\
  1066.  let ctx = canvas.getContext(\"2d\");\
  1067.  xs = parseInt(x2px(xs)); ys = parseInt(y2px(ys));\
  1068.  if (xs<0 || xs>=xsize || ys<0 || ys>=ysize)\
  1069.    {document.body.style.cursor = 'default'; return;};\
  1070.  let ps = xs+ys*xsize;\
  1071.  let image = ctx.getImageData(0, 0, xsize, ysize);\
  1072.  let iD = image.data;\
  1073.  function _getPixelColor(p) {return [iD[p],iD[p+1],iD[p+2],iD[p+3]];}\
  1074.  function _clearPixel(p) {for(let q=0; q<4; ++q) iD[p+q]=255;}\
  1075.  let _setPixel, _testColor;\
  1076.  if (use_special_filling) {\
  1077.    function _forcePixel(p,c) {for(let q=0; q<3; ++q) iD[p+q]=c[q]; iD[p+3]=255};\
  1078.    let fD = fill_ctx.getImageData(0, 0, xsize, ysize).data;\
  1079.    _setPixel = function(p) {_forcePixel(p,[fD[p],fD[p+1],fD[p+2],fD[p+3]])}\
  1080.  }\
  1081.  else {\
  1082.    function _forcePixel(p,c) {for(let q=0; q<3; ++q) iD[p+q]=c[q]; iD[p+3]=c[3]};\
  1083.    _setPixel = function(p) {_forcePixel(p,color);}\
  1084.  };\
  1085.  if(border){\
  1086.      _testColor = function(c)\
  1087.      {return Math.abs(c[0]-border[0])+Math.abs(c[1]-border[1])+Math.abs(c[2]-border[2])>3;}\
  1088.  }\
  1089.  else {\
  1090.      let cS = _getPixelColor(4*ps);\
  1091.      _testColor = function(c) {return c[0]==cS[0] && c[1]==cS[1] && c[2]==cS[2]}\
  1092.  }\
  1093.  let pad = new Array(xsize*ysize).fill(true);\
  1094.  pad[ps]=false;\
  1095.  let pStack = [ps];\
  1096.  let ct=0;\
  1097.  while (pStack.length) {\
  1098.    let p = pStack.shift();\
  1099.    if(!_testColor(_getPixelColor(4*p))) continue;\
  1100.    _setPixel(4*p);\
  1101.    ct++;\
  1102.    let x = p %% xsize, y = (p - x) / xsize;\
  1103.    if(x > 0 && pad[p-1]) {pad[p-1] = false; pStack.push(p-1)};\
  1104.    if(x < xsize-1 && pad[p+1]) {pad[p+1] = false; pStack.push(p+1)};\
  1105.    if(y > 0 && pad[p-xsize]) {pad[p-xsize] = false; pStack.push(p-xsize)};\
  1106.    if(y < ysize-1 && pad[p+xsize]) {pad[p+xsize] = false; pStack.push(p+xsize);};\
  1107.  };\
  1108.  var fill_canvas = create_canvas%d(fill_canvas_no,xsize,ysize);\
  1109.  var fill_canvas_ctx = fill_canvas.getContext(\"2d\");\
  1110.  fill_canvas_ctx.clearRect(0,0,xsize,ysize);\
  1111.  fill_canvas_ctx.putImageData(image, 0, 0);\
  1112.  document.body.style.cursor = 'default';\
  1113. };",canvas_root_id,canvas_type,canvas_root_id);
  1114. }
  1115.  
  1116. void add_js_ruler(double x,double y,double sizex,double sizey,char *font,
  1117. char *stroke_color,double stroke_opacity,char *fill_color,double fill_opacity,
  1118. int line_width,int dynamic,int use_snap){
  1119.  fprintf(js_include_file,"\n/* command ruler */\
  1120. var ruler_data = new Array(3);\
  1121. var ruler%d = function(){\
  1122.  var use_snap = %d;\
  1123.  var full = 2*Math.PI;\
  1124.  var once = true;\
  1125.  var canvas = create_canvas%d(3000,xsize,ysize);\
  1126.  var ctx = canvas.getContext(\"2d\");\
  1127.  var canvas_temp =  document.createElement(\"canvas\");\
  1128.  var size_x = xsize*(%f)/(xmax - xmin);\
  1129.  var size_y = ysize*(%f)/(ymax - ymin);\
  1130.  var dx = xsize/(xmax - xmin);\
  1131.  var dy = 0.8*ysize/(ymax - ymin);\
  1132.  canvas_temp.width = xsize;\
  1133.  canvas_temp.height = ysize;\
  1134.  var ctx_temp = canvas_temp.getContext(\"2d\");\
  1135.  var xcenter = x2px(%f);\
  1136.  var ycenter = y2px(%f);\
  1137.  var ruler_x = xcenter;\
  1138.  var ruler_y = ycenter;\
  1139.  ctx_temp.font = \"%s\";\
  1140.  ctx_temp.strokeStyle = \"rgba(%s,%f)\";\
  1141.  ctx_temp.fillStyle = \"rgba(%s,%f)\";\
  1142.  ctx_temp.lineWidth = %d;\
  1143.  ctx_temp.save();\
  1144.  if(once){\
  1145.   ctx_temp.beginPath();\
  1146.   ctx_temp.moveTo(ruler_x,ruler_y);\
  1147.   ctx_temp.lineTo(ruler_x+size_x,ruler_y);\
  1148.   ctx_temp.lineTo(ruler_x+size_x,ruler_y-size_y);\
  1149.   ctx_temp.lineTo(ruler_x,ruler_y-size_y);\
  1150.   ctx_temp.lineTo(ruler_x,ruler_y);\
  1151.   ctx_temp.closePath();\
  1152.   ctx_temp.fill();\
  1153.   ctx_temp.stroke();\
  1154.   ctx_temp.fillStyle = ctx_temp.strokeStyle;\
  1155.   var txtsize;\
  1156.   var num = 1;\
  1157.   for(var p = dx ; p < size_x ; p = p+dx){\
  1158.     txtsize = 0.5*(ctx_temp.measureText(num).width);\
  1159.     ctx_temp.fillText(num,ruler_x + p -txtsize,ruler_y - 0.9*dy);\
  1160.     num++;\
  1161.   };\
  1162.   ctx_temp.strokeStyle = \"rgba(0,0,255,0.6)\";\
  1163.   ctx_temp.lineWidth = 2;\
  1164.   for(var p = 0; p < size_x ; p = p+dx){\
  1165.    ctx_temp.beginPath();\
  1166.    ctx_temp.moveTo(ruler_x+p,ruler_y);\
  1167.    ctx_temp.lineTo(ruler_x+p,ruler_y-0.8*dy);\
  1168.    ctx_temp.closePath();\
  1169.    ctx_temp.stroke();\
  1170.   };\
  1171.   ctx_temp.strokeStyle = \"rgba(0,0,255,0.6)\";\
  1172.   ctx_temp.lineWidth = 1;\
  1173.   for(var p = 0; p < size_x ; p = p+0.5*dx){\
  1174.    ctx_temp.beginPath();\
  1175.    ctx_temp.moveTo(ruler_x+p,ruler_y);\
  1176.    ctx_temp.lineTo(ruler_x+p,ruler_y-0.6*dy);\
  1177.    ctx_temp.closePath();\
  1178.    ctx_temp.stroke();\
  1179.   };\
  1180.   ctx_temp.strokeStyle = \"rgba(255,0,0,0.6)\";\
  1181.   ctx_temp.lineWidth = 0.5;\
  1182.   for(var p = 0; p < size_x ; p = p+0.1*dx){\
  1183.    ctx_temp.beginPath();\
  1184.    ctx_temp.moveTo(ruler_x+p,ruler_y);\
  1185.    ctx_temp.lineTo(ruler_x+p,ruler_y-0.4*dy);\
  1186.    ctx_temp.closePath();\
  1187.    ctx_temp.stroke();\
  1188.   };\
  1189.   ctx_temp.drawImage(canvas,ruler_x,ruler_y);\
  1190.   once = false;\
  1191.  }",canvas_root_id,use_snap,canvas_root_id,sizex,sizey,x,y,font,stroke_color,stroke_opacity,fill_color,fill_opacity,line_width);
  1192.  
  1193.  if( dynamic == -1 ){
  1194.  fprintf(js_include_file,"\
  1195. ctx.drawImage(canvas_temp,0,0);\
  1196.   if(wims_status != \"done\"){\
  1197.    canvas_div.addEventListener( 'mouseup'   , ruler_stop,false);\
  1198.    canvas_div.addEventListener( 'mousedown' , ruler_start,false);\
  1199.    canvas_div.addEventListener( 'mousemove' , ruler_move,false);\
  1200.    canvas_div.addEventListener( 'touchstart', function(e){ e.preventDefault();ruler_start(e.changedTouches[0]);},false);\
  1201.    canvas_div.addEventListener( 'touchmove', function(e){ e.preventDefault();ruler_move(e.changedTouches[0]);},false);\
  1202.    canvas_div.addEventListener( 'touchend', function(e){ e.preventDefault();ruler_stop(e.changedTouches[0]);},false);\
  1203.   };\
  1204.   function ruler_stop(evt){\
  1205.    ruler_data[0] = ruler_x;\
  1206.    ruler_data[1] = ruler_y;\
  1207.    ruler_data[2] = angle;\
  1208.    return;\
  1209.   };\
  1210.   var ruler_object_cnt = 0;\
  1211.   function ruler_start(evt){\
  1212.    var mouse = getMouse(evt,canvas);\
  1213.    var mouse_y = mouse.y;\
  1214.    if( mouse_y > ysize - 20 ){return;};\
  1215.    var mouse_x = mouse.x;\
  1216.    if( mouse_x > ruler_x - 50 && mouse_x < ruler_x + size_x + 50){\
  1217.     if( mouse_y > ruler_y - 50 && mouse_y < ruler_y + size_y + 50){\
  1218.      ruler_object_cnt++;\
  1219.      ruler_move(evt);\
  1220.      return;\
  1221.     };\
  1222.    }else{ruler_object_cnt = 0; return;};\
  1223.   };\
  1224.   var angle = 0;\
  1225.   function ruler_move(evt){\
  1226.    var mouse = getMouse(evt,canvas);\
  1227.    switch(ruler_object_cnt){\
  1228.     case 1:\
  1229.      angle = 0;\
  1230.      var xy = multisnap_check(mouse.x,mouse.y,use_snap);\
  1231.      ruler_y = xy[1];\
  1232.      if( ruler_y > ysize - 20 ){ruler_y = 0.5*ysize;ruler_x = 0.5*xsize;return;};\
  1233.      ruler_x = xy[0];\
  1234.      ctx.clearRect(0,0,xsize,ysize);\
  1235.      ctx.save();\
  1236.      ctx.translate(ruler_x - xcenter,ruler_y - ycenter);\
  1237.      ctx.drawImage(canvas_temp,0,0);\
  1238.      ctx.restore();\
  1239.      break;\
  1240.     case 2:\
  1241.      angle = find_angle(ruler_x,ruler_y,mouse.x,mouse.y);\
  1242.      ctx.clearRect(0,0,xsize,ysize);\
  1243.      ctx.save();\
  1244.      ctx.translate(ruler_x,ruler_y);\
  1245.      ctx.rotate(angle);\
  1246.      ctx.translate( -1*xcenter, -1*ycenter );\
  1247.      ctx.drawImage( canvas_temp,0,0 );\
  1248.      ctx.restore();\
  1249.      userdraw_radius[0] = 2*Math.PI - angle;\
  1250.      break;\
  1251.     case 3:ruler_object_cnt = 0;break;\
  1252.     default:ruler_stop(evt);break;\
  1253.    };\
  1254.   };\
  1255.  };\
  1256.  ruler%d();",canvas_root_id);
  1257.  }
  1258.  else
  1259.  {
  1260.   fprintf(js_include_file,"\
  1261.   ctx.clearRect(0,0,xsize,ysize);\
  1262.   ctx.save();\
  1263.   ctx.translate(ruler_x,ruler_y);\
  1264.   ctx.rotate(%d*Math.PI/180);\
  1265.   ctx.translate( -1*xcenter, -1*ycenter );\
  1266.   ctx.drawImage( canvas_temp,0,0 );\
  1267.   ctx.restore();\
  1268.  };\
  1269.  ruler%d();",dynamic,canvas_root_id);
  1270.  }
  1271. }
  1272.  
  1273. void add_js_protractor(int type,double xcenter,double ycenter,int size,char *font,char *stroke_color,double stroke_opacity,char *fill_color,double fill_opacity,int line_width,int use_scale,int dynamic,int use_snap){
  1274. /*
  1275. use_slider_display = 2 : angle in degrees
  1276. use_slider_display = 3 : angle in radians
  1277. void add_slider_display(FILE *js_include_file,int canvas_root_id,int precision,int font_size,char *font_color,double stroke_opacity){
  1278. */
  1279.  
  1280.   if( type == 1 ){ /* geodriehoek */
  1281.  fprintf(js_include_file,"\n/* command protractor type 1 */\
  1282. var protractor_data = new Array(3);\
  1283. var protractor%d = function(){\
  1284.  var once = true;\
  1285.  var use_snap = %d;\
  1286.  var full = 2*Math.PI;\
  1287.  var canvas = create_canvas%d(2000,xsize,ysize);\
  1288.  var ctx = canvas.getContext(\"2d\");\
  1289.  var canvas_temp =  document.createElement(\"canvas\");\
  1290.  var size = parseInt(xsize*(%d)/(xmax - xmin));\
  1291.  canvas_temp.width = xsize;\
  1292.  canvas_temp.height = ysize;\
  1293.  var ctx_temp = canvas_temp.getContext(\"2d\");\
  1294.  var type = %d;\
  1295.  var xcenter = x2px(%f);\
  1296.  var ycenter = y2px(%f);\
  1297.  var half = 0.5*size;\
  1298.  var radius1 = 0.6*half;\
  1299.  var radius2 = 0.65*half;\
  1300.  var radius3 = 0.7*half;\
  1301.  ctx_temp.font = \"%s\";\
  1302.  ctx_temp.strokeStyle = \"rgba(%s,%f)\";\
  1303.  ctx_temp.fillStyle = \"rgba(%s,%f)\";\
  1304.  ctx_temp.lineWidth =%d;\
  1305.  var use_scale = %d;\
  1306.  if( once ){\
  1307.   ctx_temp.clearRect(0,0,canvas_temp.width,canvas_temp.height);\
  1308.   ctx_temp.beginPath();\
  1309.   ctx_temp.moveTo(xcenter-half,ycenter );\
  1310.   ctx_temp.lineTo(xcenter,ycenter-half);\
  1311.   ctx_temp.lineTo(xcenter+half,ycenter);\
  1312.   ctx_temp.lineTo(xcenter-half,ycenter);\
  1313.   ctx_temp.moveTo(xcenter,ycenter );\
  1314.   ctx_temp.lineTo(xcenter+0.5*half,ycenter-0.5*half);\
  1315.   ctx_temp.moveTo(xcenter,ycenter );\
  1316.   ctx_temp.lineTo(xcenter-0.5*half,ycenter-0.5*half);\
  1317.   ctx_temp.moveTo(xcenter,ycenter );\
  1318.   ctx_temp.lineTo(xcenter,ycenter-half);\
  1319.   ctx_temp.closePath();\
  1320.   ctx_temp.fill();\
  1321.   ctx_temp.stroke();\
  1322.   ctx_temp.beginPath();\
  1323.   ctx_temp.arc(xcenter,ycenter,radius1,0,Math.PI,false);\
  1324.   ctx_temp.closePath();\
  1325.   if( use_scale == 1 ){\
  1326.    ctx_temp.fillStyle = ctx_temp.strokeStyle;\
  1327.    var txtsize;\
  1328.    for(var p = 45 ; p < 180;p = p+45){\
  1329.     txtsize = 0.5*(ctx_temp.measureText(p).width);\
  1330.     ctx_temp.fillText(p,xcenter+0.5*half*Math.cos(p*Math.PI/180) - txtsize,ycenter-0.5*half*Math.sin(p*Math.PI/180));\
  1331.    };\
  1332.   };\
  1333.   for(var p = 10 ; p < 180;p = p+10){\
  1334.    ctx_temp.beginPath();\
  1335.    ctx_temp.moveTo(xcenter+radius1*Math.cos(p*Math.PI/180),ycenter-radius1*Math.sin(p*Math.PI/180));\
  1336.    ctx_temp.lineTo(xcenter+radius3*Math.cos(p*Math.PI/180),ycenter-radius3*Math.sin(p*Math.PI/180));\
  1337.    ctx_temp.closePath();\
  1338.    ctx_temp.stroke();\
  1339.   };\
  1340.   for(var p = 0 ; p < 180;p=p+2){\
  1341.    if(p%%10 != 0){\
  1342.     ctx_temp.beginPath();\
  1343.     ctx_temp.moveTo(xcenter+radius1*Math.cos(p*Math.PI/180),ycenter-radius1*Math.sin(p*Math.PI/180));\
  1344.     ctx_temp.lineTo(xcenter+radius2*Math.cos(p*Math.PI/180),ycenter-radius2*Math.sin(p*Math.PI/180));\
  1345.     ctx_temp.closePath();\
  1346.     ctx_temp.stroke();\
  1347.    };\
  1348.   };\
  1349.   ctx_temp.drawImage(canvas,xcenter,ycenter);\
  1350.   ctx_temp.save();\
  1351.   once = false;\
  1352.  };\
  1353.  ",canvas_root_id,use_snap,canvas_root_id,size,type,xcenter,ycenter,font,stroke_color,stroke_opacity,fill_color,fill_opacity,line_width,use_scale);
  1354.   }
  1355.   if( type != 1 ){
  1356.  fprintf(js_include_file,"\n/* command protractor type 0 */\
  1357. var protractor_data = new Array(3);\
  1358. var protractor%d = function(){\
  1359.  var once = true;\
  1360.  var use_snap = %d;\
  1361.  var full = 2*Math.PI;\
  1362.  var canvas = create_canvas%d(2000,xsize,ysize);\
  1363.  var ctx = canvas.getContext(\"2d\");\
  1364.  var canvas_temp =  document.createElement(\"canvas\");\
  1365.  var size = parseInt(xsize*(%d)/(xmax - xmin));\
  1366.  canvas_temp.width = xsize;\
  1367.  canvas_temp.height = ysize;\
  1368.  var ctx_temp = canvas_temp.getContext(\"2d\");\
  1369.  var type = %d;\
  1370.  var xcenter = x2px(%f);\
  1371.  var ycenter = y2px(%f);\
  1372.  var half = 0.5*size;\
  1373.  var radius1 = 0.8*half;\
  1374.  var radius2 = 0.9*half;\
  1375.  var radius3 = half;\
  1376.  ctx_temp.font = \"%s\";\
  1377.  ctx_temp.strokeStyle = \"rgba(%s,%f)\";\
  1378.  ctx_temp.fillStyle = \"rgba(%s,%f)\";\
  1379.  ctx_temp.lineWidth =%d;\
  1380.  var use_scale = %d;\
  1381.  if( once ){\
  1382.   ctx_temp.clearRect(0,0,xsize,ysize);\
  1383.   ctx_temp.arc(xcenter,ycenter,radius1,0,2*Math.PI,false);\
  1384.   ctx_temp.arc(xcenter,ycenter,radius2,0,2*Math.PI,false);\
  1385.   ctx_temp.arc(xcenter,ycenter,radius3,0,2*Math.PI,false);\
  1386.   ctx_temp.fill();\
  1387.   ctx_temp.stroke();\
  1388.   if( use_scale == 1 ){\
  1389.    ctx_temp.fillStyle = ctx_temp.strokeStyle;\
  1390.    var txtsize;\
  1391.    for(var p = 0 ; p < 360;p = p+45){\
  1392.     txtsize = 0.5*(ctx_temp.measureText(p).width);\
  1393.     ctx_temp.fillText(p,xcenter+0.6*half*Math.cos(p*Math.PI/180) - txtsize,ycenter-0.6*half*Math.sin(p*Math.PI/180));\
  1394.    };\
  1395.   };\
  1396.   ctx_temp.strokeStyle = \"rgba(255,0,0,0.4)\";\
  1397.   for(var p = 0 ; p < 360;p = p+10){\
  1398.    ctx_temp.beginPath();\
  1399.    ctx_temp.moveTo(xcenter+radius1*Math.cos(p*Math.PI/180),ycenter-radius1*Math.sin(p*Math.PI/180));\
  1400.    ctx_temp.lineTo(xcenter+radius3*Math.cos(p*Math.PI/180),ycenter-radius3*Math.sin(p*Math.PI/180));\
  1401.    ctx_temp.closePath();\
  1402.    ctx_temp.stroke();\
  1403.   };\
  1404.   ctx_temp.strokeStyle = \"rgba(0,0,255,0.4)\";\
  1405.   for(var p = 0 ; p < 360;p=p+2){\
  1406.     ctx_temp.beginPath();\
  1407.     ctx_temp.moveTo(xcenter+radius2*Math.cos(p*Math.PI/180),ycenter-radius2*Math.sin(p*Math.PI/180));\
  1408.     ctx_temp.lineTo(xcenter+radius3*Math.cos(p*Math.PI/180),ycenter-radius3*Math.sin(p*Math.PI/180));\
  1409.     ctx_temp.closePath();\
  1410.     ctx_temp.stroke();\
  1411.   };\
  1412.   ctx_temp.strokeStyle = \"rgba(0,0,0,0.6)\";\
  1413.   for(var p = 0 ; p < 360;p=p+45){\
  1414.     ctx_temp.beginPath();\
  1415.     ctx_temp.moveTo(xcenter,ycenter);\
  1416.     ctx_temp.lineTo(xcenter+radius3*Math.cos(p*Math.PI/180),ycenter-radius3*Math.sin(p*Math.PI/180));\
  1417.     ctx_temp.closePath();\
  1418.     ctx_temp.stroke();\
  1419.   };\
  1420.   ctx_temp.drawImage(canvas,0,0);\
  1421.   ctx_temp.save();\
  1422.   once = false;\
  1423.  };",canvas_root_id,use_snap,canvas_root_id,size,type,xcenter,ycenter,font,stroke_color,stroke_opacity,fill_color,fill_opacity,line_width,use_scale);
  1424.   }
  1425.   if( dynamic == -1 ){ /* rotate the protractors */
  1426.     fprintf(js_include_file,"\
  1427.  var protractor_x = xcenter;\
  1428.  var protractor_y = ycenter;\
  1429.  ctx.drawImage(canvas_temp,0,0);\
  1430.  var angle = 0;\
  1431.  if(wims_status != \"done\"){\
  1432.   canvas_div.addEventListener( 'mouseup'   , protractor_stop,false);\
  1433.   canvas_div.addEventListener( 'mousedown' , protractor_start,false);\
  1434.   canvas_div.addEventListener( 'mousemove' , protractor_move,false);\
  1435.   canvas_div.addEventListener( 'touchstart', function(e){ e.preventDefault();protractor_start(e.changedTouches[0]);},false);\
  1436.   canvas_div.addEventListener( 'touchmove', function(e){ e.preventDefault();protractor_move(e.changedTouches[0]);},false);\
  1437.   canvas_div.addEventListener( 'touchend', function(e){ e.preventDefault();protractor_stop(e.changedTouches[0]);},false);\
  1438.  };\
  1439.  function protractor_stop(evt){\
  1440.   protractor_data[0] = protractor_x;\
  1441.   protractor_data[1] = protractor_y;\
  1442.   protractor_data[2] = angle;\
  1443.   return;\
  1444.  };\
  1445.  var protractor_object_cnt = 0;\
  1446.  function protractor_start(evt){\
  1447.   var mouse = getMouse(evt,canvas);\
  1448.   var mouse_y = mouse.y;\
  1449.   if( mouse_y > ysize - 20 ){return;};\
  1450.   var mouse_x = mouse.x;\
  1451.   if( mouse_x > protractor_x - half && mouse_x < protractor_x + half ){\
  1452.    if( mouse_y > protractor_y - half && mouse_y < protractor_y + half ){\
  1453.     protractor_object_cnt++;\
  1454.     protractor_move(evt);\
  1455.     return;\
  1456.    };\
  1457.   }else{protractor_object_cnt = 0; return;};\
  1458.  };\
  1459.  function protractor_move(evt){\
  1460.   var mouse = getMouse(evt,canvas);\
  1461.   switch(protractor_object_cnt){\
  1462.    case 1:\
  1463.      var xy = multisnap_check(mouse.x,mouse.y,use_snap);\
  1464.      mouse.x = xy[0];\
  1465.      mouse.y = xy[1];\
  1466.      angle = 0;\
  1467.      protractor_x = mouse.x;\
  1468.      protractor_y = mouse.y;\
  1469.      if( protractor_y > ysize - 20 ){protractor_y = 0.5*ysize;protractor_x = 0.5*xsize;return;};\
  1470.      ctx.clearRect(0,0,xsize,ysize);\
  1471.      ctx.save();\
  1472.      ctx.translate(protractor_x - xcenter,protractor_y - ycenter);\
  1473.      ctx.drawImage(canvas_temp,0,0);\
  1474.      ctx.restore();\
  1475.      break;\
  1476.    case 2:\
  1477.     angle = find_angle(protractor_x,protractor_y,mouse.x,mouse.y);\
  1478.     ctx.clearRect(0,0,xsize,ysize);\
  1479.     ctx.save();\
  1480.     ctx.translate(protractor_x,protractor_y);\
  1481.     ctx.rotate(angle);\
  1482.     ctx.translate( -1*xcenter, -1*ycenter );\
  1483.     ctx.drawImage( canvas_temp,0,0 );\
  1484.     ctx.restore();\
  1485.     userdraw_radius[0] =2*Math.PI- angle;\
  1486.     break;\
  1487.    case 3:protractor_object_cnt = 0;break;\
  1488.    default:protractor_stop(evt);\
  1489.   };\
  1490.  };\
  1491. };\
  1492. protractor%d();",canvas_root_id);
  1493.   }
  1494.   else
  1495.   {
  1496.  fprintf(js_include_file,"\
  1497.  ctx.save();\
  1498.  ctx.translate(xcenter,ycenter);\
  1499.  ctx.rotate(%d*Math.PI/180);\
  1500.  ctx.translate( -1*xcenter, -1*ycenter );\
  1501.  ctx.drawImage( canvas_temp,0,0 );\
  1502.  ctx.restore();\
  1503. };\
  1504. protractor%d();\
  1505. ",dynamic,canvas_root_id);
  1506.   } /* end dynamic == -1*/
  1507. }
  1508.