Subversion Repositories wimsdev

Rev

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

  1. #include "canvasdraw.h"
  2. /*
  3. collection of javascript utilities (with no configurable parameters)
  4. */
  5. void add_javascript_function(){
  6. #ifdef KATEX_INSTALLED
  7. char *mathjax="centered(xml_div,obj);";
  8. #else
  9. char *mathjax="setTimeout(function(){centered(xml_div,obj)},100);";
  10. #endif
  11. int i;
  12. int type;
  13. for(i = 0 ; i < MAX_JS_FUNCTIONS; i++){
  14. /*
  15. fprintf(stdout,"checking js_function[%d] = %d<br />",i,js_function[i]);
  16. */
  17.  if( js_function[i] == 1){
  18.     switch(i){
  19.  
  20. case JS_ARROWHEAD:
  21. /* draw an arrowhead on object ; arrowhead on (x:y) from direction (x0:y0) */
  22. fprintf(js_include_file,"\n/* draw an arrowhead on object ; arrowhead on (x:y) from direction (x0:y0) */\
  23. function draw_arrowhead(x,y,x0,y0,ctx){\
  24. var angle = Math.atan2(x - x0,y - y0) + Math.PI;\
  25. var pie = Math.PI/6;\
  26. ctx.save();\
  27. ctx.fillStyle=ctx.strokeStyle;\
  28. ctx.beginPath();\
  29. ctx.moveTo(x,y);\
  30. ctx.moveTo(x - (arrow_head * Math.sin(angle - pie)),y - (arrow_head * Math.cos(angle - pie)));\
  31. ctx.lineTo(x,y);\
  32. ctx.lineTo(x - (arrow_head * Math.sin(angle + pie)),y - (arrow_head * Math.cos(angle + pie)));\
  33. ctx.closePath();\
  34. ctx.stroke();\
  35. ctx.fill();\
  36. ctx.restore();\
  37. };");
  38. break;
  39. case JS_LOAD_IMAGE:
  40. fprintf(js_include_file,"\n/* get_image_from_url */\
  41. var image_cnt = 0;\
  42. if( typeof(image_patterns) !== 'object'){var image_patterns = [];};\
  43. var get_image_from_url = function(url){\
  44. var idx = Math.ceil(1000*(Math.random()));\
  45. var canvas = create_canvas%d(idx,xsize,ysize);\
  46. canvas.style.visibility = 'hidden';\
  47. var ctx = canvas.getContext(\"2d\");\
  48. var img = new Image();\
  49. img.src = url;\
  50. img.onload = function(){\
  51.  var pat = ctx.createPattern(img,\"repeat\");\
  52.  image_patterns.push(pat);\
  53. };\
  54. };",canvas_root_id);
  55. break;
  56.  
  57. case JS_SAFE_EVAL:
  58. /* to avoid easy js-code injection...but is it a real problem ? */
  59. fprintf(js_include_file," \n/* add safe eval function */function safe_eval(exp){\
  60. exp = exp.replace(/pi/g,'3.14159');\
  61. if(exp.indexOf('^') != -1){\
  62.  exp = exp.replace(/[a-zA-Z]/g,' ');\
  63.  exp = exp.replace(/\\*10\\^-/g,'e-');\
  64.  exp = exp.replace(/\\*10\\^/g,'e+');\
  65.  exp = exp.replace(/10\\^-/g,'1e-');exp = exp.replace(/10\\^/g,'1e+');\
  66.  exp = eval(exp);\
  67.  if(isNaN(exp)){alert(\"invalid input\\ntry just a real number \\ne.g. no calculations...\");return null;}\
  68.  return exp;\
  69. };\
  70. var reg = /(?:[a-z$_][a-z0-9$_]*)|(?:[;={}\\[\\]\"'!&<>^\\\\?:])/ig;\
  71. var valid = true;\
  72. exp = exp.replace(reg,function($0){\
  73.  if(Math.hasOwnProperty($0)){\
  74.   return \"Math.\"+$0;\
  75.  }\
  76.  else\
  77.  {\
  78.   valid = false;\
  79.  }\
  80. }\
  81. );\
  82. if( !valid ){\
  83.  alert(\"hmmm \"+exp+\" ?\"); exp = null;\
  84. }\
  85. else\
  86. {\
  87.  try{ exp = eval(exp); } catch(e){alert(\"Invalid arithmetic expression\"); exp = null;};\
  88. };\
  89. return exp;\
  90. };");
  91. break;
  92.  
  93. case JS_RAWMATH:
  94. fprintf(js_include_file,"\n/* add_rawmath() */\
  95. function rawmath(i){\
  96. i=i.toLowerCase();\
  97. i=i.replace(/\\ /g,\"\");i=i.replace(/\\*\\*/g,\"^\");\
  98. if(i.indexOf(\"e+\")!=-1){i=i.replace(\"e+\",\"*10^\");};\
  99. if(i.indexOf(\"e-\")!=-1){i=i.replace(\"e-\",\"*10^-\");};\
  100. i=i.replace(/\\*\\*/g,\"*\");\
  101. if(i.charAt(0)==\"*\"){i=i.substring(1,i.length);};\
  102. var fun=[\"asin\",\"acos\",\"atan\",\"sin\",\"cos\",\"tan\",\"log\",\"ln\",\"pi\",\"e\",\"x\",\"y\"];\
  103. var cons=[\"pi\",\"e\",\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"];\
  104. var cntl = 0;var cntr = 0;\
  105. var len = i.length;\
  106. for( var p = 0;p < len; p++){\
  107.  if(i.charAt(p) == '('){cntl++;}\
  108.  if(i.charAt(p) == ')'){cntr++;}\
  109. };\
  110. if(cntl != cntr){alert(\"unmatched parenthesis !!\");return null;};\
  111. for(var p = 0; p < 12 ; p++){\
  112.  for(var d = 0; d < 12 ; d++){\
  113.   while(i.indexOf(cons[d]+\"\"+fun[p])!=-1){\
  114.    i = i.replace(cons[d]+\"\"+fun[p],cons[d]+\"*\"+fun[p]);\
  115.   };\
  116.   while(i.indexOf(fun[p]+\"\"+cons[d])!=-1){\
  117.    i = i.replace(fun[p]+\"\"+cons[d],fun[p]+\"*\"+cons[d]);\
  118.   };\
  119.  };\
  120. };\
  121. if(i.indexOf(\"(\")!=-1){\
  122.  for(var p = 0;p < 12; p++){\
  123.   if(i.indexOf(cons[p]+\"(\")!=-1){\
  124.    i = i.replace(cons[p]+\"(\",cons[p]+\"*(\");\
  125.   };\
  126.   if(i.indexOf(\")\"+cons[p])!=-1){\
  127.    i = i.replace(\")\"+cons[p],\")*\"+cons[p]);\
  128.   };\
  129.  };\
  130.  i = i.replace(/\\)\\(/g,\")*(\");\
  131. };\
  132. return i;\
  133. };");
  134. break;
  135.  
  136. case JS_PLOT:
  137. fprintf(js_include_file,"\n/* jsplot() */\
  138. var x_anim_points;var y_anim_points;var animation_steps;var animation_funs;\
  139. function jsplot(canvas_type,funs,linewidth,color,opacity,use_dashed,dashtype0,dashtype1,trange,plotsteps,use_parametric,use_animate,origin){\
  140. var obj = create_canvas%d(canvas_type,xsize,ysize);\
  141. var ctx = obj.getContext(\"2d\");\
  142. ctx.clearRect(0,0,xsize,ysize);\
  143. animation_funs = funs.length;\
  144. function eval_jsmath(x,func){return parseFloat(eval(func));};\
  145. if(origin == 0 ){\
  146.  if( typeof(multilinewidth) !== 'undefined' && multilinewidth != null ){ linewidth = multilinewidth;};\
  147.  if( typeof(multistrokecolors) !== 'undefined' && multistrokecolors != null ){ color = multistrokecolors;};\
  148.  if( typeof(multistrokeopacity) !== 'undefined' && multistrokeopacity != null ){ opacity = multistrokeopacity;};\
  149.  if( typeof(multidash) !== 'undefined' && multidash != null ){use_dashed = multidash;};\
  150. };\
  151. x_anim_points = [];y_anim_points = [];var idx=0;\
  152. if( use_parametric == 1){\
  153.  for(var i = 0 ; i < animation_funs; i=i+2){\
  154.   funs[i] = funs[i].replace(/t/g,'x');\
  155.   funs[i+1] = funs[i+1].replace(/t/g,'x');\
  156.   funs[i] = funs[i].replace(/xan/g,'tan');\
  157.   funs[i+1] = funs[i+1].replace(/xan/g,'tan');\
  158.   var fun_x = to_js_math(funs[i]);\
  159.   var fun_y = to_js_math(funs[i+1]);\
  160.   if(fun_x == null || fun_y == 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;};\
  161.   try{ parseFloat( eval_jsmath( px2x(0),fun_x ) );}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;};\
  162.   ctx.lineWidth = linewidth[i] || linewidth;\
  163.   ctx.strokeStyle='rgba('+color[i] || color +','+opacity[i] || opacity +')';\
  164.   if(use_dashed[i] == \"1\" || use_dashed == \"1\"){if(ctx.setLineDash){ctx.setLineDash([dashtype0,dashtype1]);}else{ctx.mozDash =[dashtype0,dashtype1];}};\
  165.   var y1;var x1;var y2;var x2;\
  166.   ctx.beginPath();\
  167.   var tmin = trange[0];var tmax = trange[1];\
  168.   var step = parseFloat((tmax - tmin)/plotsteps);\
  169.   for(var p = tmin ; p < tmax; p = p+step ){\
  170.    x1 = x2px(parseFloat(eval_jsmath(p,fun_x)));\
  171.    y1 = y2px(parseFloat(eval_jsmath(p,fun_y)));\
  172.    x2 = x2px(parseFloat(eval_jsmath(p+step,fun_x)));\
  173.    y2 = y2px(parseFloat(eval_jsmath(p+step,fun_y)));\
  174.    x_anim_points[idx] = x1;y_anim_points[idx] = y1;idx++;\
  175.     ctx.moveTo(x1,y1);\
  176.     ctx.lineTo(x2,y2);\
  177.     ctx.moveTo(x1,y1);\
  178.     ctx.lineTo(x2,y2);\
  179.   };\
  180.   ctx.closePath();\
  181.   ctx.stroke();\
  182.  };\
  183.  animation_funs = 0.5*animation_funs;\
  184. }else{\
  185.  for(var i = 0 ; i < animation_funs; i++){\
  186.   var fun = to_js_math(funs[i]);\
  187.   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;};\
  188.   try{ parseFloat( eval_jsmath( px2x(0),fun ) );}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;};\
  189.   if(use_dashed[i] == \"1\" || use_dashed == \"1\"){if(ctx.setLineDash){ctx.setLineDash([dashtype0,dashtype1]);}else{ctx.mozDash =[dashtype0,dashtype1];}};\
  190.   ctx.lineWidth = linewidth[i] || linewidth;\
  191.   ctx.strokeStyle='rgba('+color[i] || color +','+opacity[i] || opacity +')';\
  192.   var y1;var x1;var y2;var x2;\
  193.   ctx.beginPath();\
  194.   for(var p = 0 ; p<xsize;p++){\
  195.    x1 = px2x(p);\
  196.    y1 = y2px(parseFloat(eval_jsmath(x1,fun)));\
  197.    x2 = px2x(p+1);\
  198.    y2 = y2px(parseFloat(eval_jsmath(x2,fun)));\
  199.    x_anim_points[idx] = p;y_anim_points[idx] = y1;idx++;\
  200.    if(Math.abs(y2-y1) < ysize ){\
  201.     ctx.moveTo(p,y1);\
  202.     ctx.lineTo(p+1,y2);\
  203.    };\
  204.   };\
  205.   ctx.closePath();\
  206.   ctx.stroke();\
  207.  };\
  208. };\
  209. if( use_animate == 1 ){animation_steps = idx;animate_this();}\
  210. };",canvas_root_id);
  211. break;
  212.  
  213. case JS_MATH:
  214. fprintf(js_include_file,"\n/* to_js_math() */\
  215. function to_js_math(math_fun){\
  216. if(math_fun == null){return;};\
  217. var infun=[\"sqrt\",\"^\",\"asin\",\"acos\",\"atan\",\"log\",\"pi\",\"abs\",\"sin\",\"cos\",\"tan\",\"e\"];\
  218. 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)\"];\
  219. var len = infun.length;var in_fun;var In_Fun;var out_fun;var w_cnt;\
  220. for(var p=0 ; p < len ; p++){\
  221.  in_fun = infun[p];In_Fun = in_fun.toUpperCase();out_fun = outfun[p];w_cnt=0;\
  222.  if(math_fun.indexOf(in_fun) != -1){\
  223.   if(in_fun == \"^\"){\
  224.    var tab = [];var small_trick = \"___small_trick___\";\
  225.    while (math_fun.indexOf(\"(\") != -1){\
  226.     math_fun = math_fun.replace(/(\\([^\\(\\)]*\\))/g, function(m, t){tab.push(t);return (small_trick + (tab.length - 1));});\
  227.     w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  228.    };\
  229.    tab.push(math_fun);w_cnt = 0;math_fun = small_trick + (tab.length - 1);\
  230.    while (math_fun.indexOf(small_trick) != -1){\
  231.     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)\");});\
  232.     w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  233.    };\
  234.   }\
  235.   else\
  236.   {\
  237.    while( math_fun.indexOf(in_fun) != -1 ){\
  238.     math_fun = math_fun.replace(in_fun,out_fun);\
  239.     math_fun = math_fun.replace(in_fun,In_Fun);\
  240.     w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  241.    };\
  242.   };\
  243.  };\
  244. };\
  245. for(var p=0 ; p < len ; p++){\
  246.  in_fun = infun[p];In_Fun = in_fun.toUpperCase();w_cnt = 0;\
  247.  if(math_fun.indexOf(In_Fun) != -1 ){\
  248.   while(math_fun.indexOf(In_Fun) != -1){\
  249.    math_fun = math_fun.replace(In_Fun,in_fun);\
  250.    w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  251.   };\
  252.  };\
  253. };\
  254. return math_fun;\
  255. };");
  256. break;
  257.  
  258. case INTERACTIVE:
  259.  fprintf(js_include_file,"\n/* add mouse support */ var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0));var getMouse = function(e,element){var mx,my;var offsetX = 0,offsetY = 0;while( ( element = element.offsetParent) ){offsetX += element.offsetLeft;offsetY += element.offsetTop;};if(isTouch){mx = e.pageX - offsetX;my = e.pageY - offsetY;}else{mx = e.clientX - offsetX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft:document.body.scrollLeft);my = e.clientY - offsetY + (document.documentElement.scrollTop ? document.documentElement.scrollTop:document.body.scrollTop);};return {x: mx, y: my};};");
  260. break;
  261. case USERDRAW_AND_ZOOM:
  262. fprintf(js_include_file,"\n/* add zoom support for multidraw */\
  263. function recalculate_userdraw(xmin0,ymin0,xmax0,ymax0){\
  264. function x_zoom(px){\
  265.  var x = parseFloat(px*(xmax0 - xmin0)/xsize + xmin0);\
  266.  return parseFloat(x*xsize/(xmax - xmin) - xsize*xmin/(xmax - xmin));\
  267. };\
  268. function y_zoom(py){\
  269.  var y = parseFloat(ymax0 - py*(ymax0 - ymin0)/ysize);\
  270.  return parseFloat(-1*y*ysize/(ymax - ymin) + ymax*ysize/(ymax - ymin));\
  271. };\
  272. function r_zoom(r){\
  273.  return r*(xmin0/xmin);\
  274. };\
  275. var len = userdraw_x.length;\
  276. var x;var y;var r;\
  277. for(var p=0;p<len;p++){\
  278.  x = userdraw_x[p];\
  279.  y = userdraw_y[p];\
  280.  userdraw_x[p] = x_zoom(x);\
  281.  userdraw_y[p] = y_zoom(y);\
  282.  if( userdraw_radius[p] ){\
  283.   r = userdraw_radius[p];\
  284.   userdraw_radius[p] = r_zoom(r);\
  285.  };\
  286. };\
  287. };");
  288. break;
  289.  
  290. case DRAG_AND_ZOOM:
  291. fprintf(js_include_file,"\n/* add zoom support for drag&drop */\
  292. function recalculate_dragdrop(xmin0,ymin0,xmax0,ymax0){\
  293. function x_zoom(px){\
  294.  var x = parseFloat(px*(xmax0 - xmin0)/xsize + xmin0);\
  295.  return parseFloat(x*xsize/(xmax - xmin) - xsize*xmin/(xmax - xmin));\
  296. };\
  297. function y_zoom(py){\
  298.  var y = parseFloat(ymax0 - py*(ymax0 - ymin0)/ysize);\
  299.  return parseFloat(-1*y*ysize/(ymax - ymin) + ymax*ysize/(ymax - ymin));\
  300. };\
  301. var len = dragstuff.shapes.length;\
  302. var shape;var L;var x;var y;\
  303. for(var p=0;p<len;p++){\
  304.  shape = dragstuff.shapes[p];\
  305.  L = shape.x.length;\
  306.  for(var i=0;i<L;i++){\
  307.   x = shape.x[i];\
  308.   y = shape.y[i];\
  309.   dragstuff.shapes[p].x[i] = x_zoom(x);\
  310.   dragstuff.shapes[p].y[i] = y_zoom(y);\
  311.  };\
  312. };\
  313. };");
  314. break;
  315.  
  316. case JSPLOT_AND_ZOOM:
  317. fprintf(js_include_file,"\n/* add zoom support for jscurves */\
  318. function redraw_jsplot(){for(var p=0; p <= all_jsplots;p++){try{var fun = eval('js_plot'+p);fun();}catch(e){};};};");
  319. break;
  320.  
  321. case JS_ZOOM:
  322. fprintf(js_include_file,"\n/* add zoom support */\
  323. var x_min_start = xmin;var x_max_start = xmax;var y_min_start = ymin;var y_max_start = ymax;\
  324. var zoomcanvas = create_canvas%d(%d,xsize,ysize);\
  325. function redraw_canvas%d(key){\
  326. var xmin0 = xmin;var xmax0 = xmax;var ymin0 = ymin;var ymax0 = ymax;\
  327. switch(key){\
  328.  case 0: xmin++;ymin++;xmax--;ymax--;break;\
  329.  case 1: xmin--;ymin--;xmax++;ymax++;break;\
  330.  case 2: xmin--;xmax--;break;\
  331.  case 3: xmin++;xmax++;break;\
  332.  case 4: ymin--;ymax--;break;\
  333.  case 5: ymax++;ymin++;break;\
  334.  case 6: xmin = x_min_start;xmax=x_max_start;ymin=y_min_start;ymax=y_max_start;break;\
  335.  default: break;\
  336. };\
  337. if(xmin >= xmax){xmin = x_min_start;xmax = x_max_start;};\
  338. if(ymin >= ymax){ymax = y_max_start;ymin = y_min_start;};\
  339. if( typeof(recalculate_multidraw) === 'function'){recalculate_multidraw(xmin0,xmax0,ymin0,ymax0);redraw_userdraw();}\
  340. if( typeof(recalculate_userdraw) === 'function'){recalculate_userdraw(xmin0,ymin0,xmax0,ymax0);redraw_userdraw();}\
  341. if( typeof(redraw_grid) === 'function'){redraw_grid();};\
  342. if( typeof(redraw_jsplot) === 'function'){redraw_jsplot();};\
  343. if( typeof(recalculate_dragdrop) === 'function'){recalculate_dragdrop(xmin0,ymin0,xmax0,ymax0);dragstuff.valid = false;dragstuff.draw();};\
  344. return;\
  345. };\
  346. canvas_div.addEventListener(\"mousedown\",check_zoom_or_pan,false);\
  347. canvas_div.addEventListener(\"wheel\",wheel_zoom,false);\
  348. canvas_div.addEventListener(\"touchstart\",function(e){ e.preventDefault();check_zoom_or_pan(e.changedTouches[0]);},false);\
  349. function wheel_zoom(evt){\
  350. evt.preventDefault();\
  351. var key = 1;\
  352. if(evt.deltaY > 0 ){key = 0};\
  353. redraw_canvas%d(key);\
  354. return;\
  355. };\
  356. function check_zoom_or_pan(evt){\
  357. var mouse = getMouse(evt,zoomcanvas);\
  358. var my = mouse.y;\
  359. if(my < ysize - 30){ return; };\
  360. var mx = mouse.x;\
  361. var key = -1;\
  362. for(var p = 15 ; p < 106 ; p = p+15){\
  363.  key++;\
  364.  if(mx > xsize - p){\
  365.   redraw_canvas%d(key);\
  366.   return;\
  367.  };\
  368. };\
  369. return;\
  370. };",canvas_root_id,ZOOM_CANVAS,canvas_root_id,canvas_root_id,canvas_root_id);
  371. break;
  372.  
  373. case DRAW_FILL_PATTERN:
  374. fprintf(js_include_file,"\n /* add fill pattern */ \
  375. function create_Pattern(x0,y0,type,color){document.body.style.cursor = 'wait';var idx = Math.ceil(1000*(Math.random()));var canvas = create_canvas%d(idx,xsize,ysize);canvas.style.visibility = 'hidden';var ctx = canvas.getContext(\"2d\");var x;var y;var dx = 6;var dy = 6;ctx.lineWidth = 1;ctx.strokeStyle = color;ctx.fillStyle = color;var pat;\
  376. switch(type){\
  377.  case 2: for( x = 0 ; x < xsize ; x = x + dx ){ctx.beginPath();ctx.moveTo(x,0);ctx.lineTo(x,ysize);ctx.closePath();ctx.stroke();};for( y = 0 ; y < ysize; y = y + dy ){ctx.beginPath();ctx.moveTo(0,y);ctx.lineTo(xsize,y);ctx.closePath();ctx.stroke();}; pat = ctx.createPattern(canvas,\"no-repeat\");break;\
  378.  case 3: y = ysize;ctx.beginPath();for( x = 0 ; x < xsize ; x = x + dx ){ctx.moveTo(x,0);ctx.lineTo(xsize,y);y = y - dy;};y = 0;for( x = xsize ; x > 0 ; x = x - dx){ctx.moveTo(x,ysize);ctx.lineTo(0,y); y = y + dy;};ctx.closePath();ctx.stroke(); pat = ctx.createPattern(canvas,\"no-repeat\");break;\
  379.  case 4: y = ysize;ctx.beginPath();for( x = 0 ; x < xsize ; x = x + dx ){ctx.moveTo(x,0); ctx.lineTo(xsize,y); y = y - dy;};y = 0;for( x = xsize ; x > 0 ; x = x - dx){ctx.moveTo(x,ysize);ctx.lineTo(0,y);y = y + dy;};y = 0;for( x = 0 ; x < xsize ; x = x + dx ){ctx.moveTo(x,0); ctx.lineTo(0,y); y = y + dy;};y = 0;for( x = 0 ; x < xsize ; x = x + dx ){ctx.moveTo(xsize,y);ctx.lineTo(x,ysize);y = y + dy;};ctx.closePath(); ctx.stroke(); pat = ctx.createPattern(canvas,\"no-repeat\");break;\
  380.  case 5: for( x = 0 ; x < xsize ; x = x + dx ){for( y = 0 ; y < ysize ; y = y + dy ){ctx.beginPath();ctx.arc(x,y,1,0,2*Math.PI,false);ctx.closePath();ctx.fill();};}; pat = ctx.createPattern(canvas,\"no-repeat\");break;\
  381.  case 6: alert('wait for image '+(image_cnt+1)+'...');pat = image_patterns[image_cnt];image_cnt++;break;\
  382.  default: break;\
  383. };\
  384. document.body.style.cursor = 'default';return pat;\
  385. };",canvas_root_id);
  386. break;
  387.  
  388. case JS_TRANSFORM_MOUSE:
  389. /* identify mouse coordinates on transformed objects using command affine */
  390. fprintf(js_include_file,"\n/* translate mouse */\
  391. function transform_mouse(mx,my,obj){\
  392. if( typeof(obj.affine_matrix) === 'undefined' ){console.log('translate_mouse() affine_matrix undefined');{x:mx,y:my};};\
  393. var m = obj.affine_matrix;\
  394. var d = 1/(m[0]*m[3]-m[1]*m[2]);\
  395. var im = [ m[3]*d, -m[1]*d,-m[2]*d,m[0]*d,d*(m[2]*m[5]-m[3]*m[4]),d*(m[1]*m[4]-m[0]*m[5]) ];\
  396. return { x:mx*im[0]+my*im[2]+im[4], y:mx*im[1]+my*im[3]+im[5] };};");
  397. break;
  398.  
  399. case JS_ROTATE_MOUSE:
  400. /*
  401. identify mouse coordinates on rotated STRING (no 14) objects used for command rotate :
  402. faster than transform matrix
  403. */
  404. fprintf(js_include_file,"\n/* rotate mouse */\
  405. function rotate_mouse(mx,my,obj){\
  406. if( typeof(obj.angle) === 'undefined' ){console.log('rotate_mouse() angle undefined');return {x:mx,y:my};};\
  407. var cos = Math.cos(obj.angle);\
  408. var sin = Math.sin(obj.angle);\
  409. var xc = obj.rotation_center[0];\
  410. var yc = obj.rotation_center[1];\
  411. var x_r = parseInt((cos * (mx - xc)) + (sin * (my - yc)) + xc);\
  412. var y_r = parseInt((cos * (my - yc)) - (sin * (mx - xc)) + yc);\
  413. return {x:x_r,y:y_r};};");
  414. break;
  415.  
  416. case JS_FIND_ANGLE:
  417.  fprintf(js_include_file,"\n/* function find_angle() */ function find_angle(xc,yc,x1,y1){var dx = x1 - xc;var dy = yc - y1;return Math.atan2(dx,dy);};");
  418. break;
  419.  
  420. case DRAG_EXTERNAL_IMAGE:
  421. /*
  422. the external_canvas is already created: it needs to be FIRST in order to do some drawing onto it
  423. reply is object{} and identical to reply from dragstuff library for drag&drop&click
  424. reply[object_cnt] = {type:onclick,x:x0,y:y0,r:radius,angle:angle,clicked:0|1};
  425.  
  426.  
  427.    img[6]= parseInt(img[6] - img[16]);\
  428.    img[7]= parseInt(img[7] - img[17]);\
  429.    else{\
  430.     img[6]= parseInt(img[6] + img[16]);\
  431.     img[7]= parseInt(img[7] + img[17]);\
  432.   };\
  433.  
  434. */
  435. fprintf(js_include_file,"\n/* drag external images */\
  436. var external_ctx = external_canvas.getContext(\"2d\");\
  437. var external_canvas_rect = external_canvas.getBoundingClientRect();\
  438. canvas_div.addEventListener(\"mousedown\",setxy,false);\
  439. canvas_div.addEventListener(\"mouseup\",dragstop,false);\
  440. canvas_div.addEventListener(\"mousemove\",dragxy,false);\
  441. canvas_div.addEventListener(\"touchstart\",function(e){ e.preventDefault();setxy(e.changedTouches[0]);},false);\
  442. canvas_div.addEventListener(\"touchend\"  ,function(e){ e.preventDefault();dragstop(e.changedTouches[0]);},false);\
  443. canvas_div.addEventListener(\"touchmove\" ,function(e){ e.preventDefault();dragxy(e.changedTouches[0]);},false);\
  444. var selected_image = null;\
  445. if( typeof(ext_drag_images) !== 'object' ){var ext_drag_images = new Array();};\
  446. if( typeof(ext_image_cnt) == 'undefined'){var ext_image_cnt = 0;};\
  447. function drag_external_image(URL,sx,sy,swidth,sheight,x0,y0,width,height,onclick,object_cnt,use_offset,use_snap,resize){\
  448. var image = new Image();\
  449. image.src = URL;\
  450. slidergroup[object_cnt] = null;\
  451. image.onload = function(){\
  452.  if( sx < 1 ){ sx = 0; };\
  453.  if( sy < 1 ){ sy = 0; };\
  454.  if( swidth < 1 ){swidth = image.width;};\
  455.  if( sheight < 1 ){sheight = image.height;};\
  456.  if( width < 1 ){width = image.width;};\
  457.  if( height < 1 ){height = image.height;};\
  458.  if( resize == 1 ){\
  459.   if( swidth > image.width ){ swidth = image.width; };\
  460.   if( sheight > image.height){ sheight = image.height;};\
  461.   if( width > image.width ){ width = image.width; };\
  462.   if( height > image.height){ height = image.height;};\
  463.  };\
  464.  var img = new Array(18);\
  465.  img[0] = onclick;img[1] = image;img[2] = sx;img[3] = sy;img[4] = swidth;img[5] = sheight;\
  466.  img[8] = width;img[9] = height;img[10] = object_cnt;img[11] = use_snap;\
  467.  img[6] = x0;img[7] = y0;\
  468.  img[12] = ext_image_cnt;\
  469.  img[13] = img[6];img[14] = img[7];img[15] = 0;img[16] = 0;img[17] = 0;\
  470.  if(use_offset == 4 ){\
  471.   img[16] = 0.5*img[8];\
  472.   img[17] = 0.5*img[9];\
  473.   img[6]= parseInt(img[6] - img[16]);\
  474.   img[7]= parseInt(img[7] - img[17]);\
  475.  };\
  476.  external_ctx.drawImage(img[1],img[2],img[3],img[4],img[5],img[6],img[7],img[8],img[9]);\
  477.  dragdrop_reply[img[10]] = {object_cnt:object_cnt,type:img[0],x:x0,y:y0,r:0,angle:0,clicked:img[15]};\
  478.  ext_drag_images[ext_image_cnt] = img;\
  479.  ext_image_cnt++;\
  480. };\
  481. };\
  482. function dragstop(evt){\
  483. if(selected_image != null){\
  484.  var s_img = ext_drag_images[selected_image];\
  485.  dragdrop_reply[s_img[10]] = {type:s_img[0],x:s_img[6]+s_img[16],y:s_img[7]+s_img[17],r:s_img[8],angle:s_img[15],clicked:s_img[15]};\
  486.  console.log(dragdrop_reply[s_img[12]]);\
  487. };\
  488. selected_image = null;return;\
  489. };\
  490. function dragxy(evt){\
  491. if( selected_image != null ){\
  492.  var s_img = ext_drag_images[selected_image];\
  493.  var mouse = getMouse(evt,external_canvas);\
  494.  var xy = multisnap_check(mouse.x,mouse.y,s_img[11]);\
  495.  xy[0] = parseInt(xy[0] - 0.5*s_img[8]);\
  496.  xy[1] = parseInt(xy[1] - 0.5*s_img[9]);\
  497.  s_img[6] = xy[0];s_img[7] = xy[1];\
  498.  ext_drag_images[selected_image] = s_img;\
  499.  external_ctx.clearRect(0,0,xsize,ysize);\
  500.  for(var i = 0; i < ext_image_cnt ; i++){\
  501.   var img = ext_drag_images[i];\
  502.   external_ctx.drawImage(img[1],img[2],img[3],img[4],img[5],img[6],img[7],img[8],img[9]);\
  503.  };\
  504. };\
  505. };\
  506. function setxy(evt){\
  507. if( ! selected_image ){\
  508.  console.log(selected_image);\
  509.  var mouse = getMouse(evt,external_canvas);\
  510.  var xm = mouse.x;\
  511.  var ym = mouse.y;\
  512.  var img;var xmarge;var ymarge;\
  513.  for(var p = 0 ; p < ext_image_cnt ; p++){\
  514.   if( ext_drag_images[p] ){\
  515.    img = ext_drag_images[p];\
  516.    if( img[0] != 0 ){\
  517.     xmarge = 0.5*img[8];ymarge = 0.5*img[9];\
  518.     if( xm > img[6] - xmarge && xm < img[6] + img[8]){\
  519.      if( ym > img[7] - ymarge && ym < img[7] + img[9]){\
  520.       if( img[0] == 1){\
  521.        if( dragdrop_reply[img[10]].clicked == 1 ){\
  522.         dragdrop_reply[img[10]].clicked = 0;external_ctx.strokeStyle = '#ffffff';\
  523.        }\
  524.        else\
  525.        {\
  526.         dragdrop_reply[img[10]].clicked = 1;external_ctx.strokeStyle = '#00ff00';\
  527.        };\
  528.        external_ctx.lineWidth = 2;\
  529.        external_ctx.beginPath();\
  530.        external_ctx.rect(img[6]-2,img[7]-2,img[8]+2,img[9]+2);\
  531.        external_ctx.closePath();\
  532.        external_ctx.stroke();\
  533.        return;\
  534.       }\
  535.       else\
  536.       {\
  537.        img[6] = xm;\
  538.        img[7] = ym;\
  539.        selected_image = p;\
  540.        dragxy(evt);\
  541.        ext_drag_images[p] = img;\
  542.       };\
  543.      };\
  544.     };\
  545.    };\
  546.   };\
  547.  };\
  548. }\
  549. else\
  550. {\
  551.  selected_image = null;\
  552. };\
  553. };");
  554. break;
  555.  
  556. case DRAW_EXTERNAL_IMAGE:
  557. /*
  558. the external_canvas is already created: it needs to be FIRST in order to do some drawing onto it
  559. only drag_xy !
  560. snaptogrid | xsnaptogrid | ysnaptogrid works
  561. 14/5/2019
  562. on heavy styled wims (unice.fr etc problems with mouse?
  563. now uniform method of retreiving mouse coordinates getMouse()
  564. */
  565. fprintf(js_include_file,"\n/* draw external images */\
  566. function draw_external_image(URL,sx,sy,swidth,sheight,x0,y0,width,height,use_offset,resize){\
  567. var external_ctx = image_copy_canvas.getContext(\"2d\");\n\
  568. var image = new Image();\
  569. image.src = URL;\
  570. image.onload = function(){\
  571.  if( sx < 1 ){ sx = 0; };\
  572.  if( sy < 1 ){ sy = 0; };\
  573.  if( swidth < 1 ){swidth = image.width;};\
  574.  if( sheight < 1 ){sheight = image.height;};\
  575.  if( width < 1 ){width = image.width;};\
  576.  if( height < 1 ){height = image.height;};\
  577.  if( resize == 1 ){\
  578.   if( swidth > image.width ){ swidth = image.width; };\
  579.   if( sheight > image.height){ sheight = image.height;};\
  580.   if( width > image.width ){ width = image.width; };\
  581.   if( height > image.height){ height = image.height;};\
  582.  };\
  583.  var img = new Array(9);\
  584.  img[0] = image;img[1] = sx;img[2] = sy;img[3] = swidth;img[4] = sheight;img[5] = x0;img[6] = y0;\
  585.  if(use_offset == 4 ){img[5] = parseInt(img[5] - 0.5*width);img[6] = parseInt(img[6] - 0.5*height);};\
  586.  img[7] = width;img[8] = height;\
  587.  external_ctx.drawImage(img[0],img[1],img[2],img[3],img[4],img[5],img[6],img[7],img[8]);\
  588. };\
  589. };");
  590. break;
  591.  
  592. case DRAW_BEZIER:
  593. fprintf(js_include_file,"\n/* draw bezier curve */\
  594. if( typeof(all_fill_patterns) != 'object' ){ var all_fill_patterns = []; };\
  595. function draw_bezier(canvas_type,linewidth,xy_points,fill_color,fill_opacity,stroke_color,stroke_opacity,use_filled,use_dashed,dashtype0,dashtype1,use_rotate,angle){\
  596. var obj;\
  597. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){\
  598.  obj = document.getElementById(\"wims_canvas%d\"+canvas_type);\
  599. }\
  600. else\
  601. {\
  602.  obj = create_canvas%d(canvas_type,xsize,ysize);\
  603. };\
  604. var ctx = obj.getContext(\"2d\");\
  605. ctx.save();\
  606. ctx.strokeStyle=\"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  607. ctx.lineWidth = linewidth;\
  608. if(use_rotate == 1 ){ctx.rotate(angle*Math.PI/180);};\
  609. if(use_dashed == 1){if(ctx.setLineDash){ctx.setLineDash([dashtype0,dashtype1]);}else{ctx.mozDash = [dashtype0,dashtype1];};};\
  610. ctx.beginPath();\
  611. ctx.moveTo(x2px(xy_points[0]),y2px(xy_points[1]));\
  612. ctx.bezierCurveTo(x2px(xy_points[2]),y2px(xy_points[3]),x2px(xy_points[4]),y2px(xy_points[5]),x2px(xy_points[6]),y2px(xy_points[7]));\
  613. var color = \"rgba(\"+fill_color+\",\"+fill_opacity+\")\";\
  614. if(use_filled > 1 ){ if(! all_fill_patterns[use_filled] ){ var pat = create_Pattern(0,0,use_filled,color); all_fill_patterns[use_filled] = pat;};ctx.fillStyle = all_fill_patterns[use_filled]; } else { ctx.fillStyle = color;};\
  615. ctx.stroke();\
  616. ctx.restore();\
  617. };",canvas_root_id,canvas_root_id,canvas_root_id);
  618. break;
  619.  
  620. case DRAW_GRIDFILL:/* not used for userdraw */
  621. fprintf(js_include_file,"\n/* draw gridfill */\
  622. var grid_fill_pattern;\
  623. function draw_gridfill(canvas_type,x0,y0,dx,dy,linewidth,color,opacity,xsize,ysize,use_userdraw){\
  624. if( dx == 0 || dy == 0 ){alert(\"increment is zero !!! \");return;};\
  625. var fc = %d+canvas_type;\
  626. var obj = create_canvas%d(fc,xsize,ysize);\
  627. var ctx = obj.getContext('2d');\
  628. var x,y;\
  629. ctx.fillStyle='rgba(255,255,255,0.01)';\
  630. ctx.rect(0,0,xsize,ysize);\
  631. ctx.fill();\
  632. ctx.lineWidth = linewidth;\
  633. ctx.strokeStyle=\"rgba(\"+color+\",0.01)\";\
  634. for( x = 0 ; x <= xsize ; x = x + dx ){\
  635.  ctx.beginPath();\
  636.  ctx.moveTo(x,0);\
  637.  ctx.lineTo(x,ysize);\
  638.  ctx.closePath();\
  639.  ctx.stroke();\
  640. };\
  641. for( y = 0 ; y <= ysize; y = y + dy ){\
  642.  ctx.beginPath();\
  643.  ctx.moveTo(0,y);\
  644.  ctx.lineTo(xsize,y);\
  645.  ctx.closePath();\
  646.  ctx.stroke();\
  647. };\
  648. if( use_userdraw ){\
  649.  grid_fill_pattern = ctx;\
  650. }\
  651. else\
  652. {\
  653.  setTimeout(function(){ filltoborder( x0,y0,color,color,canvas_type,true,ctx); },500);};return;\
  654. };",canvas_root_id,canvas_root_id);
  655. break;
  656.  
  657. case DRAW_IMAGEFILL:/* not  used for userdraw */
  658. fprintf(js_include_file,"\n/* draw imagefill */\
  659. function draw_imagefill(canvas_type,x0,y0,URL,xsize,ysize,use_userdraw,use_scaling){\
  660. var fc = %d+canvas_type;\
  661. var obj = create_canvas%d(fc,xsize,ysize);\
  662. var ctx = obj.getContext('2d');\
  663. var img = new Image();\
  664. img.src = URL;\
  665. obj.style.visibility = 'hidden';\
  666. img.onload = function(){\
  667.  if( use_scaling == 1 ){\
  668.   ctx.drawImage(img,x0,y0,xsize,ysize);\
  669.  }else{\
  670.   var w0 = img.width;var h0 = img.height;var w;var h;\
  671.   for( w = x0; w < xsize ; w = w + w0 ){\
  672.    for( h = y0; h < ysize; h = h + h0){\
  673.      ctx.drawImage(img,w,h,w0,h0);\
  674.    };\
  675.   };\
  676.  };\
  677.  if( use_userdraw ){\
  678.   image_pattern = ctx;\
  679.  }\
  680.  else\
  681.  {\
  682.   setTimeout(function(){ filltoborder( x0,y0,'red','red',canvas_type,true,ctx); },500);\
  683.  };\
  684. };\
  685. };",canvas_root_id,canvas_root_id);
  686. break;
  687.  
  688. case DRAW_DOTFILL:/* not  used for userdraw */
  689. fprintf(js_include_file,"\n/* draw dotfill */\
  690. var dot_fill_pattern;\
  691. function draw_dotfill(canvas_type,x0,y0,dx,dy,radius,color,opacity,xsize,ysize,use_userdraw){\
  692. if( dx == 0 || dy == 0 ){alert(\"increment is zero !!! \");return;};\
  693. var fc = %d+canvas_type;\
  694. var obj = create_canvas%d(fc,xsize,ysize);\
  695. var ctx = obj.getContext('2d');\
  696. var x,y;\
  697. ctx.fillStyle='rgba(255,255,255,0.01)';\
  698. ctx.rect(0,0,xsize,ysize);\
  699. ctx.fill();\
  700. ctx.fillStyle=\"rgba(\"+color+\",0.01)\";\
  701. ctx.strokeStyle=\"rgba(\"+color+\",0.01)\";\
  702. for( x = 0 ; x < xsize ; x = x + dx ){\
  703.  for( y = 0 ; y < ysize ; y = y + dy ){\
  704.   ctx.beginPath();\
  705.   ctx.arc(x,y,radius,0,2*Math.PI,false);\
  706.   ctx.closePath();\
  707.   ctx.fill();\
  708.  };\
  709. };\
  710. if( use_userdraw ){\
  711.  dot_fill_pattern = ctx;\
  712. }\
  713. else\
  714. {\
  715. setTimeout(function(){ filltoborder( x0,y0,color,color,canvas_type,true,ctx); },500);\
  716. };\
  717. return;\
  718. };",canvas_root_id,canvas_root_id);
  719. break;
  720.  
  721. case DRAW_SUBSUP:/* Uses 'script-size for numbers and for sub & sup strings */
  722. /* use_offset
  723.  0=none;
  724.  1=yoffset
  725.  2=xoffset
  726.  3=xyoffset
  727.  4=centered
  728. */
  729. fprintf(js_include_file,"\n/* draw sub sup imitation in canvas */\
  730. function draw_subsup(ctx,x,y,txt,use_offset){\
  731. var fnt = ctx.font;\
  732. var S = fnt.replace(/[A-Za-z]/g, '');\
  733. var s = 0.8*S;\
  734. var px;if(fnt.indexOf('px')>0){px = 'px';}else{if(fnt.indexOf('em')>0){px = 'em';}else{px = 'pt';}};\
  735. var C;var c;var len = txt.length;var baseline = 'middle';var space = 0;ctx.save();var subsup=0;\
  736. var m = 0.4*(ctx.measureText(txt).width);\
  737. var h = ctx.measureText('M').width;\
  738. switch(use_offset){\
  739.  case 0:break;\
  740.  case 1:y=y-h;;break;\
  741.  case 2:x=x+h;break;\
  742.  case 3:x=x+h;y=y-h;;break;\
  743.  case 4:x=x-m;break;\
  744.  default:break;\
  745. };\
  746. ctx.font = S+px+' Helvetica';ctx.textBaseline = baseline;\
  747. for( c = 0 ; c < len ;c++){\
  748.  C = txt.charAt(c);space = 0;\
  749.  if(C == '_'){ctx.font = s+px+' Helvetica';subsup = 1;c++;space = 3;baseline='top';C = txt.charAt(c);}\
  750.  else\
  751.  if(C == '^'){ctx.font = s+px+' Helvetica';subsup = 1;c++;space = 3;baseline='bottom';C = txt.charAt(c);}\
  752.  else\
  753.  if(C == ' '){ctx.font = S+px+' Helvetica';if(subsup == 1){space = 0.6*s - (ctx.measureText('M').width);subsup = 0;};baseline = 'middle';}\
  754.  else\
  755.  if(C >= '0' && C <= '9'){ctx.font = s+'px Helvetica';}\
  756.  else{ctx.font = S+px+' Helvetica';};\
  757.  ctx.textBaseline = baseline;ctx.fillText(C,x,y);x = space + x + ctx.measureText(C).width;\
  758. };\
  759. ctx.stroke();\
  760. ctx.restore();\
  761. return;\
  762. };");
  763. break;
  764.  
  765. case DRAW_TEXTFILL:/* not  used for userdraw */
  766. fprintf(js_include_file,"\n/* draw textfill */\
  767. var text_fill_pattern;\
  768. function draw_textfill(canvas_type,x0,y0,color,fontfamily,xsize,ysize,txt,use_userdraw){\
  769. var fc = %d+canvas_type;\
  770. var obj = create_canvas%d(fc,xsize,ysize);\
  771. var ctx = obj.getContext('2d');\
  772. ctx.font = fontfamily;\
  773. var dx = 2+(ctx.measureText(txt)).width;\
  774. var dy = 2+(ctx.measureText('MI')).width;\
  775. ctx.fillStyle='rgba(255,255,255,0.01)';\
  776. ctx.rect(0,0,xsize,ysize);\
  777. ctx.fill();\
  778. ctx.fillStyle=\"rgba(\"+color+\",0.01)\";\
  779. ctx.strokeStyle=\"rgba(\"+color+\",0.01)\";\
  780. for(var x = 0 ; x <= xsize ; x = x + dx ){\
  781. for(var y = 0 ; y <= ysize ; y = y + dy ){\
  782.  ctx.fillText(txt, x, y);\
  783. };\
  784. };\
  785. if( use_userdraw ){\
  786. text_fill_pattern = ctx;\
  787. }\
  788. else\
  789. {\
  790. setTimeout(function(){ filltoborder( x0,y0,color,color,canvas_type,true,ctx); },500);\
  791. };\
  792. return;};",canvas_root_id,canvas_root_id);
  793. break;
  794.  
  795. case DRAW_DIAMONDFILL:/* not used for userdraw */
  796. fprintf(js_include_file,"\n/* draw hatch fill */\
  797. var diamond_fill_pattern;\
  798. function draw_diamondfill(canvas_type,x0,y0,dx,dy,linewidth,color,stroke_opacity,xsize,ysize,use_userdraw){\
  799. if( dx == 0 || dy == 0 ){alert(\"increment is zero !!! \");return;};\
  800. var fc = %d+canvas_type;\
  801. var obj = create_canvas%d(fc,xsize,ysize);\
  802. var ctx = obj.getContext('2d');\
  803. var x;\
  804. var y;\
  805. ctx.lineWidth = linewidth;\
  806. ctx.fillStyle='rgba(255,255,255,0.01)';\
  807. ctx.rect(0,0,xsize,ysize);\
  808. ctx.fill();\
  809. ctx.strokeStyle=\"rgba(\"+color+\",0.01)\";\
  810. y = ysize;\
  811. ctx.beginPath();\
  812. for( x = 0 ; x <= xsize ; x = x + dx ){\
  813.  ctx.moveTo(x,0);\
  814.  ctx.lineTo(xsize,y);\
  815.  y = y - dy;\
  816. };\
  817. y=0;\
  818. for( x = xsize ; x >= 0 ; x = x - dx){\
  819. ctx.moveTo(x,ysize);\
  820. ctx.lineTo(0,y);\
  821. y = y + dy;\
  822. };\
  823. y = 0;\
  824. for( x = 0 ; x <= xsize ; x = x + dx ){\
  825. ctx.moveTo(x,0);\
  826. ctx.lineTo(0,y);\
  827. y = y + dy;\
  828. };\
  829. y = 0;\
  830. for( x = 0 ; x <= xsize ; x = x + dx ){\
  831. ctx.moveTo(xsize,y);\
  832. ctx.lineTo(x,ysize);\
  833. y = y + dy;\
  834. };\
  835. ctx.closePath();\
  836. ctx.stroke();\
  837. if( use_userdraw ){\
  838. diamond_fill_pattern = ctx;\
  839. }\
  840. else\
  841. {\
  842. setTimeout(function(){ filltoborder( x0,y0,color,color,canvas_type,true,ctx); },500);\
  843. };\
  844. return;\
  845. }",canvas_root_id,canvas_root_id);
  846. break;
  847.  
  848. case DRAW_HATCHFILL:/* not used for userdraw */
  849. fprintf(js_include_file,"\n/* draw hatch fill */\
  850. var hatch_fill_pattern;\
  851. function draw_hatchfill(canvas_type,x0,y0,dx,dy,linewidth,color,stroke_opacity,xsize,ysize,use_userdraw){\
  852. if( dx == 0 || dy == 0 ){alert(\"increment is zero !!! \");return;};\
  853. var fc = %d+canvas_type;\
  854. var obj = create_canvas%d(fc,xsize,ysize);\
  855. var ctx = obj.getContext('2d');\
  856. var x,y;\
  857. ctx.fillStyle='rgba(255,255,255,0.01)';\
  858. ctx.rect(0,0,xsize,ysize);\
  859. ctx.fill();\
  860. ctx.strokeStyle=\"rgba(\"+color+\",0.01)\";\
  861. ctx.lineWidth = linewidth;\
  862. y = ysize;\
  863. ctx.beginPath();\
  864. for( x = 0 ; x <= xsize ; x = x + dx ){\
  865. ctx.moveTo(x,0);\
  866. ctx.lineTo(xsize,y);\
  867. y = y - dy;\
  868. };\
  869. y = 0;\
  870. for( x = xsize ; x >= dx ; x = x - dx){\
  871. ctx.moveTo(x,ysize);\
  872. ctx.lineTo(0,y);\
  873. y = y + dy;\
  874. };\
  875. ctx.closePath();\
  876. ctx.stroke();\
  877. if( use_userdraw ){\
  878. hatch_fill_pattern = ctx;\
  879. }\
  880. else\
  881. {\
  882. setTimeout(function(){ filltoborder( x0,y0,color,color,canvas_type,true,ctx); },500);\
  883. };\
  884. return;};",canvas_root_id,canvas_root_id);
  885. break;
  886.  
  887. case DRAW_LINES:/*  used for js-tracing */
  888. fprintf(js_include_file,"\n/* draw lines */\
  889. function calc_line(x1,x2,y1,y2){\
  890. var marge = 2;\
  891. if(x1 < x2+marge && x1>x2-marge){\
  892.  return [x1,0,x1,ysize];\
  893. };\
  894. if(y1 < y2+marge && y1>y2-marge){\
  895.  return [0,y1,xsize,y1];\
  896. };\
  897. var Y1 = y1 - (x1)*(y2 - y1)/(x2 - x1);\
  898. var Y2 = y1 + (xsize - x1)*(y2 - y1)/(x2 - x1);\
  899. return [0,Y1,xsize,Y2];\
  900. };\
  901. var draw_lines = function(ctx,x_points,y_points,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle){\
  902. ctx.save();\
  903. var line = new Array(4);\
  904. if(use_rotate == 1 ){ctx.rotate(angle*Math.PI/180);}\
  905. ctx.lineWidth = line_width;\
  906. ctx.strokeStyle=\"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  907. if(use_dashed == 1){if(ctx.setLineDash){ctx.setLineDash([dashtype0,dashtype1]);}else{ctx.mozDash = [dashtype0,dashtype1];};};\
  908. for(var p = 0 ; p < x_points.length ; p = p+2 ){\
  909.  line = calc_line(x_points[p],x_points[p+1],y_points[p],y_points[p+1]);\
  910.  ctx.beginPath();\
  911.  ctx.moveTo(line[0],line[1]);\
  912.  ctx.lineTo(line[2],line[3]);\
  913.  ctx.closePath();\
  914.  ctx.stroke();\
  915.  }\
  916.  ctx.restore();\
  917.  return;\
  918. };");
  919. break;
  920.  
  921. case DRAW_CROSSHAIRS:/*  used for tracing */
  922. fprintf(js_include_file,"\n/* draw crosshairs  */\
  923. var draw_crosshairs = function(ctx,x_points,y_points,line_width,crosshair_size,stroke_color,stroke_opacity,use_rotate,angle){\
  924. ctx.save();\
  925. if(use_rotate == 1 ){ctx.rotate(angle*Math.PI/180);}\
  926. ctx.lineWidth = line_width;\
  927. ctx.strokeStyle=\"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  928. var x1,x2,y1,y2;\
  929. for(var p = 0 ; p < x_points.length ; p++ ){\
  930.  x1 = x_points[p] - crosshair_size;\
  931.  x2 = x_points[p] + crosshair_size;\
  932.  y1 = y_points[p] - crosshair_size;\
  933.  y2 = y_points[p] + crosshair_size;\
  934.  ctx.beginPath();\
  935.  ctx.moveTo(x1,y1);\
  936.  ctx.lineTo(x2,y2);\
  937.  ctx.closePath();\
  938.  ctx.stroke();\
  939.  ctx.beginPath();\
  940.  ctx.moveTo(x2,y1);\
  941.  ctx.lineTo(x1,y2);\
  942.  ctx.closePath();\
  943.  ctx.stroke();\
  944. }\
  945. ctx.restore();\
  946.  return;\
  947. };");
  948. break;
  949.  
  950. case DRAW_VIDEO:/* not  used for userdraw */
  951. fprintf(js_include_file,"\n/* draw video */\
  952. var draw_video = function(canvas_root_id,x,y,w,h,URL){\
  953. var canvas_div = document.getElementById(\"canvas_div\"+canvas_root_id);\
  954. var video_div = document.createElement(\"div\");\
  955. canvas_div.appendChild(video_div);\
  956. video_div.style.position = \"absolute\";\
  957. video_div.style.left = x+\"px\";\
  958. video_div.style.top = y+\"px\";\
  959. video_div.style.width = w+\"px\";\
  960. video_div.style.height = h+\"px\";\
  961. var video = document.createElement(\"video\");\
  962. video_div.appendChild(video);\
  963. video.style.width = w+\"px\";\
  964. video.style.height = h+\"px\";\
  965. video.autobuffer = true;\
  966. video.controls = true;video.autoplay = false;\
  967. var src = document.createElement(\"source\");\
  968. src.type = \"video/mp4\";\
  969. src.src = URL;\
  970. video.appendChild(src);\
  971. video.load();\
  972. return;\
  973. };");
  974. break;
  975.  
  976. case DRAW_AUDIO:/* not used for userdraw */
  977. fprintf(js_include_file,"\n/* draw audio */\
  978. var draw_audio = function(canvas_root_id,x,y,w,h,loop,visible,URL1,URL2){\
  979. var canvas_div = document.getElementById(\"canvas_div\"+canvas_root_id);\
  980. var audio_div = document.createElement(\"div\");\
  981. canvas_div.appendChild(audio_div);\
  982. audio_div.style.position = \"absolute\";\
  983. audio_div.style.left = x+\"px\";\
  984. audio_div.style.top = y+\"px\";\
  985. audio_div.style.width = w+\"px\";\
  986. audio_div.style.height = h+\"px\";\
  987. var audio = document.createElement(\"audio\");\
  988. audio_div.appendChild(audio);\
  989. audio.setAttribute(\"style\",\"width:\"+w+\"px;height:\"+h+\"px\");\
  990. audio.autobuffer = true;\
  991. if(visible == 1 ){ audio.controls = true;audio.autoplay = false;}else{ audio.controls = false;audio.autoplay = true;};\
  992. if(loop == 1 ){ audio.loop = true;}else{ audio.loop = false;};\
  993. var src1 = document.createElement(\"source\");\
  994. src1.type = \"audio/ogg\";\
  995. src1.src = URL1;\
  996. audio.appendChild(src1);\
  997. var src2 = document.createElement(\"source\");\
  998. src2.type = \"audio/mpeg\";\
  999. src2.src = URL2;\
  1000. audio.appendChild(src2);\
  1001. audio.load();\
  1002. return;\
  1003. };");
  1004. break;
  1005.  
  1006. case DRAW_HTTP:/* not  used for userdraw */
  1007. fprintf(js_include_file,"\n/* draw http */\
  1008. var draw_http = function(canvas_root_id,x,y,w,h,URL){\
  1009. var canvas_div = document.getElementById(\"canvas_div\"+canvas_root_id);\
  1010. var http_div = document.createElement(\"div\");\
  1011. var iframe = document.createElement(\"iframe\");\
  1012. canvas_div.appendChild(http_div);\
  1013. http_div.appendChild(iframe);\
  1014. iframe.src = URL;\
  1015. iframe.setAttribute(\"width\",w);\
  1016. iframe.setAttribute(\"height\",h);\
  1017. return;\
  1018. };");
  1019. break;
  1020.  
  1021. case DRAW_XML:
  1022. /*
  1023. !! function draw_xml(object)
  1024. !! produced by : DRAW_XML
  1025. !! used by commands: katex,latex,mathml,html,obabel
  1026. !! uses js-functions: calculate_size(xml_div),rad2deg(rad)
  1027. !! user interaction: drag,onclick,slider
  1028. !! reply function: read_dragdrop()
  1029.  
  1030. onclick=0; no interaction
  1031. onclick=1: click
  1032. onclick=2: drag ==> always centered (use_offset=4)
  1033. onclick=3: slider + click on object
  1034. onclick=4: slider (always active , keyword 'active' in slider params)
  1035. onclick=5: slider + dragdrop
  1036. xy:  drag_type = 0;
  1037. x:   drag_type = 1;
  1038. y:   drag_type = 2;
  1039.  
  1040. obj.type: mathml,katex,html,svg,image(bitmap) (attention: for centering image needs to be measured after loading page !!)
  1041. */
  1042.  
  1043. fprintf(js_include_file,"\n/* draw xml */\
  1044. function centered(xml_div,obj){\
  1045. var ww = 0.5*(parseFloat(window.getComputedStyle(xml_div).width));\
  1046. var hh = 0.5*(parseFloat(window.getComputedStyle(xml_div).height));\
  1047. obj.offset = [ ww , hh ];\
  1048. xml_div.style.left = obj.x[0] - obj.offset[0] +'px';xml_div.style.top  = obj.y[0] - obj.offset[1] +'px';\
  1049. };\
  1050. function rad2deg(rad){return rad*180/(Math.PI);};\
  1051. if( typeof(slidergroup) !== 'object' ){ var slidergroup = [];};\
  1052. function draw_xml(obj){\
  1053. var mouse;var xy = [obj.x[0],obj.y[0]];\
  1054. var xml_div;\
  1055. dragdrop_reply[obj.object_cnt] = {object_cnt:obj.object_cnt,type:obj.onclick,x:obj.x,y:obj.y,r:0,angle:obj.angle,clicked:0};\
  1056. if( obj.once ){\
  1057.  xml_div = document.createElement('DIV');\
  1058.  canvas_div.appendChild(xml_div);\
  1059.  if( obj.type == 'katex' ){ obj.mathml = LoadKaTeX('html',obj.mathml);};\
  1060.  xml_div.id = 'xml_div'+obj.id;\
  1061.  xml_div.innerHTML = obj.mathml;\
  1062.  xml_div.style.position = \"absolute\";\
  1063.  xml_div.style.color = \"rgba(\"+obj.stroke_color+\",\"+obj.stroke_opacity+\")\";\
  1064.  xml_div.style.font = obj.fontfamily;\
  1065.  if( ! obj.rotation_center){obj.rotation_center = [obj.x[0],obj.y[0]];}else{obj.rotation_center=[x2px(obj.rotation_center[0]) ,y2px(obj.rotation_center[1]) ];};\
  1066.  if( obj.use_center == 1 ){if( obj.type == 'image' ){xml_div.addEventListener('load',function(e){centered(xml_div,obj);},true);}else{%s};};\
  1067. }\
  1068. else\
  1069. {\
  1070.  xml_div = document.getElementById('xml_div'+obj.id );\
  1071. };\
  1072. if( typeof(xml_div) === 'undefined' ){console.log('hmmmmm'); return;};\
  1073. xml_div.style.left = parseInt(obj.x[0] - obj.offset[0]) +'px';\
  1074. xml_div.style.top  = parseInt(obj.y[0] - obj.offset[1]) +'px';\
  1075. var back_color = 'rgba('+obj.fill_color+','+obj.fill_opacity+')';\
  1076. var no_color = 'rgba(255,255,255,0)';var dragging = false;\
  1077. if( obj.use_affine != 0 || obj.angle != 0 ){\
  1078.  xml_div.style.transform = 'matrix('+obj.transform[0]+','+obj.transform[1]+','+obj.transform[2]+','+obj.transform[3]+','+obj.transform[4]+','+obj.transform[5]+') rotate('+rad2deg(obj.angle)+'deg)';\
  1079. };\
  1080. if( obj.once ){\
  1081.  obj.once = false;\
  1082.  switch(obj.onclick){\
  1083.   case 2:\
  1084.    if(isTouch){\
  1085.     canvas_div.addEventListener('touchmove' ,function(evt){ evt.preventDefault();if(!dragging){return;};mouse = getMouse(evt.changedTouches[0],xml_div);xy = multisnap_check( mouse.x,mouse.y,obj.use_snap);xml_div.style.left = xy[0] - obj.offset[0] - obj.transform[4] + 'px';xml_div.style.top = xy[1] - obj.offset[1] - obj.transform[5] + 'px';},false);\
  1086.     canvas_div.addEventListener('touchend'  ,function(evt){ evt.preventDefault();dragging = false;xml_div.style.backgroundColor = no_color;dragdrop_reply[obj.object_cnt] = {object_cnt:obj.object_cnt,type:obj.onclick,x:xy[0],y:xy[1],r:0,angle:obj.angle,clicked:0};obj.x[0] = xy[0];obj.y[0] = xy[1];},false);\
  1087.     xml_div.addEventListener('touchstart',function(evt){evt.preventDefault();if(dragging){dragging = false;xml_div.style.backgroundColor = no_color;}else{dragging = true;xml_div.style.backgroundColor = back_color;};},false);\
  1088.     xml_div.addEventListener('touchend'  ,function(evt){ evt.preventDefault();dragging = false;xml_div.style.backgroundColor = no_color;dragdrop_reply[obj.object_cnt] = {object_cnt:obj.object_cnt,type:obj.onclick,x:xy[0],y:xy[1],r:0,angle:obj.angle,clicked:0};obj.x[0] = xy[0];obj.y[0] = xy[1];},false);\
  1089.    }else{\
  1090.     canvas_div.addEventListener('mousemove',function(evt){if(!dragging){return;};mouse = getMouse(evt,xml_div);xy = multisnap_check( mouse.x,mouse.y,obj.use_snap);xml_div.style.left = xy[0] - obj.offset[0] - obj.transform[4] + 'px';xml_div.style.top = xy[1] - obj.offset[1] - obj.transform[5] + 'px';},false);\
  1091.     canvas_div.addEventListener('mouseup',function(evt){dragging = false;xml_div.style.backgroundColor = no_color;dragdrop_reply[obj.object_cnt] = {object_cnt:obj.object_cnt,type:obj.onclick,x:xy[0],y:xy[1],r:0,angle:obj.angle,clicked:0};obj.x[0] = xy[0];obj.y[0] = xy[1];},false);\
  1092.     xml_div.addEventListener('mousedown', function(evt){if(dragging){dragging = false;xml_div.style.backgroundColor = no_color;}else{dragging = true;xml_div.style.backgroundColor = back_color;};},false);\
  1093.    };\
  1094.    break;\
  1095.   case 1:\
  1096.    if(isTouch ){\
  1097.     xml_div.addEventListener('touchstart', function(e){ e.preventDefault();if(dragdrop_reply[obj.object_cnt].clicked == 0){ dragdrop_reply[obj.object_cnt].clicked = 1;xml_div.style.backgroundColor = back_color;}else{dragdrop_reply[obj.object_cnt].clicked = 0;xml_div.style.backgroundColor = no_color;};} ,false);\
  1098.    }else{\
  1099.     xml_div.addEventListener('mousedown'  , function(evt){if(dragdrop_reply[obj.object_cnt].clicked == 0){ dragdrop_reply[obj.object_cnt].clicked = 1;xml_div.style.backgroundColor = back_color;}else{dragdrop_reply[obj.object_cnt].clicked = 0;xml_div.style.backgroundColor = no_color;};} ,false);\
  1100.    };\
  1101.    break;\
  1102.   case 3:\
  1103.    if(isTouch ){\
  1104.     xml_div.addEventListener('touchstart',function(evt){ if(slidergroup[obj.object_cnt] == null ){ slidergroup[obj.object_cnt] = obj;xml_div.style.backgroundColor = back_color;}else{ slidergroup[obj.object_cnt] = null;xml_div.style.backgroundColor = no_color;};} ,false);\
  1105.    }else{\
  1106.     xml_div.addEventListener('mousedown' ,function(evt){ if(slidergroup[obj.object_cnt] == null ){ slidergroup[obj.object_cnt] = obj;xml_div.style.backgroundColor = back_color;}else{ slidergroup[obj.object_cnt] = null;xml_div.style.backgroundColor = no_color;};} ,false);\
  1107.    };\
  1108.    break;\
  1109.   case 4:slidergroup[obj.object_cnt] = obj;break;\
  1110.   case 5:slidergroup[obj.object_cnt] = obj;\
  1111.    canvas_div.addEventListener('mousemove',function(evt){if(!dragging){return;};mouse = getMouse(evt,xml_div);xy = multisnap_check( mouse.x,mouse.y,obj.use_snap);xml_div.style.left = xy[0] - obj.offset[0] - obj.transform[4] + 'px';xml_div.style.top = xy[1] - obj.offset[1] - obj.transform[5] + 'px';},false);\
  1112.    canvas_div.addEventListener('mouseup',function(evt){dragging = false;xml_div.style.backgroundColor = no_color;dragdrop_reply[obj.object_cnt] = {object_cnt:obj.object_cnt,type:obj.onclick,x:xy[0],y:xy[1],r:0,angle:obj.angle,clicked:0};obj.x[0] = xy[0];obj.y[0] = xy[1];},false);\
  1113.    xml_div.addEventListener('mousedown', function(evt){if(dragging){dragging = false;xml_div.style.backgroundColor = no_color;}else{dragging = true;xml_div.style.backgroundColor = back_color;};},false);\
  1114.    break;\
  1115.   default: break;\
  1116.  };\
  1117. };\
  1118. return;\
  1119. };",mathjax);
  1120.  
  1121. /*
  1122. console.log('angle='+obj.angle+'obj.use_center='+obj.use_center+'id='+obj.id+'xml_div.id = '+xml_div.id+' once ='+obj.once+' offset='+ obj.offset+' div x = '+xml_div.style.left+' div y ='+xml_div.style.top+' obj.x='+px2x(obj.x)+'obj.y='+px2y(obj.y));\
  1123. */
  1124. break;
  1125.  
  1126. case DRAW_SGRAPH:
  1127. /*
  1128.  xstart = given
  1129.  ystart = given
  1130.  sgraph(canvas_type,precision,xmajor,ymajor,xminor,yminor,majorcolor,minorcolor,fontfamily)
  1131. */
  1132. fprintf(js_include_file,"\n/* draw sgraph */\
  1133. var draw_sgraph = function(canvas_type,precision,xmajor,ymajor,xminor,yminor,majorcolor,minorcolor,fontfamily,opacity,font_size){\
  1134. var obj;if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){obj = document.getElementById(\"wims_canvas%d\"+canvas_type);}else{ obj = create_canvas%d(canvas_type,xsize,ysize);};\
  1135. var ctx = obj.getContext(\"2d\");\
  1136. ctx.font = fontfamily;\
  1137. var minor_opacity = 0.8*opacity;\
  1138. ctx.clearRect(0,0,xsize,ysize);\
  1139. var zero_x = 0.1*xsize;\
  1140. var zero_y = 0.9*ysize;\
  1141. var snor_x;var snor_y;\
  1142. if( xstart != xmin){\
  1143.  snor_x = 0.1*xsize;\
  1144. }\
  1145. else\
  1146. {\
  1147.  snor_x = 0;\
  1148.  xstart = xmin;\
  1149. };\
  1150. ctx.strokeStyle = \"rgba(\"+majorcolor+\",\"+opacity+\")\";\
  1151. ctx.lineWidth = 2;\
  1152. ctx.beginPath();\
  1153. ctx.moveTo(xsize,zero_y);\
  1154. ctx.lineTo(zero_x,zero_y);\
  1155. ctx.lineTo(zero_x,0);\
  1156. ctx.stroke();\
  1157. ctx.closePath();\
  1158. ctx.beginPath();\
  1159. ctx.moveTo(zero_x,zero_y);\
  1160. ctx.lineTo(zero_x + 0.25*snor_x,zero_y - 0.1*snor_x);\
  1161. ctx.lineTo(zero_x + 0.5*snor_x,zero_y + 0.1*snor_x);\
  1162. ctx.lineTo(zero_x + 0.75*snor_x,zero_y - 0.1*snor_x);\
  1163. ctx.lineTo(zero_x + snor_x,zero_y);\
  1164. ctx.stroke();\
  1165. ctx.closePath();\
  1166. ctx.beginPath();\
  1167. var num = xstart;\
  1168. var flipflop = 1;\
  1169. var step_x = xmajor*(xsize - zero_x - snor_x)/(xmax - xstart);\
  1170. var txtsize;var txt_marge=step_x - 5;\
  1171. for(var x = zero_x+snor_x ; x < xsize;x = x + step_x){\
  1172.  txtsize = ctx.measureText(num).width;\
  1173.  if( txtsize > txt_marge ){if( flipflop == 1 ){flipflop = 0;}else{flipflop = 1;};};\
  1174.  if( flipflop == 1){\
  1175.   ctx.fillText(num,x - 0.5*txtsize,zero_y+font_size);\
  1176.  }\
  1177.  else\
  1178.  {\
  1179.   ctx.fillText(num,x - 0.5*txtsize,zero_y+2*font_size);\
  1180.  };\
  1181.  num = num + xmajor;\
  1182. };\
  1183. ctx.stroke();\
  1184. ctx.closePath();\
  1185. ctx.lineWidth = 1;\
  1186. ctx.beginPath();\
  1187. for(var x = zero_x+snor_x ; x < xsize;x = x + step_x){\
  1188.   ctx.moveTo(x,zero_y);\
  1189.   ctx.lineTo(x,0);\
  1190. };\
  1191. ctx.stroke();\
  1192. ctx.closePath();\
  1193. if( xminor > 1){\
  1194.  ctx.lineWidth = 0.5;\
  1195.  ctx.beginPath();\
  1196.  ctx.strokeStyle = \"rgba(\"+minorcolor+\",\"+minor_opacity+\")\";\
  1197.  var minor_step_x = step_x / xminor;\
  1198.  var nx;\
  1199.  for(var x = zero_x+snor_x; x < xsize;x = x + step_x){\
  1200.    num = 1;\
  1201.    for(var p = 1 ; p < xminor ; p++){\
  1202.     nx = x + num*minor_step_x;\
  1203.     ctx.moveTo(nx,zero_y);\
  1204.     ctx.lineTo(nx,0);\
  1205.     num++;\
  1206.    };\
  1207.  };\
  1208.  ctx.stroke();\
  1209.  ctx.closePath();\
  1210.  ctx.beginPath();\
  1211.  ctx.lineWidth = 2;\
  1212.  ctx.strokeStyle = \"rgba(\"+majorcolor+\",\"+opacity+\")\";\
  1213.  for(var x = zero_x+snor_x ; x < xsize;x = x + step_x){\
  1214.   ctx.moveTo(x,zero_y);ctx.lineTo(x,zero_y - 12);\
  1215.  };\
  1216.  for(var x = zero_x+snor_x ; x < xsize;x = x + minor_step_x){\
  1217.   ctx.moveTo(x,zero_y);ctx.lineTo(x,zero_y - 6);\
  1218.  };\
  1219.  ctx.stroke();\
  1220.  ctx.closePath();\
  1221.  ctx.lineWidth = 0.5;\
  1222. };\
  1223. xmin = xstart - (xmajor*(zero_x+snor_x)/step_x);\
  1224. if( ystart != ymin){\
  1225.  snor_y = 0.1*ysize;\
  1226. }\
  1227. else\
  1228. {\
  1229.  snor_y = 0;\
  1230.  ystart = ymin;\
  1231. };\
  1232. ctx.lineWidth = 2;\
  1233. ctx.strokeStyle = \"rgba(\"+majorcolor+\",\"+opacity+\")\";\
  1234. ctx.beginPath();\
  1235. ctx.moveTo(zero_x,zero_y);\
  1236. ctx.lineTo(zero_x - 0.1*snor_y,zero_y - 0.25*snor_y);\
  1237. ctx.lineTo(zero_x + 0.1*snor_y,zero_y - 0.5*snor_y);\
  1238. ctx.lineTo(zero_x - 0.1*snor_y,zero_y - 0.75*snor_y);\
  1239. ctx.lineTo(zero_x,zero_y - snor_y);\
  1240. ctx.stroke();\
  1241. ctx.closePath();\
  1242. ctx.beginPath();\
  1243. ctx.lineWidth = 1;\
  1244. num = ystart;\
  1245. var step_y = ymajor*(zero_y - snor_y)/(ymax - ystart);\
  1246. for(var y = zero_y - snor_y ; y > 0; y = y - step_y){\
  1247.  ctx.moveTo(zero_x,y);\
  1248.  ctx.lineTo(xsize,y);\
  1249.  ctx.fillText(num,zero_x - ctx.measureText(num+\" \").width,parseInt(y+0.2*font_size));\
  1250.  num = num + ymajor;\
  1251. };\
  1252. ctx.stroke();\
  1253. ctx.closePath();\
  1254. if( yminor > 1){\
  1255.  ctx.lineWidth = 0.5;\
  1256.  ctx.beginPath();\
  1257.  ctx.strokeStyle = \"rgba(\"+minorcolor+\",\"+minor_opacity+\")\";\
  1258.  var minor_step_y = step_y / yminor;\
  1259.  var ny;\
  1260.  for(var y = 0 ; y < zero_y - snor_y ;y = y + step_y){\
  1261.   num = 1;\
  1262.   for(var p = 1 ;p < yminor;p++){\
  1263.     ny = y + num*minor_step_y;\
  1264.     ctx.moveTo(zero_x,ny);\
  1265.     ctx.lineTo(xsize,ny);\
  1266.     num++;\
  1267.    };\
  1268.  };\
  1269.  ctx.stroke();\
  1270.  ctx.closePath();\
  1271.  ctx.lineWidth = 2;\
  1272.  ctx.beginPath();\
  1273.  ctx.strokeStyle = \"rgba(\"+majorcolor+\",\"+opacity+\")\";\
  1274.  for(var y = zero_y - snor_y ; y > 0 ;y = y - step_y){\
  1275.   ctx.moveTo(zero_x,y);\
  1276.   ctx.lineTo(zero_x+12,y);\
  1277.  };\
  1278.  for(var y = zero_y - snor_y ; y > 0 ;y = y - minor_step_y){\
  1279.   ctx.moveTo(zero_x,y);\
  1280.   ctx.lineTo(zero_x+6,y);\
  1281.  };\
  1282.  ctx.stroke();\
  1283.  ctx.closePath();\
  1284. };\
  1285. ymin = ystart - (ymajor*(ysize - zero_y + snor_y)/step_y);\
  1286. if( typeof(legend%d)  !== 'undefined' ){\
  1287.  ctx.globalAlpha = 1.0;\
  1288.  var y_offset = 2*font_size;\
  1289.  var txt;var txt_size;\
  1290.  var x_offset = xsize - 2*font_size;\
  1291.  var l_length = legend%d.length;var barcolor = new Array();\
  1292.  if( typeof(legendcolors%d) !== 'undefined' ){\
  1293.   for(var p = 0 ; p < l_length ; p++){\
  1294.    barcolor[p] = legendcolors%d[p];\
  1295.   };\
  1296.  }else{\
  1297.   if( barcolor.length == 0 ){\
  1298.    for(var p = 0 ; p < l_length ; p++){\
  1299.     barcolor[p] = stroke_color;\
  1300.    };\
  1301.   };\
  1302.  };\
  1303.  for(var p = 0; p < l_length; p++){\
  1304.   ctx.fillStyle = barcolor[p];\
  1305.   txt = legend%d[p];\
  1306.   txt_size = ctx.measureText(txt).width;\
  1307.   ctx.fillText(legend%d[p],x_offset - txt_size, y_offset);\
  1308.   y_offset = parseInt(y_offset + 1.5*font_size);\
  1309.  };\
  1310. };\
  1311. if( typeof(xaxislabel) !== 'undefined' ){\
  1312.   ctx.fillStyle = \'#000000\';\
  1313.   var txt_size = ctx.measureText(xaxislabel).width + 4 ;\
  1314.   ctx.fillText(xaxislabel,xsize - txt_size, zero_y - 7);\
  1315. };\
  1316. if( typeof(yaxislabel) !== 'undefined'){\
  1317.   ctx.save();\
  1318.   ctx.fillStyle = \'#000000\';\
  1319.   var txt_size = ctx.measureText(yaxislabel).width;\
  1320.   ctx.translate(zero_x+8 + font_size,txt_size+font_size);\
  1321.   ctx.rotate(-0.5*Math.PI);\
  1322.   ctx.fillText(yaxislabel,0,0);\
  1323.   ctx.restore();\
  1324. };\
  1325. };",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);
  1326. break;
  1327.  
  1328. case DRAW_NUMBERLINE:
  1329. fprintf(js_include_file,"\n/* draw numberline */\
  1330. var draw_numberline = function(canvas_type,use_axis_numbering,x0,x1,xmajor,xminor,y0,y1,linewidth,strokecolor,strokeopacity,fontfamily,fontcolor,precision){\
  1331. var obj = create_canvas%d(canvas_type,xsize,ysize);\
  1332. var ctx = obj.getContext(\"2d\");\
  1333. ctx.lineWidth = linewidth || 1;\
  1334. ctx.strokeStyle = \"rgba(\"+strokecolor+\",\"+strokeopacity+\")\";\
  1335. ctx.font = fontfamily || 'Arial 12px';\
  1336. var fontsize = parseInt(ctx.font);\
  1337. ctx.fillStyle =  \"rgba(\"+fontcolor+\",\"+strokeopacity+\")\";\
  1338. x1 = x2px(x1);\
  1339. x0 = x2px(x0);\
  1340. y0 = y2px(y0);\
  1341. y1 = y2px(y1);\
  1342. var sub_devision = -1;\
  1343. if( xminor%%2 == 0 ){ sub_devision = xminor/2; };\
  1344. var ybase1 = parseInt( y0 + fontsize + 2 );\
  1345. var ybase2 = parseInt( ybase1 + fontsize + 2 );\
  1346. var yh = Math.abs(parseInt( y0 - 0.3*(y0 -y1)));\
  1347. var ys = Math.abs(parseInt( y0 - 0.6*(y0 -y1)));\
  1348. xmajor = x2px(xmajor) - x2px(0);\
  1349. var i;var len;var p;\
  1350. xminor = xmajor / xminor;\
  1351. ctx.beginPath();\
  1352. for(p = x0 ; p < x1 ; p = p + xmajor){\
  1353.  ctx.moveTo(p,y0);ctx.lineTo(p,y1);i = 0;\
  1354.  for(var s = p ; s < p + xmajor ; s = s + xminor ){\
  1355.   ctx.moveTo(s,y0);\
  1356.   if( sub_devision == i){ ctx.lineTo(s,ys); } else { ctx.lineTo(s,yh); };\
  1357.   i++;\
  1358.  };\
  1359. };\
  1360. ctx.moveTo(p,y0);ctx.lineTo(p,y1);\
  1361. ctx.closePath();\
  1362. ctx.stroke();\
  1363. if( use_axis_numbering >-1 ){\
  1364.  var str = x_strings[use_axis_numbering];\
  1365.  len = str.length;if((len/2+0.5)%%2 == 0){ alert(\"xaxis number unpaired:  text missing ! \");return;};\
  1366.  var corr;var x_nums;var x_text;var flipflop = 0;var off = ybase1;\
  1367.  ctx.beginPath();\
  1368.  if( x_strings_up[use_axis_numbering] == null){\
  1369.   for(var p = 0 ; p < len ; p = p+2){\
  1370.    var x_nums = x2px(eval(str[p]));\
  1371.    var x_text = str[p+1];\
  1372.    corr = ctx.measureText(x_text).width;\
  1373.    if( corr > xmajor){ if(flipflop == 0 ){flipflop = 1; off = ybase2;}else{flipflop = 0; off = ybase1;};};\
  1374.    ctx.fillText(x_text,parseInt(x_nums-0.5*corr),off);\
  1375.   };\
  1376.  }\
  1377.  else\
  1378.  {\
  1379.   for(var p = 0 ; p < len ; p = p+2){\
  1380.    x_nums = x2px(eval(str[p]));\
  1381.    x_text = str[p+1];\
  1382.    corr = ctx.measureText(x_text).width + ybase1 - fontsize;\
  1383.    ctx.save();\
  1384.    ctx.translate(x_nums+0.5*fontsize, corr);\
  1385.    ctx.rotate(-1.5708);\
  1386.    ctx.fillText(x_text,0,0);\
  1387.    ctx.restore();\
  1388.   };\
  1389.  }\
  1390. }\
  1391. else\
  1392. {\
  1393.  var corr;var num;var flipflop = 0;var off = ybase1;\
  1394.  var prec = parseInt(Math.log(precision)/Math.log(10));\
  1395.  for(var p = x0 ; p < x1+xmajor ; p = p+xmajor){\
  1396.   num = (px2x(p)).toFixed(prec);\
  1397.   corr = ctx.measureText(num).width;\
  1398.   if( corr > xmajor){ if(flipflop == 0 ){flipflop = 1; off = ybase2;}else{flipflop = 0; off = ybase1;};};\
  1399.   ctx.fillText(num,parseInt(p - 0.5*corr),off);\
  1400.  };\
  1401. };\
  1402. };",canvas_root_id);
  1403. break;
  1404.  
  1405. case DRAW_GRID:/* not used for userdraw */
  1406. fprintf(js_include_file,"\n/* draw grid */\
  1407. var draw_grid%d = function(canvas_type,precision,stroke_opacity,xmajor,ymajor,xminor,yminor,tics_length,line_width,stroke_color,axis_color,font_size,font_family,use_axis,use_axis_numbering,use_dashed,dashtype0,dashtype1,font_color,fill_opacity){\
  1408. var obj;if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){obj = document.getElementById(\"wims_canvas%d\"+canvas_type);}else{obj = create_canvas%d(canvas_type,xsize,ysize);};\
  1409. var ctx = obj.getContext(\"2d\");ctx.clearRect(0,0,xsize,ysize);\
  1410. if(use_dashed == 1){if(ctx.setLineDash){ctx.setLineDash([dashtype0,dashtype1]);}else{ctx.mozDash = [dashtype0,dashtype1];};};\
  1411. ctx.save();\
  1412. var stroke_color = \"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  1413. ctx.fillStyle = \"rgba(\"+font_color+\",\"+1.0+\")\";\
  1414. var axis_color = \"rgba(\"+axis_color+\",\"+stroke_opacity+\")\";\
  1415. ctx.font = font_family;\
  1416. var barcolor = new Array();\
  1417. var xstep = xsize*xmajor/(xmax - xmin);\
  1418. var ystep = ysize*ymajor/(ymax - ymin);\
  1419. var x2step = xstep / xminor;\
  1420. var y2step = ystep / yminor;\
  1421. var zero_x = x2px(0);var zero_y = y2px(0);var f_x;var f_y;\
  1422. if(xmin < 0 ){ f_x = -1;}else{ f_x = 1;};\
  1423. if(ymin < 0 ){ f_y = -1;}else{ f_y = 1;};\
  1424. ctx.beginPath();\
  1425. ctx.lineWidth = line_width;\
  1426. ctx.strokeStyle = stroke_color;\
  1427. for(var p = zero_x ; p < xsize; p = p + xstep){\
  1428. ctx.moveTo(p,0);\
  1429. ctx.lineTo(p,ysize);\
  1430. };\
  1431. for(var p = zero_x ; p > 0; p = p - xstep){\
  1432. ctx.moveTo(p,0);\
  1433. ctx.lineTo(p,ysize);\
  1434. };\
  1435. for(var p = zero_y ; p < ysize; p = p + ystep){\
  1436. ctx.moveTo(0,p);\
  1437. ctx.lineTo(xsize,p);\
  1438. };\
  1439. for(var p = zero_y ; p > 0; p = p - ystep){\
  1440. ctx.moveTo(0,p);\
  1441. ctx.lineTo(xsize,p);\
  1442. };\
  1443. if( typeof(xaxislabel) !== 'undefined' ){\
  1444. ctx.save();\
  1445. ctx.font = \"italic \"+font_size+\"px Arial\";\
  1446. var corr =  parseInt(1.1*ctx.measureText(xaxislabel).width);\
  1447. ctx.fillText(xaxislabel,xsize - corr,zero_y - tics_length - 0.4*font_size);\
  1448. ctx.restore();\
  1449. };\
  1450. if( typeof(yaxislabel) !== 'undefined' ){\
  1451. ctx.save();\
  1452. ctx.font = \"italic \"+font_size+\"px Arial\";\
  1453. var corr = parseInt(ctx.measureText(yaxislabel).width + font_size);\
  1454. ctx.translate(zero_x+tics_length + font_size,corr);\
  1455. ctx.rotate(-0.5*Math.PI);\
  1456. ctx.fillText(yaxislabel,0,0);\
  1457. ctx.restore();\
  1458. };\
  1459. ctx.stroke();\
  1460. ctx.closePath();",canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id);
  1461.  
  1462. if( use_axis == 1 ){
  1463. fprintf(js_include_file,"\
  1464. ctx.save();\
  1465. ctx.beginPath();\
  1466. ctx.strokeStyle = stroke_color;\
  1467. ctx.lineWidth = 0.6*line_width;\
  1468. for(var p = zero_x ; p < xsize; p = p + x2step){\
  1469.  ctx.moveTo(p,0);\
  1470.  ctx.lineTo(p,ysize);\
  1471. };\
  1472. for(var p = zero_x ; p > 0; p = p - x2step){\
  1473.  ctx.moveTo(p,0);\
  1474.  ctx.lineTo(p,ysize);\
  1475. };\
  1476. for(var p = zero_y ; p < ysize; p = p + y2step){\
  1477.  ctx.moveTo(0,p);\
  1478.  ctx.lineTo(xsize,p);\
  1479. };\
  1480. for(var p = zero_y ; p > 0; p = p - y2step){\
  1481.  ctx.moveTo(0,p);\
  1482.  ctx.lineTo(xsize,p);\
  1483. };\
  1484. ctx.stroke();\
  1485. ctx.closePath();\
  1486. ctx.beginPath();\
  1487. ctx.lineWidth = 2*line_width;\
  1488. ctx.strokeStyle = axis_color;\
  1489. ctx.moveTo(0,zero_y);\
  1490. ctx.lineTo(xsize,zero_y);\
  1491. ctx.moveTo(zero_x,0);\
  1492. ctx.lineTo(zero_x,ysize);\
  1493. ctx.stroke();\
  1494. ctx.closePath();\
  1495. ctx.lineWidth = line_width+0.5;\
  1496. ctx.beginPath();\
  1497. for(var p = zero_x ; p < xsize; p = p + xstep){\
  1498.  ctx.moveTo(p,zero_y-tics_length);\
  1499.  ctx.lineTo(p,zero_y+tics_length);\
  1500. };\
  1501. for(var p = zero_x ; p > 0; p = p - xstep){\
  1502.  ctx.moveTo(p,zero_y-tics_length);\
  1503.  ctx.lineTo(p,zero_y+tics_length);\
  1504. };\
  1505. for(var p = zero_y ; p < ysize; p = p + ystep){\
  1506.  ctx.moveTo(zero_x-tics_length,p);\
  1507.  ctx.lineTo(zero_x+tics_length,p);\
  1508. };\
  1509. for(var p = zero_y ; p > 0; p = p - ystep){\
  1510.  ctx.moveTo(zero_x-tics_length,p);\
  1511.  ctx.lineTo(zero_x+tics_length,p);\
  1512. };\
  1513. for(var p = zero_x ; p < xsize; p = p + x2step){\
  1514.  ctx.moveTo(p,zero_y-0.5*tics_length);\
  1515.  ctx.lineTo(p,zero_y+0.5*tics_length);\
  1516. };\
  1517. for(var p = zero_x ; p > 0; p = p - x2step){\
  1518.  ctx.moveTo(p,zero_y-0.5*tics_length);\
  1519.  ctx.lineTo(p,zero_y+0.5*tics_length);\
  1520. };\
  1521. for(var p = zero_y ; p < ysize; p = p + y2step){\
  1522.  ctx.moveTo(zero_x-0.5*tics_length,p);\
  1523.  ctx.lineTo(zero_x+0.5*tics_length,p);\
  1524. };\
  1525. for(var p = zero_y ; p > 0; p = p - y2step){\
  1526.  ctx.moveTo(zero_x-0.5*tics_length,p);\
  1527.  ctx.lineTo(zero_x+0.5*tics_length,p);\
  1528. };\
  1529. ctx.stroke();\
  1530. ctx.closePath();\
  1531. ctx.restore();");
  1532. }
  1533.  
  1534. if( use_axis_numbering != -1 ){
  1535. fprintf(js_include_file,"\
  1536. ctx.save();\
  1537. ctx.fillColor = axis_color;\
  1538. ctx.strokeStyle = axis_color;\
  1539. ctx.lineWidth = 2*line_width;\
  1540. ctx.font = font_family;\
  1541. var shift = zero_y+2*font_size;var flip=0;var skip=0;var corr;var cnt;var disp_cnt;var prec;\
  1542. if( x_strings[use_axis_numbering] != null ){\
  1543.  var str = x_strings[use_axis_numbering];\
  1544.  var len = str.length;if((len/2+0.5)%%2 == 0){ alert(\"xaxis number unpaired:  text missing ! \");return;};\
  1545.  ctx.beginPath();\
  1546.  if( x_strings_up[use_axis_numbering] == null){\
  1547.   for(var p = 0 ; p < len ; p = p+2){\
  1548.    var x_nums = x2px(eval(str[p]));\
  1549.    var x_text = str[p+1];\
  1550.    corr = ctx.measureText(x_text).width;\
  1551.    skip = 1.2*corr/xstep;\
  1552.    if( zero_y+2*font_size > ysize ){shift = ysize - 2*font_size;};\
  1553.    if( skip > 1 ){if(flip == 0 ){flip = 1; shift = shift + font_size;}else{flip = 0; shift = shift - font_size;};};\
  1554.    ctx.fillText(x_text,parseInt(x_nums-0.5*corr),shift);\
  1555.    ctx.moveTo(x_nums,zero_y - tics_length);\
  1556.    ctx.lineTo(x_nums,zero_y + tics_length);\
  1557.   };\
  1558.  }\
  1559.  else\
  1560.  {\
  1561.   for(var p = 0 ; p < len ; p = p+2){\
  1562.    var x_nums = x2px(eval(str[p]));\
  1563.    var x_text = str[p+1];\
  1564.    corr = 2 + tics_length + zero_y + ctx.measureText(x_text).width;\
  1565.    if( corr > ysize ){corr = ysize;};\
  1566.    ctx.save();\
  1567.    ctx.translate(x_nums+0.25*font_size, corr);\
  1568.    ctx.rotate(-1.5708);\
  1569.    ctx.fillText(x_text,0,0);\
  1570.    ctx.restore();\
  1571.    ctx.moveTo(x_nums,zero_y - tics_length);\
  1572.    ctx.lineTo(x_nums,zero_y + tics_length);\
  1573.   };\
  1574.  };\
  1575.  ctx.closePath();\
  1576. }\
  1577. else\
  1578. {\
  1579.  skip = 1;cnt = px2x(zero_x);\
  1580.  prec = Math.log(precision)/(Math.log(10));\
  1581.  var y_basis;if(f_y == 1){ y_basis = ysize }else{ y_basis = zero_y + 1.4*font_size;};\
  1582.  for( var p = zero_x ; p < xsize ; p = p+xstep){\
  1583.   if(skip == 0 ){\
  1584.    disp_cnt = cnt.toFixed(prec);\
  1585.    corr = ctx.measureText(disp_cnt).width;\
  1586.    skip = parseInt(1.2*corr/xstep);\
  1587.    ctx.fillText(disp_cnt,p-0.5*corr,y_basis);\
  1588.   }\
  1589.   else\
  1590.   {\
  1591.    skip--;\
  1592.   };\
  1593.   cnt = cnt + xmajor;\
  1594.  };\
  1595.  cnt = px2x(zero_x);skip = 1;\
  1596.  for( var p = zero_x ; p > 0 ; p = p-xstep){\
  1597.   if(skip == 0 ){\
  1598.    disp_cnt = cnt.toFixed(prec);\
  1599.    corr = ctx.measureText(disp_cnt).width;\
  1600.    skip = parseInt(1.2*corr/xstep);\
  1601.    ctx.fillText(disp_cnt,p-0.5*corr,y_basis);\
  1602.   }\
  1603.   else\
  1604.   {\
  1605.    skip--;\
  1606.   };\
  1607.   cnt = cnt - xmajor;\
  1608.  };\
  1609. };\
  1610. if( y_strings != null ){\
  1611.  var len = y_strings.length;if((len/2+0.5)%%2 == 0){ alert(\"yaxis number unpaired:  text missing ! \");return;};\
  1612.  ctx.beginPath();\
  1613.  for(var p = 0 ; p < len ; p = p+2){\
  1614.   var y_nums = y2px(eval(y_strings[p]));\
  1615.   var y_text = y_strings[p+1];\
  1616.   corr = 2 + tics_length + ctx.measureText(y_text).width;\
  1617.   if( corr > zero_x){corr = parseInt(zero_x+2); }\
  1618.   ctx.fillText(y_text,zero_x - corr,y_nums + 0.5*font_size);\
  1619.   ctx.moveTo(zero_x - tics_length,y_nums);\
  1620.   ctx.lineTo(zero_x + tics_length,y_nums);\
  1621.  };\
  1622.  ctx.closePath();\
  1623. }\
  1624. else\
  1625. {\
  1626.  if(f_x == 1){ corr = 1.5*tics_length; }\
  1627.  cnt = px2y(zero_y);skip = 1;\
  1628.  for( var p = zero_y ; p < ysize ; p = p+ystep){\
  1629.   if(skip == 0 ){\
  1630.    skip = parseInt(1.4*font_size/ystep);\
  1631.    disp_cnt = cnt.toFixed(prec);\
  1632.    if(f_x == -1 ){ corr = parseInt(zero_x - (2 + tics_length + ctx.measureText(disp_cnt).width));};\
  1633.    ctx.fillText(disp_cnt,parseInt(corr),parseInt(p+(0.4*font_size)));\
  1634.   }\
  1635.   else\
  1636.   {\
  1637.    skip--;\
  1638.   };\
  1639.   cnt = cnt - ymajor;\
  1640.  };\
  1641.  corr = 0;cnt = px2y(zero_y);skip = 1;\
  1642.  if(f_x == 1){ corr = 1.5*tics_length; }\
  1643.  for( var p = zero_y ; p > 0 ; p = p-ystep){\
  1644.   if(skip == 0 ){\
  1645.    skip = parseInt(1.4*font_size/ystep);\
  1646.    disp_cnt = cnt.toFixed(prec);\
  1647.    if(f_x == -1 ){corr = parseInt(zero_x - (2 + tics_length + ctx.measureText(disp_cnt).width));};\
  1648.    ctx.fillText(disp_cnt,parseInt(corr),parseInt(p+(0.4*font_size)));\
  1649.   }\
  1650.   else\
  1651.   {\
  1652.    skip--;\
  1653.   };\
  1654.   cnt = cnt + ymajor;\
  1655.  };\
  1656. };\
  1657. ctx.stroke();\
  1658. ctx.restore();");
  1659. }
  1660.  
  1661. if( legend_cnt != -1 ){
  1662. fprintf(js_include_file,"ctx.save();\
  1663. ctx.globalAlpha = 1.0;\
  1664. ctx.font = \"bold \"+font_size+\"px Arial\";\
  1665. var y_offset = 2*font_size;\
  1666. var txt;var txt_size;\
  1667. var x_offset = xsize - 2*font_size;\
  1668. var l_length = legend0.length;\
  1669. if( typeof(legendcolors0) !== 'undefined' ){\
  1670.  for(var p = 0 ; p < l_length ; p++){\
  1671.    barcolor[p] = legendcolors0[p];\
  1672.  };\
  1673. }\
  1674. else\
  1675. {\
  1676.  if( barcolor.length == 0 ){\
  1677.   for(var p = 0 ; p < l_length ; p++){\
  1678.    barcolor[p] = stroke_color;\
  1679.   };\
  1680.  };\
  1681. };\
  1682. for(var p = 0; p < l_length; p++){\
  1683.  ctx.fillStyle = barcolor[p];\
  1684.  txt = legend0[p];\
  1685.  txt_size = ctx.measureText(txt).width;\
  1686.  ctx.fillText(legend0[p],x_offset - txt_size, y_offset);\
  1687.  y_offset = parseInt(y_offset + 1.5*font_size);\
  1688. };\
  1689. ctx.restore();");
  1690. }
  1691.  
  1692. if( barchart_cnt != 0 ){
  1693. fprintf(js_include_file,"ctx.save();\
  1694. var num_barcharts = 0;\
  1695. var bar_name = eval('barchart_0');\
  1696. while( typeof(bar_name) !== 'undefined' ){\
  1697.    try{ bar_name = eval('barchart_'+num_barcharts);num_barcharts++;}catch(e){break;};\
  1698. };\
  1699. var bar_width = parseInt(0.8*x2step/(num_barcharts));\
  1700. for(var i=0 ; i< num_barcharts ; i++){\
  1701.  bar_name = eval('barchart_'+i);\
  1702.  var bar_x = new Array();\
  1703.  var bar_y = new Array();\
  1704.  var lb = bar_name.length;\
  1705.  var idx = 0;\
  1706.  var dx = parseInt(0.5*i*bar_width);\
  1707.  for( var p = 0 ; p < lb ; p = p + 3 ){\
  1708.   bar_x[idx] = x2px(bar_name[p]);\
  1709.   bar_y[idx] = y2px(bar_name[p+1]);\
  1710.   barcolor[idx] = bar_name[p+2];\
  1711.   idx++;\
  1712.  };\
  1713.  ctx.globalAlpha = fill_opacity;\
  1714.  for( var p = 0; p < idx ; p++ ){\
  1715.   ctx.beginPath();\
  1716.   ctx.strokeStyle = barcolor[p];\
  1717.   ctx.fillStyle = barcolor[p];\
  1718.   ctx.rect(bar_x[p]-0.4*x2step+dx,bar_y[p],bar_width,zero_y - bar_y[p]);\
  1719.   ctx.fill();\
  1720.   ctx.stroke();\
  1721.   ctx.closePath();\
  1722.  };\
  1723. };\
  1724. ctx.restore();");
  1725. }
  1726.  
  1727. if( linegraph_cnt != 0 ){
  1728. fprintf(js_include_file,"ctx.save();\
  1729. ctx.globalAlpha = 1.0;\
  1730. var i = 0;\
  1731. var line_name = eval('linegraph_'+i);\
  1732. while ( typeof(line_name) !== 'undefined' ){\
  1733.  ctx.strokeStyle = 'rgba('+line_name[0]+','+stroke_opacity+')';\
  1734.  ctx.lineWidth = parseInt(line_name[1]);\
  1735.  if(line_name[2] == \"1\"){\
  1736.   var d1 = parseInt(line_name[3]);\
  1737.   var d2 = parseInt(line_name[4]);\
  1738.   if(ctx.setLineDash){ ctx.setLineDash([d1,d2]); } else { ctx.mozDash = [d1,d2];};\
  1739.  }\
  1740.  else\
  1741.  {\
  1742.  if(ctx.setLineDash){ctx.setLineDash = null;};if(ctx.mozDash){ctx.mozDash = null;}\
  1743.  };\
  1744.  var data_x = new Array();var data_y = new Array();\
  1745.  var lb = line_name.length;var idx = 0;\
  1746.  for( var p = 5 ; p < lb ; p = p + 2 ){\
  1747.   data_x[idx] = x2px(line_name[p]);\
  1748.   data_y[idx] = y2px(line_name[p+1]);\
  1749.   idx++;\
  1750.  };\
  1751.  for( var p = 0; p < idx ; p++){\
  1752.   ctx.beginPath();\
  1753.   ctx.moveTo(data_x[p],data_y[p]);\
  1754.   ctx.lineTo(data_x[p+1],data_y[p+1]);\
  1755.   ctx.stroke();\
  1756.   ctx.closePath();\
  1757.  };\
  1758.  i++;\
  1759.  try{ line_name = eval('linegraph_'+i); }catch(e){ break; }\
  1760. };\
  1761. ctx.restore();return;");
  1762. }
  1763. fprintf(js_include_file,"};");
  1764.  
  1765. break;
  1766.  
  1767. case DRAW_PIECHART:
  1768. fprintf(js_include_file,"\n/* draw piecharts */\
  1769. if( typeof(all_fill_patterns) != 'object' ){ var all_fill_patterns = []; };\
  1770. function draw_piechart(canvas_type,x_center,y_center,radius, data_color_list,fill_opacity,legend_cnt,font_family,use_filled,use_offset){\
  1771. var obj;\
  1772. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){\
  1773.  obj = document.getElementById(\"wims_canvas%d\"+canvas_type);\
  1774. }\
  1775. else\
  1776. {\
  1777.  obj = create_canvas%d(canvas_type,xsize,ysize);\
  1778. };\
  1779. var center_text = use_offset || 0;\
  1780. var ld = data_color_list.length;\
  1781. var sum = 0;\
  1782. var idx = 0;\
  1783. var font_size = parseInt(font_family.replace(/[^0-9\\.]+/g, \"\"));\
  1784. var colors = new Array();\
  1785. var data = new Array();\
  1786. for(var p = 0;p < ld; p = p + 2){\
  1787.  data[idx] = parseFloat(data_color_list[p]);\
  1788.  sum = sum + data[idx];\
  1789.  colors[idx] = data_color_list[p+1];\
  1790.  idx++;\
  1791. };\
  1792. if( use_filled > 1 ){\
  1793.  var i = 2;\
  1794.  for(var p = 0 ;  p < idx ; p++){\
  1795.   if(i > 5 ){ i = 2; };\
  1796.   var pat = create_Pattern(0,0,i,colors[p]); all_fill_patterns[p] = pat;i++;\
  1797.  };\
  1798. };\
  1799. var ctx = obj.getContext(\"2d\");\
  1800. ctx.save();\
  1801. var angle;\
  1802. var angle_end = 0;\
  1803. var offset = Math.PI / 2;\
  1804. ctx.globalAlpha = fill_opacity;\
  1805. var angles = [];\
  1806. for(var p=0; p < idx; p++){\
  1807.  ctx.beginPath();\
  1808.  ctx.moveTo(x_center,y_center);\
  1809.  angle = Math.PI * (2 * data[p] / sum);\
  1810.  ctx.arc(x_center,y_center, radius, angle_end - offset, angle_end + angle - offset, false);\
  1811.  ctx.lineTo(x_center, y_center);\
  1812.  if( use_filled > 1 ){ ctx.fillStyle = all_fill_patterns[p]; }else{ ctx.fillStyle = colors[p];};\
  1813.  ctx.fill();\
  1814.  ctx.closePath();\
  1815.  angles.push(angle_end + angle - offset);\
  1816.  angle_end  = angle_end + angle;\
  1817. };\
  1818. if(typeof(legend0) !== 'undefined'){\
  1819.  var legenda = eval(\"legend\"+legend_cnt);\
  1820.  ctx.globalAlpha = 1.0;\
  1821.  ctx.font = font_family;\
  1822.  var y_offset = font_size;\
  1823.  var x_offset = 0;\
  1824.  var txt;var txt_size;\
  1825.  for(var p = 0; p < idx; p++){\
  1826.   ctx.fillStyle = colors[p];\
  1827.   txt = legenda[p];\
  1828.   txt_size = ctx.measureText(txt).width + 2;\
  1829.   if(center_text == 4){\
  1830.    ctx.save();\
  1831.    ctx.translate(x_center, y_center);\
  1832.    ctx.rotate(angles[p]);\
  1833.    ctx.fillText(txt,radius-txt_size,0);\
  1834.    ctx.restore();\
  1835.   }\
  1836.   else\
  1837.   {\
  1838.    if( x_center + radius + txt_size > xsize ){ x_offset =  x_center + radius + txt_size - xsize;} else { x_offset = 0; };\
  1839.    ctx.fillText(txt,x_center + radius - x_offset, y_center - radius + y_offset);\
  1840.    y_offset = parseInt(y_offset + 1.5*font_size);\
  1841.   };\
  1842.  };\
  1843. };\
  1844. ctx.restore();\
  1845. };",canvas_root_id,canvas_root_id,canvas_root_id);
  1846. break;
  1847.  
  1848. case DRAW_JSBOXPLOT:
  1849. fprintf(js_include_file,"\n/* draw jsboxplots */\
  1850. if( typeof(all_fill_patterns) != 'object' ){ var all_fill_patterns = []; };\
  1851. function statistics(data){\
  1852. var len = data.length;\
  1853. var min = 10000000;\
  1854. var max = -10000000;\
  1855. var sum = 0;var d;\
  1856. for(var i=0;i<len;i++){\
  1857.  d = data[i];\
  1858.  if(d < min){min = d;}else{if(d > max){max = d;};};\
  1859.  sum+= parseFloat(data[i]);\
  1860. };\
  1861. var mean = parseFloat(sum/len);\
  1862. var variance = 0;\
  1863. for(var i=0;i<len;i++){\
  1864.  d = data[i];\
  1865.  variance += (d - mean)*(d - mean);\
  1866. };\
  1867. variance = parseFloat(variance / len);\
  1868. var std = Math.sqrt(variance);\
  1869. data.sort(function(a,b){return a - b;});\
  1870. var median;var Q1;var Q3;\
  1871. var half = Math.floor(0.5*len);\
  1872. var q1 = Math.floor(0.25*len);\
  1873. var q3 = Math.floor(0.75*len);\
  1874. var half = Math.floor(0.5*len);\
  1875. if(len %%2 == 1){\
  1876.  median = data[half];\
  1877.  Q1 = data[q1];\
  1878.  Q3 = data[q3];\
  1879. }\
  1880. else\
  1881. {\
  1882.  median = (data[half - 1] + data[half] )/2;\
  1883.  Q1 = (data[q1 - 1] + data[q1] )/2;\
  1884.  Q3 = (data[q3 - 1] + data[q3] )/2;\
  1885. };\
  1886. return [min,Q1,median,Q3,max];\
  1887. };");
  1888. break;
  1889.  
  1890. case DRAW_BOXPLOT:
  1891. fprintf(js_include_file,"\n/* draw boxplots */\
  1892. if( typeof(all_fill_patterns) != 'object' ){ var all_fill_patterns = []; };\
  1893. draw_boxplot = function(canvas_type,xy,hw,cxy,data,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1){\
  1894. var obj;\
  1895. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){obj = document.getElementById(\"wims_canvas%d\"+canvas_type);}else{obj = create_canvas%d(canvas_type,xsize,ysize);};\
  1896. var ctx = obj.getContext(\"2d\");\
  1897. ctx.clearRect(0,0,xsize,ysize);\
  1898. ctx.save();\
  1899. ctx.lineWidth = line_width;\
  1900. ctx.strokeStyle =  \"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  1901. var colors = new Array(2);\
  1902. colors[0] = \"rgba(\"+fill_color+\",\"+fill_opacity+\")\";\
  1903. colors[1] = \"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  1904. if( use_filled > 1 ){\
  1905.   var pat = create_Pattern(0,0,3,colors[0]);\
  1906.   all_fill_patterns[0] = pat;\
  1907.   pat = create_Pattern(0,0,4,colors[1]);\
  1908.   all_fill_patterns[1] = pat;\
  1909. };\
  1910. if(use_dashed == 1){if(ctx.setLineDash){ctx.setLineDash([dashtype0,dashtype1]);}else{if(ctx.mozDash){ ctx.mozDash = [dashtype0,dashtype1];};};};\
  1911. var hh = 0.25*hw;\
  1912. switch(boxplot_source){\
  1913.  case 1: if( typeof(jsboxplot_data) === 'undefined'){return;};data = statistics(jsboxplot_data);break;\
  1914.  case 2: if( typeof(student_boxplot_data) === 'undefined'){return;};data = statistics(student_boxplot_data);break;\
  1915.  case 3: if( typeof(student_boxplot) === 'undefined'){return;};data = student_boxplot;break;\
  1916.  default: break;\
  1917. };\
  1918. var min,Q1,median,Q3,max;\
  1919. if(xy == 1 ){\
  1920.  min=x2px(data[0]);Q1=x2px(data[1]);median=x2px(data[2]);Q3=x2px(data[3]);max=x2px(data[4]);\
  1921.  hh = Math.abs(y2px(hh) - y2px(ystart));\
  1922.  hw = Math.abs(y2px(hw) - y2px(ystart));\
  1923.  cxy = y2px(cxy);\
  1924.  ctx.beginPath();\
  1925.  ctx.moveTo(min,cxy);\
  1926.  ctx.lineTo(Q1,cxy);\
  1927.  ctx.moveTo(Q3,cxy);\
  1928.  ctx.lineTo(max,cxy);\
  1929.  ctx.moveTo(min,cxy+hh);\
  1930.  ctx.lineTo(min,cxy-hh);\
  1931.  ctx.moveTo(max,cxy+hh);\
  1932.  ctx.lineTo(max,cxy-hh);\
  1933.  ctx.closePath();\
  1934.  ctx.stroke();\
  1935.  ctx.beginPath();\
  1936.  ctx.rect(Q1,cxy-2*hh,median-Q1,hw);\
  1937.  ctx.closePath();\
  1938.  if( use_filled != 0 ){\
  1939.   if( use_filled == 1 ) {ctx.fillStyle = colors[0]; }else{ ctx.fillStyle = all_fill_patterns[0] };\
  1940.   ctx.fill();\
  1941.  };\
  1942.  ctx.stroke();\
  1943.  ctx.beginPath();\
  1944.  ctx.rect(median,cxy-2*hh,Q3-median,hw);\
  1945.  ctx.closePath();\
  1946.  if( use_filled != 0 ){\
  1947.   if( use_filled == 1 ) {ctx.fillStyle = colors[1]; }else{ ctx.fillStyle = all_fill_patterns[1] };\
  1948.   ctx.fill();\
  1949.  };\
  1950.  ctx.stroke();\
  1951. }else{\
  1952.  min=y2px(data[0]);Q1=y2px(data[1]);median=y2px(data[2]);Q3=y2px(data[3]);max=y2px(data[4]);\
  1953.  hh = Math.abs(x2px(hh) - x2px(xstart));\
  1954.  hw = Math.abs(x2px(hw) - x2px(xstart));\
  1955.  cxy = x2px(cxy);\
  1956.  ctx.beginPath();\
  1957.  ctx.moveTo(cxy,min);\
  1958.  ctx.lineTo(cxy,Q1);\
  1959.  ctx.moveTo(cxy,Q3);\
  1960.  ctx.lineTo(cxy,max);\
  1961.  ctx.moveTo(cxy + hh,min);\
  1962.  ctx.lineTo(cxy - hh,min);\
  1963.  ctx.moveTo(cxy + hh,max);\
  1964.  ctx.lineTo(cxy - hh,max);\
  1965.  ctx.closePath;\
  1966.  ctx.stroke();\
  1967.  ctx.beginPath();\
  1968.  ctx.rect(cxy - 2*hh,Q1,hw,median - Q1);\
  1969.  ctx.closePath();\
  1970.  if( use_filled != 0 ){\
  1971.   if( use_filled == 1 ) {ctx.fillStyle = colors[0]; }else{ ctx.fillStyle = all_fill_patterns[0] };\
  1972.   ctx.fill();\
  1973.  };\
  1974.  ctx.stroke();\
  1975.  ctx.beginPath();\
  1976.  ctx.rect(cxy - 2*hh,median,hw,Q3 - median);\
  1977.  ctx.closePath();\
  1978.  if( use_filled != 0 ){\
  1979.   if( use_filled == 1 ) {ctx.fillStyle = colors[1]; }else{ ctx.fillStyle = all_fill_patterns[1] };\
  1980.   ctx.fill();\
  1981.  };\
  1982.  ctx.stroke();\
  1983. };\
  1984. ctx.restore();};",canvas_root_id,canvas_root_id,canvas_root_id);
  1985. break;
  1986.  
  1987. case DRAW_CENTERSTRING:
  1988. fprintf(js_include_file,"\n/* draw centerstring */\
  1989. var draw_centerstring = function(canvas_type,y,font_family,stroke_color,stroke_opacity,text){\
  1990. var obj;\
  1991. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){\
  1992.  obj = document.getElementById(\"wims_canvas%d\"+canvas_type);\
  1993. }\
  1994. else\
  1995. {\
  1996.  obj = create_canvas%d(canvas_type,xsize,ysize);\
  1997. };\
  1998. var ctx = obj.getContext(\"2d\");\
  1999. ctx.save();\
  2000. ctx.clearRect(0,0,xsize,ysize);\
  2001. ctx.font = font_family;\
  2002. ctx.fillStyle = \"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  2003. var stringwidth = ctx.measureText(text).width;\
  2004. var x = parseInt((xsize - stringwidth)/2);if( x < 0 ){x = 0;};\
  2005. ctx.fillText(text,x,y2px(y));\
  2006. ctx.restore();\
  2007. return;\
  2008. };",canvas_root_id,canvas_root_id,canvas_root_id);
  2009. break;
  2010.  
  2011. case DRAW_TEXTS:
  2012. fprintf(js_include_file,"\n/* draw text */\
  2013. var draw_text = function(canvas_type,x,y,font_size,font_family,stroke_color,stroke_opacity,angle2,text,use_rotate,angle,use_offset){\
  2014. var obj;\
  2015. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){\
  2016.  obj = document.getElementById(\"wims_canvas%d\"+canvas_type);\
  2017. }\
  2018. else\
  2019. {\
  2020.  obj = create_canvas%d(canvas_type,xsize,ysize);\
  2021. };\
  2022. var ctx = obj.getContext(\"2d\");\
  2023. if( font_family != 'null' ){\
  2024.  ctx.font = font_family;\
  2025. }\
  2026. else\
  2027. {\
  2028.  ctx.font = font_size+'px Arial';\
  2029. };\
  2030. if( use_offset == 3 ){if(angle2 < 0 ){ y = y + 0.8*font_size; x = x + (Math.cos(angle2))*font_size; }else{y = y - 0.8*font_size; x = x + (Math.sin(angle2))*font_size;};};\
  2031. if(angle2 == 0 && angle != 0){\
  2032.  ctx.save();\
  2033.  if(use_rotate == 1 ){\
  2034.  ctx.rotate(angle*Math.PI/180);};\
  2035.  ctx.restore();\
  2036. };\
  2037. ctx.fillStyle = \"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  2038. if(angle2 != 0){\
  2039.  ctx.save();\
  2040.  ctx.translate(x,y);\
  2041.  ctx.rotate((360-angle2)*(Math.PI / 180));\
  2042.  ctx.fillText(text,0,0);\
  2043.  ctx.restore();\
  2044. }\
  2045. else\
  2046. {\
  2047.  ctx.fillText(text,x,y);\
  2048. };\
  2049. return;\
  2050. };",canvas_root_id,canvas_root_id,canvas_root_id);
  2051. break;
  2052.  
  2053. case DRAW_INPUTS:
  2054. /* function center_input may be used for other centering...if not? integrate it in draw_static_inputs...*/
  2055. fprintf(js_include_file,"\n/* draw static input fields */\
  2056. if(typeof(input_cnt) !== 'undefined' ){var input_cnt = 0;};\
  2057. var draw_static_inputs = function(root_id,num,x,y,size,readonly,css_class,value,use_offset){\
  2058. var input = document.createElement(\"input\");\
  2059. input.setAttribute(\"id\",\"canvas_input\"+num);\
  2060. input.setAttribute(\"style\",\"text-align:center;position:absolute;left:\"+x+\"px;top:\"+y+\"px;\");\
  2061. if(css_class != \"none\"){input.setAttribute(\"class\",css_class);};\
  2062. input.setAttribute(\"size\",size);\
  2063. input.setAttribute(\"value\",value);\
  2064. input.addEventListener(\"touchstart\", function(e){this.focus();},false);\
  2065. if( readonly == 0 || wims_status == \"done\" ){ input.setAttribute(\"readonly\",\"readonly\");if( wims_status == \"done\" ){input.setAttribute(\"value\",\"\");};};\
  2066. canvas_div.appendChild(input);\
  2067. if(use_offset != 0 ){ center_input('canvas_input'+num,x,y,css_class);};\
  2068. input_cnt++;\
  2069. };\
  2070. function center_input(id,x,y,css_class){\
  2071. var inp = document.getElementById(id);\
  2072. var pos = inp.getBoundingClientRect();\
  2073. var center_x = parseInt(x - 0.5*(pos.width));\
  2074. var center_y = parseInt(y - 0.5*(pos.height));\
  2075. try{if(css_class != \"none\"){inp.setAttribute(\"class\",css_class);};inp.setAttribute(\"style\",\"text-align:center;position:absolute;left:\"+center_x+\"px;top:\"+center_y+\"px;\");}\
  2076. catch(e){console.log('error :'+e);return;};\
  2077. };");
  2078. break;
  2079.  
  2080. case DRAW_TEXTAREAS:
  2081. fprintf(js_include_file,"\n/* draw text area inputfields */\
  2082. var draw_textareas = function(root_id,num,x,y,cols,rows,readonly,style,value){\
  2083. var canvas_div = document.getElementById(\"canvas_div\"+root_id);\
  2084. var textarea = document.createElement(\"textarea\");\
  2085. textarea.setAttribute(\"id\",\"canvas_input\"+num);\
  2086. textarea.setAttribute(\"style\",\"position:absolute;left:\"+x+\"px;top:\"+y+\"px;\"+style);\
  2087. textarea.setAttribute(\"cols\",cols);\
  2088. textarea.setAttribute(\"rows\",rows);\
  2089. textarea.value = value;\
  2090. if( readonly == 0 || wims_status == \"done\" ){ textarea.setAttribute(\"readonly\",\"readonly\");if( wims_status == \"done\" ){textarea.value=\"\";};};\
  2091. canvas_div.appendChild(textarea);};");
  2092. break;
  2093.  
  2094. case DRAW_PIXELS:
  2095. fprintf(js_include_file,"\n/* draw pixel */\
  2096. var draw_setpixel = function(x,y,color,opacity,pixelsize){\
  2097. var idx = 2000+Math.ceil(1000*(Math.random()));\
  2098. var canvas = create_canvas%d(idx,xsize,ysize);\
  2099. var d = 0.5*pixelsize;\
  2100. var ctx = canvas.getContext(\"2d\");\
  2101. if(pixelsize%%2 == 1){ ctx.translate(0.5,0.5);};\
  2102. ctx.fillStyle = \"rgba(\"+color+\",\"+opacity+\")\";\
  2103. ctx.clearRect(0,0,xsize,ysize);\
  2104. for(var p=0; p<x.length;p++){\
  2105.  ctx.fillRect( x2px(x[p]) - d, y2px(y[p]) - d , pixelsize, pixelsize );\
  2106. };\
  2107. ctx.fill();ctx.stroke();\
  2108. };",canvas_root_id);
  2109. break;
  2110.  
  2111. case DRAW_CLOCK:
  2112. fprintf(js_include_file,"\n/* command clock */\
  2113. var clock_canvas = create_canvas%d(%d,xsize,ysize);\
  2114. var clock_ctx = clock_canvas.getContext(\"2d\");\
  2115. var clock = function(xc,yc,radius,H,M,S,type,interaction,h_color,m_color,s_color,bg_color,fg_color){\
  2116. clock_ctx.clearRect(xc - radius,yc - radius,2*radius,2*radius);\
  2117. clock_ctx.save();\
  2118. clock_ctx.globalAlpha = clock_bg_opacity;\
  2119. this.type = type || 0;\
  2120. this.interaction = interaction || 0;\
  2121. this.H = H;\
  2122. this.M = M;\
  2123. this.S = S;\
  2124. this.xc = xc || xsize/2;\
  2125. this.yc = yc || ysize/2;\
  2126. this.radius = radius || xsize/4;\
  2127. var font_size = parseInt(0.2*this.radius);\
  2128. this.H_color = h_color || \"black\";\
  2129. this.M_color = m_color || \"black\";\
  2130. this.S_color = s_color || \"black\";\
  2131. this.fg_color = fg_color || \"black\";\
  2132. this.bg_color = bg_color || \"white\";\
  2133. clock_ctx.translate(this.xc,this.yc);\
  2134. clock_ctx.beginPath();\
  2135. clock_ctx.arc(0,0,this.radius,0,2*Math.PI,false);\
  2136. clock_ctx.fillStyle = this.bg_color;\
  2137. clock_ctx.fill();\
  2138. clock_ctx.closePath();\
  2139. clock_ctx.beginPath();\
  2140. clock_ctx.font = font_size+\"px Arial\";\
  2141. clock_ctx.fillStyle = this.fg_color;\
  2142. clock_ctx.textAlign = \"center\";\
  2143. clock_ctx.textBaseline = 'middle';\
  2144. var angle;var x1,y1,x2,y2;\
  2145. var angle_cos;var angle_sin;\
  2146. clock_ctx.globalAlpha = clock_fg_opacity;\
  2147. switch(type){\
  2148. case 0:clock_ctx.beginPath();\
  2149. for(var p = 1; p <= 12 ; p++){\
  2150.  angle_cos = this.radius*(Math.cos(p * (Math.PI * 2) / 12));\
  2151.  angle_sin = this.radius*(Math.sin(p * (Math.PI * 2) / 12));\
  2152.  x1 = 0.8*angle_cos;y1 = 0.8*angle_sin;x2 = angle_cos;y2 = angle_sin;\
  2153.  clock_ctx.moveTo(x1,y1);\
  2154.  clock_ctx.lineTo(x2,y2);\
  2155. };\
  2156. for(var p = 1; p <= 60 ; p++){\
  2157.  angle_cos = this.radius*(Math.cos(p * (Math.PI * 2) / 60));\
  2158.  angle_sin = this.radius*(Math.sin(p * (Math.PI * 2) / 60));\
  2159.  x1 = 0.9*angle_cos;y1 = 0.9*angle_sin;x2 = angle_cos;y2 = angle_sin;\
  2160.  clock_ctx.moveTo(x1,y1);\
  2161.  clock_ctx.lineTo(x2,y2);\
  2162. };\
  2163. clock_ctx.closePath();\
  2164. clock_ctx.stroke();\
  2165. break;\
  2166. case 1:\
  2167. for(var p= 1; p <= 12 ; p++){ angle = (p - 3) * (Math.PI * 2) / 12;x1 = 0.9*this.radius*Math.cos(angle);y1 = 0.9*this.radius*Math.sin(angle);clock_ctx.fillText(p, x1, y1);};break;\
  2168. case 2:\
  2169. for(var p= 1; p <= 12 ; p++){ angle = (p - 3) * (Math.PI * 2) / 12;x1 = 0.8*this.radius*Math.cos(angle);y1 = 0.8*this.radius*Math.sin(angle);clock_ctx.fillText(p, x1, y1);};\
  2170. clock_ctx.beginPath();\
  2171. for(var p = 1; p <= 12 ; p++){\
  2172.  angle_cos = this.radius*(Math.cos(p * (Math.PI * 2) / 12));\
  2173.  angle_sin = this.radius*(Math.sin(p * (Math.PI * 2) / 12));\
  2174.  x1 = 0.9*angle_cos;y1 = 0.9*angle_sin;x2 = angle_cos;y2 = angle_sin;\
  2175.  clock_ctx.moveTo(x1,y1);\
  2176.  clock_ctx.lineTo(x2,y2);\
  2177. };\
  2178. for(var p = 1; p <= 60 ; p++){\
  2179.  angle_cos = this.radius*(Math.cos(p * (Math.PI * 2) / 60));\
  2180.  angle_sin = this.radius*(Math.sin(p * (Math.PI * 2) / 60));\
  2181.  x1 = 0.95*angle_cos;y1 = 0.95*angle_sin;x2 = angle_cos;y2 = angle_sin;\
  2182.  clock_ctx.moveTo(x1,y1);\
  2183.  clock_ctx.lineTo(x2,y2);\
  2184. };\
  2185. clock_ctx.closePath();\
  2186. clock_ctx.stroke();\
  2187. break;\
  2188. };\
  2189. angle = (this.H - 3 + this.M/60 ) * 2 * Math.PI / 12;\
  2190. clock_ctx.rotate(angle);\
  2191. clock_ctx.beginPath();\
  2192. clock_ctx.moveTo(-3, -2);\
  2193. clock_ctx.lineTo(-3, 2);\
  2194. clock_ctx.lineTo(this.radius * 0.6, 1);\
  2195. clock_ctx.lineTo(this.radius  * 0.6, -1);\
  2196. clock_ctx.fillStyle = this.H_color;\
  2197. clock_ctx.fill();\
  2198. clock_ctx.rotate(-angle);\
  2199. angle = (this.M - 15 + this.S/60) * 2 * Math.PI / 60;\
  2200. clock_ctx.rotate(angle);\
  2201. clock_ctx.beginPath();\
  2202. clock_ctx.moveTo(-3, -2);\
  2203. clock_ctx.lineTo(-3, 2);\
  2204. clock_ctx.lineTo(this.radius  * 0.8, 1);\
  2205. clock_ctx.lineTo(this.radius  * 0.8, -1);\
  2206. clock_ctx.fillStyle = this.M_color;\
  2207. clock_ctx.fill();\
  2208. clock_ctx.rotate(-angle);\
  2209. angle = (this.S - 15) * 2 * Math.PI / 60;\
  2210. clock_ctx.rotate(angle);\
  2211. clock_ctx.beginPath();\
  2212. clock_ctx.moveTo(0,0);\
  2213. clock_ctx.lineTo(this.radius  * 0.9, 1);\
  2214. clock_ctx.lineTo(this.radius  * 0.9, -1);\
  2215. clock_ctx.strokeStyle = this.S_color;\
  2216. clock_ctx.stroke();\
  2217. clock_ctx.restore();\
  2218. };",canvas_root_id,CLOCK_CANVAS);
  2219. break;
  2220.  
  2221. case DRAW_LATTICE:
  2222. fprintf(js_include_file,"\n/* draw lattice */\
  2223. var draw_lattice = function(canvas_type,line_width,x0,y0,dx1,dy1,dx2,dy2,n1,n2,fill_color,fill_opacity,stroke_color,stroke_opacity,use_rotate,angle,use_filled){\
  2224. var obj;\
  2225. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){\
  2226.  obj = document.getElementById(\"wims_canvas%d\"+canvas_type);\
  2227. }\
  2228. else\
  2229. {\
  2230.  obj = create_canvas%d(canvas_type,xsize,ysize);\
  2231. };\
  2232. var ctx = obj.getContext(\"2d\");\
  2233. ctx.save();\
  2234. if(use_rotate == 1 ){ctx.rotate(angle*Math.PI/180);}\
  2235. var color = \"rgba(\"+fill_color+\",\"+fill_opacity+\")\";\
  2236. if(use_filled > 1 ){ if(! all_fill_patterns[use_filled] ){ var pat = create_Pattern(0,0,use_filled,color); all_fill_patterns[use_filled] = pat;};ctx.fillStyle = all_fill_patterns[use_filled]; } else { ctx.fillStyle = color;};\
  2237. ctx.strokeStyle=\"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  2238. var radius = line_width;\
  2239. var x = 0;\
  2240. var y = 0;\
  2241. var x_step_px = xsize/(xmax-xmin);\
  2242. var y_step_px = ysize/(ymax-ymin);\
  2243. var xv1 = dx1*x_step_px;\
  2244. var yv1 = dy1*y_step_px;\
  2245. var xv2 = dx2*x_step_px;\
  2246. var yv2 = dy2*y_step_px;\
  2247. for(var p = 0; p < n1 ;p++){\
  2248.  x = p*xv1 + x0;\
  2249.  y = p*yv1 + y0;\
  2250.  for(var c = 0; c < n2 ; c++){\
  2251.   ctx.beginPath();\
  2252.   ctx.arc(x+c*xv2,y+c*yv2,radius,0,2*Math.PI,false);\
  2253.   ctx.fill();\
  2254.   ctx.stroke();\
  2255.   ctx.closePath();\
  2256.  };\
  2257. };\
  2258. ctx.restore();\
  2259. return;\
  2260. };",canvas_root_id,canvas_root_id,canvas_root_id);
  2261. break;
  2262.  
  2263. case DRAW_XYLOGSCALE:
  2264. fprintf(js_include_file,"\n/* draw xylogscale */\
  2265. var draw_grid%d = function(canvas_type,line_width,major_color,minor_color,major_opacity,minor_opacity,font_size,font_family,font_color,use_axis_numbering,precision){\
  2266. var obj;\
  2267. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){\
  2268.  obj = document.getElementById(\"wims_canvas%d\"+canvas_type);\
  2269. }\
  2270. else\
  2271. {\
  2272.  obj = create_canvas%d(canvas_type,xsize,ysize);\
  2273. };\
  2274. var ctx = obj.getContext(\"2d\");\
  2275. ctx.clearRect(0,0,xsize,ysize);\
  2276. ctx.save();\
  2277. var xmarge;var ymarge;var x_e;var y_e;var num;var corr;var xtxt;var ytxt;\
  2278. var x_min = Math.log(xmin)/Math.log(xlogbase);\
  2279. var x_max = Math.log(xmax)/Math.log(xlogbase);\
  2280. var y_min = Math.log(ymin)/Math.log(ylogbase);\
  2281. var y_max = Math.log(ymax)/Math.log(ylogbase);\
  2282. if(use_axis_numbering != -1){\
  2283.  ctx.font = font_family;\
  2284.  xmarge = ctx.measureText(ylogbase+'^'+y_max.toFixed(0)+' ').width;\
  2285.  ymarge = parseInt(1.5*font_size);\
  2286.  ctx.save();\
  2287.  ctx.fillStyle=\"rgba(255,215,0,0.2)\";\
  2288.  ctx.rect(0,0,xmarge,ysize);\
  2289.  ctx.rect(0,ysize-ymarge,xsize,ysize);\
  2290.  ctx.fill();\
  2291.  ctx.restore();\
  2292. }else{xmarge = 0;ymarge = 0;};\
  2293. if( typeof(xaxislabel) !== 'undefined' ){\
  2294.  ctx.save();\
  2295.  ctx.font = \"italic \"+font_size+\"px Arial\";\
  2296.  ctx.fillStyle = \"rgba(\"+font_color+\",\"+major_opacity+\")\";\
  2297.  corr =  ctx.measureText(xaxislabel).width;\
  2298.  ctx.fillText(xaxislabel,xsize - 1.5*corr,ysize - 2*font_size);\
  2299.  ctx.restore();\
  2300. };\
  2301. if( typeof(yaxislabel) !== 'undefined' ){\
  2302.  ctx.save();\
  2303.  ctx.font = \"italic \"+font_size+\"px Arial\";\
  2304.  ctx.fillStyle = \"rgba(\"+font_color+\",\"+major_opacity+\")\";\
  2305.  corr = ctx.measureText(yaxislabel).width;\
  2306.  ctx.translate(xmarge+font_size,corr+font_size);\
  2307.  ctx.rotate(-0.5*Math.PI);\
  2308.  ctx.fillText(yaxislabel,0,0);\
  2309.  ctx.restore();\
  2310. };\
  2311. ctx.fillStyle = \"rgba(\"+font_color+\",\"+major_opacity+\")\";\
  2312. ctx.lineWidth = line_width;\
  2313. for(var p = x_min; p <= x_max ; p++){\
  2314.  num = Math.pow(xlogbase,p);\
  2315.  for(var i = 1 ; i < xlogbase ; i++){\
  2316.   x_e = x2px(i*num);\
  2317.   if( i == 1 ){\
  2318.    ctx.lineWidth = line_width;\
  2319.    ctx.strokeStyle=\"rgba(\"+major_color+\",\"+major_opacity+\")\";\
  2320.    if( use_axis_numbering != -1 && p > x_min){\
  2321.      xtxt = xlogbase+'^'+p.toFixed(0);\
  2322.      corr = 0.5*(ctx.measureText(xtxt).width);\
  2323.      ctx.fillText(xtxt,x_e - corr,ysize - 4);\
  2324.    };\
  2325.   }else{\
  2326.    ctx.lineWidth = 0.2*line_width;\
  2327.    ctx.strokeStyle=\"rgba(\"+minor_color+\",\"+minor_opacity+\")\";\
  2328.   };\
  2329.   if( x_e >= xmarge ){\
  2330.    ctx.beginPath();\
  2331.    ctx.moveTo(x_e,0);\
  2332.    ctx.lineTo(x_e,ysize - ymarge);\
  2333.    ctx.stroke();\
  2334.    ctx.closePath();\
  2335.   };\
  2336.  };\
  2337. };\
  2338. for(var p = y_min; p <= y_max ; p++){\
  2339.  num = Math.pow(ylogbase,p);\
  2340.  for(var i = 1 ; i < ylogbase ; i++){\
  2341.   y_e = y2px(i*num);\
  2342.   if( i == 1 ){\
  2343.    ctx.lineWidth = line_width;\
  2344.    ctx.strokeStyle=\"rgba(\"+major_color+\",\"+major_opacity+\")\";\
  2345.    if( use_axis_numbering != -1 && p > y_min){\
  2346.     ctx.fillText(ylogbase+'^'+p.toFixed(0),0,y_e);\
  2347.    };\
  2348.   }else{\
  2349.    ctx.lineWidth = 0.2*line_width;\
  2350.    ctx.strokeStyle=\"rgba(\"+minor_color+\",\"+minor_opacity+\")\";\
  2351.   };\
  2352.   ctx.beginPath();\
  2353.   ctx.moveTo(xmarge,y_e);\
  2354.   ctx.lineTo(xsize,y_e);\
  2355.   ctx.stroke();\
  2356.   ctx.closePath();\
  2357.  };\
  2358. };\
  2359. ctx.restore();\
  2360. };",canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id);
  2361. break;
  2362.  
  2363. case DRAW_XLOGSCALE:
  2364. fprintf(js_include_file,"\n/* draw xlogscale */\
  2365. var draw_grid%d = function(canvas_type,line_width,major_color,minor_color,major_opacity,minor_opacity,font_size,font_family,font_color,use_axis_numbering,ymajor,yminor,precision){\
  2366. var obj;\
  2367. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){\
  2368.  obj = document.getElementById(\"wims_canvas%d\"+canvas_type);\
  2369. }\
  2370. else\
  2371. {\
  2372.  obj = create_canvas%d(canvas_type,xsize,ysize);\
  2373. };\
  2374. var ctx = obj.getContext(\"2d\");\
  2375. ctx.clearRect(0,0,xsize,ysize);\
  2376. ctx.save();\
  2377. ctx.lineWidth = line_width;\
  2378. var prec = Math.log(precision)/Math.log(10);\
  2379. var x_min = Math.log(xmin)/Math.log(xlogbase);\
  2380. var x_max = Math.log(xmax)/Math.log(xlogbase);\
  2381. var y_min = 0;var y_max = ysize;var x_e;var corr;\
  2382. var xtxt;var ytxt;var num;var xmarge;var ymarge;\
  2383. if(use_axis_numbering != -1){\
  2384.  ctx.font = font_family;\
  2385.  xmarge = ctx.measureText(ymax.toFixed(prec)+' ').width;\
  2386.  ymarge = parseInt(1.5*font_size);\
  2387.  ctx.save();\
  2388.  ctx.fillStyle=\"rgba(255,215,0,0.2)\";\
  2389.  ctx.rect(0,0,xmarge,ysize);\
  2390.  ctx.rect(0,ysize-ymarge,xsize,ysize);\
  2391.  ctx.fill();\
  2392.  ctx.restore();\
  2393. }else{xmarge = 0;ymarge = 0;};\
  2394. if( typeof(xaxislabel) !== 'undefined' ){\
  2395.  ctx.save();\
  2396.  ctx.font = \"italic \"+font_size+\"px Arial\";\
  2397.  ctx.fillStyle = \"rgba(\"+font_color+\",\"+major_opacity+\")\";\
  2398.  corr =  ctx.measureText(xaxislabel).width;\
  2399.  ctx.fillText(xaxislabel,xsize - 1.5*corr,ysize - 2*font_size);\
  2400.  ctx.restore();\
  2401. };\
  2402. if( typeof(yaxislabel) !== 'undefined' ){\
  2403.  ctx.save();\
  2404.  ctx.font = \"italic \"+font_size+\"px Arial\";\
  2405.  ctx.fillStyle = \"rgba(\"+font_color+\",\"+major_opacity+\")\";\
  2406.  corr = ctx.measureText(yaxislabel).width;\
  2407.  ctx.translate(xmarge+font_size,corr+font_size);\
  2408.  ctx.rotate(-0.5*Math.PI);\
  2409.  ctx.fillText(yaxislabel,0,0);\
  2410.  ctx.restore();\
  2411. };\
  2412. ctx.fillStyle = \"rgba(\"+font_color+\",\"+major_opacity+\")\";\
  2413. ctx.lineWidth = line_width;\
  2414. for(var p = x_min; p <= x_max ; p++){\
  2415.  num = Math.pow(xlogbase,p);\
  2416.  for(var i = 1 ; i < xlogbase ; i++){\
  2417.   x_e = x2px(i*num);\
  2418.   if( i == 1 ){\
  2419.     ctx.lineWidth = line_width;\
  2420.     ctx.strokeStyle=\"rgba(\"+major_color+\",\"+major_opacity+\")\";\
  2421.    if( use_axis_numbering != -1 && p > x_min ){\
  2422.      xtxt = xlogbase+'^'+p.toFixed(0);\
  2423.      corr = 0.5*(ctx.measureText(xtxt).width);\
  2424.      ctx.fillText(xtxt,x_e - corr,ysize - 4);\
  2425.    };\
  2426.   }else{\
  2427.    ctx.lineWidth = 0.2*line_width;\
  2428.    ctx.strokeStyle=\"rgba(\"+minor_color+\",\"+minor_opacity+\")\";\
  2429.   };\
  2430.   if( x_e >= xmarge ){\
  2431.    ctx.beginPath();\
  2432.    ctx.moveTo(x_e,0);\
  2433.    ctx.lineTo(x_e,ysize - ymarge);\
  2434.    ctx.stroke();\
  2435.    ctx.closePath();\
  2436.   };\
  2437.  };\
  2438. };\
  2439. var stepy = Math.abs(y2px(ymajor) - y2px(0));\
  2440. var minor_step = stepy / yminor;\
  2441. for(var y = 0 ; y < ysize - stepy ; y = y + stepy){\
  2442.  ctx.strokeStyle=\"rgba(\"+major_color+\",\"+major_opacity+\")\";\
  2443.  ctx.lineWidth = line_width;\
  2444.  ctx.beginPath();\
  2445.  ctx.moveTo(xmarge,y);\
  2446.  ctx.lineTo(xsize,y);\
  2447.  ctx.stroke();\
  2448.  ctx.closePath();\
  2449.  if( use_axis_numbering != -1){\
  2450.   ytxt = (px2y(y)).toFixed(prec);\
  2451.   ctx.fillText( ytxt,0 ,y + 0.5*font_size );\
  2452.  };\
  2453.  for(var dy = 1 ; dy < yminor ; dy++){\
  2454.   ctx.strokeStyle=\"rgba(\"+minor_color+\",\"+minor_opacity+\")\";\
  2455.   ctx.lineWidth = 0.2*line_width;\
  2456.   ctx.beginPath();\
  2457.   ctx.moveTo(xmarge,y+dy*minor_step);\
  2458.   ctx.lineTo(xsize,y+dy*minor_step);\
  2459.   ctx.stroke();\
  2460.   ctx.closePath();\
  2461.  };\
  2462. };\
  2463. ctx.restore();\
  2464. };",canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id);
  2465. break;
  2466.  
  2467. case DRAW_YLOGSCALE:
  2468. fprintf(js_include_file,"\n/* draw ylogscale */\
  2469. var draw_grid%d = function(canvas_type,line_width,major_color,minor_color,major_opacity,minor_opacity,font_size,font_family,font_color,use_axis_numbering,xmajor,xminor,precision){\
  2470. var obj;\
  2471. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){\
  2472.  obj = document.getElementById(\"wims_canvas%d\"+canvas_type);\
  2473. }\
  2474. else\
  2475. {\
  2476.  obj = create_canvas%d(canvas_type,xsize,ysize);\
  2477. };\
  2478. var ctx = obj.getContext(\"2d\");\
  2479. ctx.clearRect(0,0,xsize,ysize);\
  2480. ctx.save();\
  2481. ctx.lineWidth = line_width;\
  2482. var y_min = Math.log(ymin)/Math.log(ylogbase);\
  2483. var y_max = Math.log(ymax)/Math.log(ylogbase);\
  2484. var x_min = 0;var x_max = xsize;var y_s;var y_e;var num;var xmarge;var ymarge;\
  2485. if(use_axis_numbering != -1){\
  2486.  ctx.font = font_family;\
  2487.  xmarge = ctx.measureText(ylogbase+\"^\"+y_max.toFixed(0)+' ').width;\
  2488.  ymarge = 2*font_size;\
  2489.  ctx.save();\
  2490.  ctx.fillStyle=\"rgba(255,215,0,0.2)\";\
  2491.  ctx.rect(0,0,xmarge,ysize);\
  2492.  ctx.rect(0,ysize-ymarge,xsize,ysize);\
  2493.  ctx.fill();\
  2494.  ctx.restore();\
  2495. }else{xmarge = 0;ymarge = 0;};\
  2496. if( typeof(xaxislabel) !== 'undefined' ){\
  2497.  ctx.save();\
  2498.  ctx.font = \"italic \"+font_size+\"px Arial\";\
  2499.  ctx.fillStyle = \"rgba(\"+font_color+\",\"+major_opacity+\")\";\
  2500.  corr =  ctx.measureText(xaxislabel).width;\
  2501.  ctx.fillText(xaxislabel,xsize - 1.5*corr,ysize - 2*font_size);\
  2502.  ctx.restore();\
  2503. };\
  2504. if( typeof(yaxislabel) !== 'undefined' ){\
  2505.  ctx.save();\
  2506.  ctx.font = \"italic \"+font_size+\"px Arial\";\
  2507.  ctx.fillStyle = \"rgba(\"+font_color+\",\"+major_opacity+\")\";\
  2508.  corr = ctx.measureText(yaxislabel).width;\
  2509.  ctx.translate(xmarge+font_size,corr+font_size);\
  2510.  ctx.rotate(-0.5*Math.PI);\
  2511.  ctx.fillText(yaxislabel,0,0);\
  2512.  ctx.restore();\
  2513. };\
  2514. ctx.fillStyle = \"rgba(\"+font_color+\",\"+major_opacity+\")\";\
  2515. ctx.lineWidth = line_width;\
  2516. for(var p = y_min; p <= y_max ; p++){\
  2517.  num = Math.pow(ylogbase,p);\
  2518.  for(var i = 1 ; i < ylogbase ; i++){\
  2519.   y_e = y2px(i*num);\
  2520.   if( i == 1 ){\
  2521.    ctx.lineWidth = line_width;\
  2522.    ctx.strokeStyle=\"rgba(\"+major_color+\",\"+major_opacity+\")\";\
  2523.    if( use_axis_numbering != -1 && p > y_min){\
  2524.     ctx.fillText(ylogbase+'^'+p.toFixed(0),0,y_e);\
  2525.    };\
  2526.   }else{\
  2527.    ctx.lineWidth = 0.2*line_width;\
  2528.    ctx.strokeStyle=\"rgba(\"+minor_color+\",\"+minor_opacity+\")\";\
  2529.   };\
  2530.   ctx.beginPath();\
  2531.   ctx.moveTo(xmarge,y_e);\
  2532.   ctx.lineTo(xsize,y_e);\
  2533.   ctx.stroke();\
  2534.   ctx.closePath();\
  2535.  };\
  2536. };\
  2537. var stepx = Math.abs(x2px(xmajor) - x2px(0));\
  2538. var minor_step = stepx / xminor;\
  2539. var prec = Math.log(precision)/Math.log(10);\
  2540. var xtxt;var corr;var flip = 0;\
  2541. for(var x = stepx ; x < xsize ; x = x + stepx){\
  2542.  ctx.strokeStyle=\"rgba(\"+major_color+\",\"+major_opacity+\")\";\
  2543.  ctx.lineWidth = line_width;\
  2544.  ctx.beginPath();\
  2545.  ctx.moveTo(x,ysize-ymarge);\
  2546.  ctx.lineTo(x,0);\
  2547.  ctx.stroke();\
  2548.  ctx.closePath();\
  2549.  if( use_axis_numbering != -1){\
  2550.   xtxt = (px2x(x)).toFixed(prec);\
  2551.   corr = 0.5*(ctx.measureText(xtxt).width);\
  2552.   if(flip == 0 ){flip = 1;ctx.fillText( xtxt,x - corr ,ysize - 0.2*font_size );}else{\
  2553.   flip = 0;ctx.fillText( xtxt,x - corr ,ysize - 1.2*font_size );};\
  2554.  };\
  2555.  for(var dx = 1 ; dx < xminor ; dx++){\
  2556.   ctx.strokeStyle=\"rgba(\"+minor_color+\",\"+minor_opacity+\")\";\
  2557.   ctx.lineWidth = 0.2*line_width;\
  2558.   ctx.beginPath();\
  2559.   ctx.moveTo(x+dx*minor_step,ysize - ymarge);\
  2560.   ctx.lineTo(x+dx*minor_step,0);\
  2561.   ctx.stroke();\
  2562.   ctx.closePath();\
  2563.  };\
  2564. };\
  2565. ctx.restore();\
  2566. };",canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id);
  2567. break;
  2568.  
  2569. case ADD_USER_INPUTS:
  2570. fprintf(js_include_file,"\n/* add_input_xy */\
  2571. function add_input_xy(){\
  2572. if( wims_status == \"done\" ){return;};\
  2573. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  2574. var input_xy_div = document.createElement('div');\
  2575. input_xy_div.id = \"input_xy_div\";\
  2576. tooltip_div.appendChild(input_xy_div);",canvas_root_id);
  2577.  
  2578. if(strstr(draw_type,"polyline") != NULL || strstr(draw_type,"point") != NULL || strstr(draw_type,"cross") != NULL ){ /* ( input_x : input_y )*/
  2579. type=1;
  2580. fprintf(js_include_file,"input_xy_div.innerHTML=\"<br /><span class='%s'>(<input type='text' size='2' value='' id='userinput_x'/> : <input type='text' size='2' value='' id='userinput_y'/>)<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> \";",css_class);
  2581. }else{
  2582. if(strstr(draw_type,"circle") != NULL ){/* M: (input_x :input_y) R:input_r*/
  2583. type=2;
  2584. fprintf(js_include_file,"input_xy_div.innerHTML=\"<br /><span class='%s'>M:&nbsp;(<input type='text' size='2' value='' id='userinput_x'/> : <input type='text' size='2' value='' id='userinput_y'/>) &nbsp;&nbsp;R:&nbsp;<input type='text' size='2' value='' id='userinput_r'/><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> \";",css_class);
  2585. }else{
  2586. type=3;
  2587. if(strstr(draw_type,"segment") != NULL  ||  strstr(draw_type,"line") != NULL  ||  strstr(draw_type,"arrow") != NULL  ){  /* ( input_x1 : input_y1) --- ( input_x2 : input_y2) */
  2588. fprintf(js_include_file,"input_xy_div.innerHTML=\"<br /><span class='%s'>(<input type='text' size='2' value='' id='userinput_x1'/> : <input type='text' size='2' value='' id='userinput_y1'/>) &minus;&minus;&minus; (<input type='text' size='2' value='' id='userinput_x2'/> : <input type='text' size='2' value='' id='userinput_y2'/>)<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> \";",css_class);
  2589. }else{
  2590. type=4;
  2591. if(strstr(draw_type,"triang") != NULL ){ /* ( input_x1 : input_y1) --- ( input_x2 : input_y2) --- ( input_x3 : input_y3) */
  2592. fprintf(js_include_file,"input_xy_div.innerHTML=\"<br /><span class='%s'>&#8420;&nbsp;&nbsp;<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;'/><br/>(<input type='text' size='2' value='' id='userinput_x1'/> : <input type='text' size='2' value='' id='userinput_y1'/>)<br/>(<input type='text' size='2' value='' id='userinput_x2'/> : <input type='text' size='2' value='' id='userinput_y2'/>)<br/>(<input type='text' size='2' value='' id='userinput_x3'/> : <input type='text' size='2' value='' id='userinput_y3'/>)</span> \";",css_class);
  2593. }else{
  2594. type=5;
  2595. if(strstr(draw_type,"text") != NULL ){ /*Text: input_r ( input_x1 : input_y1)  */
  2596. fprintf(js_include_file,"input_xy_div.innerHTML=\"<br /><span class='%s'>(<input type='text' size='2' value='' id='userinput_x'/>:<input type='text' size='2' value='' id='userinput_y'/>)&nbsp;<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> \";",css_class);
  2597. }else{canvas_error("command 'userinput' or 'userinput_xy' is not supported for your 'userdraw' type...");
  2598. }}}}}
  2599.  
  2600. fprintf(js_include_file,"\
  2601. var update_button = document.getElementById(\"update_button\");\
  2602. var delete_button = document.getElementById(\"delete_button\");\
  2603. update_button.addEventListener(\"mousedown\",function(e){update_me();redraw_userdraw();return;},false);\
  2604. delete_button.addEventListener(\"mousedown\",function(e){remove_last();return;},false);\
  2605. };add_input_xy();");
  2606.  
  2607. switch(type){
  2608.  case 1:
  2609. fprintf(js_include_file,"\n/* add_input_xy */\
  2610. function update_me(){\
  2611. var x = safe_eval(document.getElementById('userinput_x').value);\
  2612. var y = safe_eval(document.getElementById('userinput_y').value);\
  2613. userdraw_x.push(x2px(x));userdraw_y.push(y2px(y));\
  2614. return;\
  2615. };");break;
  2616.  case 2:
  2617. fprintf(js_include_file,"\n/* add_input_xy */\
  2618. function update_me(){\
  2619. var x = safe_eval(document.getElementById('userinput_x').value);\
  2620. var y = safe_eval(document.getElementById('userinput_y').value);\
  2621. var r = safe_eval(document.getElementById('userinput_r').value);\
  2622. r = scale_x_radius(r);\
  2623. userdraw_radius.push(r);userdraw_x.push(x2px(x));userdraw_y.push(y2px(y));\
  2624. return;\
  2625. };");break;
  2626.  case 3:
  2627. fprintf(js_include_file,"\n/* add_input_xy */\
  2628. function update_me(){\
  2629. var x,y;\
  2630. for(var p=1; p<3;p++){\
  2631.  x = safe_eval(document.getElementById('userinput_x'+p).value);\
  2632.  y = safe_eval(document.getElementById('userinput_y'+p).value);\
  2633.  userdraw_x.push(x2px(x));userdraw_y.push(y2px(y));\
  2634. };\
  2635. return;\
  2636. };");
  2637.  break;
  2638.  case 4:
  2639. fprintf(js_include_file,"\n/* add_input_xy */\
  2640. function update_me(){\
  2641. var x,y;\
  2642. for(var p=1; p<4;p++){\
  2643.  x = safe_eval(document.getElementById('userinput_x'+p).value);\
  2644.  y = safe_eval(document.getElementById('userinput_y'+p).value);\
  2645.  userdraw_x.push(x2px(x));userdraw_y.push(y2px(y));\
  2646. };\
  2647. return;\
  2648. };");
  2649.  break;
  2650.  case 5:
  2651.  /* a inputfield with 'id=userdraw_text_abc' is provided by command 'userdraw text,color'*/
  2652. fprintf(js_include_file,"\n/* add_input_xy */\
  2653. function update_me(){\
  2654. var x = safe_eval(document.getElementById('userinput_x').value);\
  2655. var y = safe_eval(document.getElementById('userinput_y').value);\
  2656. var txt = conv_to_unicode(document.getElementById('userdraw_text_abc').value);\
  2657. userdraw_x.push(x2px(x));userdraw_y.push(y2px(y));userdraw_text.push(txt.replace(/\\\\/g,' '));\
  2658. return;\
  2659. };");
  2660.  break;
  2661.  default: canvas_error("hmmm, I've no idea...");break;
  2662. }
  2663.  
  2664. break;
  2665.  
  2666. default:break;
  2667.    }
  2668.   }
  2669.  }
  2670.   return;
  2671. }
  2672.