Subversion Repositories wimsdev

Rev

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

  1. void add_drag_code(FILE *js_include_file,int canvas_cnt,int canvas_root_id);
  2. void *my_newmem(size_t size);
  3. void canvas_error(char *msg);
  4. char *eval(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int xsteps,int precision);
  5. char *eval_parametric(int xsize,int ysize,char *fun1,char* fun2,double xmin,double xmax,double ymin,double ymax, double tmin,double tmax,int plotsteps,int precision);
  6. char *data2js_array(int data[],int len);
  7. char *xy2js_array(int xy[],int len);
  8. char *double_xy2js_array(double xy[],int len,int decimals);
  9. void swap(int *a,int *b);
  10. int find_number_of_digits(int i);
  11. int x2px(double x);
  12. int y2px(double y);
  13. void add_js_mouse(FILE *js_include_file,int canvas_cnt,int canvas_root_id,int precision,char *stroke_color,int font_size,double stroke_opacity);
  14. void add_js_points(FILE *js_include_file,int num,char *draw_type,int line_width, int radius ,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1);
  15. void add_js_circles(FILE *js_include_file,int num,char *draw_type, int line_width, int radius , char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1);
  16. void add_js_segments(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1);
  17. void add_js_polyline(FILE *js_include_file,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1);
  18. void add_js_lines(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1);
  19. void add_js_arrows(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1,int arrow_head);
  20. void add_js_crosshairs(FILE *js_include_file,int num,char *draw_type,int line_width, int crosshair_size ,char *stroke_color,double stroke_opacity);
  21. void add_js_paths(FILE *js_include_file,int num,char *draw_type,int line_width, int closed_path,char *stroke_color,double stroke_opacity,int use_filled, char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1);
  22. void add_js_poly(FILE *js_include_file,int num,char *draw_type,int line_width,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1);
  23. void add_js_rect(FILE *js_include_file,int num,int roundrect,char *draw_type,int line_width,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1);
  24. void add_js_floodfill(FILE *js_include_file,int canvas_root_id);
  25. void add_js_filltoborder(FILE *js_include_file,int canvas_root_id);
  26. void add_js_text(FILE *js_include_file,int canvas_root_id,int fontsize,char *font_family,char *font_color,double stroke_opacity,int use_rotate,int angle,int use_translate,int translate_x,int translate_y);
  27. void add_input_circle(FILE *js_include_file,int type,int num);
  28. void add_input_segment(FILE *js_include_file,int num);
  29. void add_input_line(FILE *js_include_file,int num);
  30. void add_input_polyline(FILE *js_include_file);
  31. void add_textarea_polygon(FILE *js_include_file);
  32. void add_input_crosshair(FILE *js_include_file,int num);
  33. void add_input_arrow(FILE *js_include_file,int num);
  34. void add_input_xy(FILE *js_include_file, int canvas_root_id);
  35. void add_input_xyr(FILE *js_include_file, int canvas_root_id);
  36. void add_input_x1y1x2y2(FILE *js_include_file, int canvas_root_id);
  37. void add_textarea_xy(FILE *js_include_file, int canvas_root_id);
  38. /* prints to stdout : should be last */
  39. void add_js_tooltip(int canvas_root_id,char *tooltip_text,char *bgcolor,int xsize,int ysize);
  40.  
  41. /* ............. */
  42.  
  43. void add_js_circles(FILE *js_include_file,int num,char *draw_type,int line_width, int radius ,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  44. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  45. var num = %d;\
  46. userdraw_radius[0] = %d;\
  47. var line_width = %d;\
  48. var stroke_color = \"%s\";\
  49. var stroke_opacity = %f;\
  50. var use_filled = %d;\
  51. var fill_color = \"%s\";\
  52. var fill_opacity = %f;\
  53. var use_dashed = %d;\
  54. var dashtype1 = %d;\
  55. var dashtype0 = %d;\
  56. var click_cnt = 0;\
  57. var x0,y0,x1,y1;\
  58. var canvas_rect;\
  59. function user_draw(evt){\
  60. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  61. y0 = evt.clientY - canvas_rect.top;\
  62. if(y0 < ysize + 1){\
  63.  x0 = evt.clientX - canvas_rect.left;\
  64.  if( x_use_snap_to_grid == 1 ){\
  65.   x0 = snap_to_x(x0);\
  66.  };\
  67.  if( y_use_snap_to_grid == 1 ){\
  68.   y0 = snap_to_y(y0);\
  69.  };\
  70.  if(evt.which == 1){\
  71.   if( click_cnt == 0 ){\
  72.    userdraw_x[xy_cnt] = x0;\
  73.    userdraw_y[xy_cnt] = y0;\
  74.    userdraw_radius[xy_cnt] = line_width;\
  75.    click_cnt = 1;\
  76.    draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  77.   }\
  78.   else\
  79.   {\
  80.    click_cnt = 0;\
  81.    if( num != 1 ){ xy_cnt++; }\
  82.   }\
  83.  }\
  84.  else\
  85.  {\
  86.    canvas_remove(x0,y0);\
  87.  }\
  88. }\
  89. };\
  90. function user_drag(evt){\
  91. if( click_cnt == 1 ){\
  92.    canvas_rect = canvas_userdraw.getBoundingClientRect();\
  93.    y1 = evt.clientY - canvas_rect.top;\
  94.    x1 = evt.clientX - canvas_rect.left;\
  95.    if( x_use_snap_to_grid == 1 ){\
  96.     x0 = snap_to_x(x0);\
  97.    };\
  98.    if( y_use_snap_to_grid == 1 ){\
  99.     y0 = snap_to_y(y0);\
  100.    };\
  101.    userdraw_radius[xy_cnt] = parseInt(Math.sqrt( (x1-x0)*(x1-x0) + (y1-y0)*(y1-y0) ));\
  102.    userdraw_x[xy_cnt] = x0;\
  103.    userdraw_y[xy_cnt] = y0;\
  104.    context_userdraw.clearRect(0,0,xsize,ysize);\
  105.    draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  106.  }\
  107. };\
  108. function canvas_remove(x,y){\
  109. var marge = 10*line_width;\
  110. var diff1;var diff2;\
  111. for(var p = 0;p < userdraw_x.length ; p++){\
  112.  diff1 = (x-userdraw_x[p])*(x - userdraw_x[p]) + (y - userdraw_y[p])*(y - userdraw_y[p]) - userdraw_radius[p]*userdraw_radius[p];\
  113.  diff2 = (x-userdraw_x[p])*(x - userdraw_x[p]) + (y - userdraw_y[p])*(y - userdraw_y[p]) - (userdraw_radius[p] - marge)*(userdraw_radius[p] - marge);\
  114.  if( diff1 < 0 && diff2 > 0 ){\
  115.   if(confirm(\"remove circle ?\")){\
  116.    userdraw_x.splice(p,1);\
  117.    userdraw_y.splice(p,1);\
  118.    userdraw_radius.splice(p,1);\
  119.    xy_cnt--;\
  120.    context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  121.    draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  122.   };\
  123.   return;\
  124.  }\
  125. }\
  126. };",draw_type,num,radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);
  127. }
  128.  
  129. void add_js_crosshairs(FILE *js_include_file,int num,char *draw_type,int line_width, int crosshair_size ,char *stroke_color,double stroke_opacity){
  130. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on currect active canvas -->\n\
  131. var num = %d;\
  132. var crosshair_size = parseInt(0.5*%d);\
  133. var canvas_rect;\
  134. var line_width = %d;\
  135. var stroke_color = \"%s\";\
  136. var stroke_opacity = %f;\
  137. context_userdraw.lineWidth = line_width;\
  138. context_userdraw.strokeStyle=\"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  139. function user_drag(evt){return;}\
  140. function user_draw(evt){\
  141. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  142. var x = evt.clientX - canvas_rect.left;\
  143. var y = evt.clientY - canvas_rect.top;\
  144. if( x_use_snap_to_grid == 1 ){\
  145.  x = snap_to_x(x);\
  146. };\
  147. if( y_use_snap_to_grid == 1 ){\
  148.  y = snap_to_y(y);\
  149. };\
  150. var x1,y1,x2,y2;\
  151. if(evt.which == 1){\
  152.   userdraw_x[xy_cnt] = x;\
  153.   userdraw_y[xy_cnt] = y;\
  154.   x1 = x - crosshair_size;\
  155.   x2 = x + crosshair_size;\
  156.   y1 = y - crosshair_size;\
  157.   y2 = y + crosshair_size;\
  158.   if( num != 1 ){ xy_cnt++;\
  159.    for(var p = 0; p < xy_cnt - 1 ;p++){\
  160.     if(x1 < userdraw_x[p] && x2 > userdraw_x[p]){\
  161.      if(y1 < userdraw_y[p] && y2 > userdraw_y[p]){\
  162.       canvas_remove(x,y);\
  163.       context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");\
  164.      }\
  165.     }\
  166.    }\
  167.   };\
  168.   context_userdraw.beginPath();\
  169.   context_userdraw.moveTo(x1,y1);\
  170.   context_userdraw.lineTo(x2,y2);\
  171.   context_userdraw.closePath();\
  172.   context_userdraw.stroke();\
  173.   context_userdraw.beginPath();\
  174.   context_userdraw.moveTo(x2,y1);\
  175.   context_userdraw.lineTo(x1,y2);\
  176.   context_userdraw.closePath();\
  177.   context_userdraw.stroke();\
  178.   context_userdraw.clearRect(0,0,xsize,ysize);\
  179.   draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  180. }\
  181. else\
  182. {\
  183. canvas_remove(x,y);\
  184. }\
  185. }\
  186. function canvas_remove(x,y){\
  187. var marge = 2*crosshair_size;\
  188. for(var p = 0;p < userdraw_x.length ; p++){\
  189.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  190.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  191.    userdraw_x.splice(p,1);userdraw_y.splice(p,1);\
  192.    context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);xy_cnt--;\
  193.    draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  194.    return;\
  195.   }\
  196.  }\
  197. }\
  198. };",draw_type,num,crosshair_size,line_width,stroke_color,stroke_opacity);
  199. }
  200.  
  201. void add_js_rect(FILE *js_include_file,int num,int roundrect,char *draw_type,int line_width,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  202. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on currect active canvas -->\n\
  203. var canvas_rect;\
  204. var roundrect = %d;\
  205. var line_width = %d;\
  206. var stroke_color = \"%s\";\
  207. var stroke_opacity = %f;\
  208. var use_filled = %d;\
  209. var fill_color = \"%s\";\
  210. var fill_opacity = %f;\
  211. var use_dashed = %d;\
  212. var dashtype0 = %d;\
  213. var dashtype1 = %d;\
  214. var num = %d;\
  215. var use_rotate = 0;\
  216. var angle = 0;\
  217. var use_translate = 0;\
  218. var vector=[0,0];\
  219. var closed_path = 1;\
  220. var clickcnt = 0;\
  221. xy_cnt = 0;\
  222. var x0,y0,x1,y1;\
  223. var marge = 10*line_width;\
  224. function user_draw(evt){\
  225. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  226. y0 = evt.clientY - canvas_rect.top;\
  227. if( y0  < ysize + 1 ){\
  228.  x0 = evt.clientX - canvas_rect.left;\
  229.  if( x_use_snap_to_grid == 1 ){\
  230.   x0 = snap_to_x(x0);\
  231.  };\
  232.  if( y_use_snap_to_grid == 1 ){\
  233.   y0 = snap_to_y(y0);\
  234.  };\
  235.  if( evt.which == 1 ){\
  236.   if(clickcnt == 0 ){\
  237.    clickcnt = 1;\
  238.    userdraw_x[xy_cnt] = x0;userdraw_y[xy_cnt] = y0;xy_cnt++;\
  239.   }\
  240.   else\
  241.   {\
  242.    clickcnt = 0;\
  243.    if(roundrect == 0 ){\
  244.     draw_rects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,use_translate,vector);\
  245.    }\
  246.    else\
  247.    {\
  248.     draw_roundrects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,use_translate,vector);\
  249.    }\
  250.    if( num != 1 ){ xy_cnt++; }else{xy_cnt--;}\
  251.   }\
  252.  }\
  253.  else\
  254.  {\
  255.   canvas_remove(x0,y0);\
  256.  };\
  257. };\
  258. };\
  259. function user_drag(evt){\
  260. if( clickcnt == 1 ){\
  261.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  262.  y1 = evt.clientY - canvas_rect.top;\
  263.  x1 = evt.clientX - canvas_rect.left;\
  264.  if( x_use_snap_to_grid == 1 ){\
  265.  x1 = snap_to_x(x1);\
  266.  };\
  267.  if( y_use_snap_to_grid == 1 ){\
  268.  y1 = snap_to_y(y1);\
  269.  };\
  270.  userdraw_x[xy_cnt] = x1;\
  271.  userdraw_y[xy_cnt] = y1;\
  272.  context_userdraw.clearRect(0,0,xsize,ysize);\
  273.  if( roundrect == 0 ){\
  274.   draw_rects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,use_translate,vector);\
  275.  }\
  276.  else\
  277.  {\
  278.   draw_roundrects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,use_translate,vector);\
  279.  };\
  280. };\
  281. };\
  282. function canvas_remove(x,y){\
  283. for(var p = 0;p < userdraw_x.length ; p++){\
  284.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  285.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  286.    if( confirm(\"remove rectangle ?\" )){\
  287.     if( p%%2 == 0 ){\
  288.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  289.     }\
  290.     else\
  291.     {\
  292.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  293.     }\
  294.     xy_cnt--;\
  295.     context_userdraw.clearRect(0,0,xsize,ysize);\
  296.     if(xy_cnt < 2){xy_cnt = 0;click_cnt = 0;userdraw_x = [];userdraw_y = [];return;};\
  297.     if( roundrect == 0 ){\
  298.      draw_rects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,use_translate,vector);\
  299.     }\
  300.     else\
  301.     {\
  302.      draw_roundrects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,use_translate,vector);\
  303.     }\
  304.     return;\
  305.    };\
  306.   };\
  307.  };\
  308. };\
  309. };",draw_type,roundrect,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,num);
  310. }
  311.  
  312. void add_js_poly(FILE *js_include_file,int num,char *draw_type,int line_width,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  313. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on currect active canvas -->\n\
  314. var canvas_rect;\
  315. var num = %d;\
  316. var line_width = %d;\
  317. var stroke_color = \"%s\";\
  318. var stroke_opacity = %f;\
  319. var use_filled = %d;\
  320. var fill_color = \"%s\";\
  321. var fill_opacity = %f;\
  322. var use_dashed = %d;\
  323. var dashtype0 = %d;\
  324. var dashtype1 = %d;\
  325. var use_rotate = 0;\
  326. var angle = 0;\
  327. var use_translate = 0;\
  328. var vector=[0,0];\
  329. var closed_path = 1;\
  330. var done = 1;\
  331. var x,y;\
  332. var marge = 10*line_width;\
  333. function user_draw(evt){\
  334. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  335. y = evt.clientY - canvas_rect.top;\
  336. if( y < ysize + 1 ){\
  337.  x = evt.clientX - canvas_rect.left;\
  338.  if( x_use_snap_to_grid == 1 ){\
  339.   x = snap_to_x(x);\
  340.  };\
  341.  if( y_use_snap_to_grid == 1 ){\
  342.   y = snap_to_y(y);\
  343.  };\
  344.  if( evt.which == 1){\
  345.   if( num == -1 && xy_cnt > 2 ){\
  346.    if( x - marge < userdraw_x[0] && x + marge > userdraw_x[0]){\
  347.     if( y - marge < userdraw_y[0] && y + marge > userdraw_y[0]){\
  348.      userdraw_x.splice(xy_cnt,1);userdraw_y.splice(xy_cnt,1);\
  349.      draw_paths(context_userdraw,userdraw_x,userdraw_y,line_width,closed_path,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,use_translate,vector);\
  350.      done = 1;return;\
  351.     };\
  352.    };\
  353.   }\
  354.   else\
  355.   {\
  356.    if( xy_cnt == num - 1){\
  357.     draw_paths(context_userdraw,userdraw_x,userdraw_y,line_width,closed_path,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,use_translate,vector);\
  358.     done = 1;return;\
  359.    };\
  360.   };\
  361.   done = 0;\
  362.   userdraw_x[xy_cnt] = x;userdraw_y[xy_cnt] = y;xy_cnt++;\
  363.   user_drag(evt);\
  364.  }\
  365.  else\
  366.  {\
  367.   canvas_remove(x,y);\
  368.   return;\
  369.  }\
  370. };\
  371. };\
  372. function user_drag(evt){\
  373. if( done == 0 ){\
  374.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  375.  x = evt.clientX - canvas_rect.left;\
  376.  y = evt.clientY - canvas_rect.top;\
  377.  if( x_use_snap_to_grid == 1 ){\
  378.   x = snap_to_x(x);\
  379.  };\
  380.  if( y_use_snap_to_grid == 1 ){\
  381.   y = snap_to_y(y);\
  382.  };\
  383.  context_userdraw.clearRect(0,0,xsize,ysize);\
  384.  userdraw_x[xy_cnt] = x;userdraw_y[xy_cnt] = y;\
  385.  draw_paths(context_userdraw,userdraw_x,userdraw_y,line_width,closed_path,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,use_translate,vector);\
  386. }\
  387. }\
  388. function canvas_remove(x,y){\
  389. for(var p = 0;p < userdraw_x.length ; p++){\
  390.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  391.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  392.    if( confirm(\"remove polygone ?\" )){\
  393.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  394.     xy_cnt = 0;userdraw_x = [];userdraw_y = [];done = 1;\
  395.    }\
  396.    return;\
  397.   }\
  398.  }\
  399. }\
  400. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);
  401. }
  402.  
  403. /*  function draw_circles(ctx,x_points,y_points,radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);*/
  404. void add_js_points(FILE *js_include_file,int num,char *draw_type,int line_width, int radius ,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  405. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  406. var num = %d;\
  407. var canvas_rect;\
  408. userdraw_radius[0] = %d;\
  409. var line_width = %d;\
  410. var stroke_color = \"%s\";\
  411. var stroke_opacity = %f;\
  412. var use_filled = %d;\
  413. var fill_color = \"%s\";\
  414. var fill_opacity = %f;\
  415. var use_dashed = %d;\
  416. var dashtype0 = %d;\
  417. var dashtype1 = %d;\
  418. function user_drag(evt){return;};\
  419. function user_draw(evt){\
  420. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  421. var y = evt.clientY - canvas_rect.top;\
  422. if( y < ysize + 1 ){\
  423.  var lu = userdraw_x.length;\
  424.  var x = evt.clientX - canvas_rect.left;\
  425.  if( x_use_snap_to_grid == 1 ){\
  426.   x = snap_to_x(x);\
  427.  };\
  428.  if( y_use_snap_to_grid == 1 ){\
  429.   y = snap_to_y(y);\
  430.  };\
  431.  if(evt.which == 1){\
  432.   if( num == 1 ){\
  433.   userdraw_x[0] = x;\
  434.   userdraw_y[0] = y;\
  435.   }\
  436.   else\
  437.   {\
  438.   userdraw_x[lu] = x;\
  439.   userdraw_y[lu] = y;\
  440.   userdraw_radius[lu] = userdraw_radius[0];\
  441.   };\
  442.   context_userdraw.clearRect(0,0,xsize,ysize);\
  443.   draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  444.  }\
  445.  else\
  446.  {\
  447.  canvas_remove(x,y);\
  448.  }\
  449. }\
  450. };\
  451. function canvas_remove(x,y){\
  452. var marge = 4*line_width;\
  453. for(var p = 0;p < userdraw_x.length ; p++){\
  454.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  455.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  456.    userdraw_x.splice(p,1);userdraw_y.splice(p,1);\
  457.    context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  458.    draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  459.    return;\
  460.   }\
  461.  }\
  462. }\
  463. };",draw_type,num,radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);
  464.  
  465. }
  466. void add_js_polyline(FILE *js_include_file,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1){
  467. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  468. var canvas_rect;\
  469. var cnt = 0;\
  470. var line_width = %d;\
  471. var stroke_color = \"%s\";\
  472. var stroke_opacity = %f;\
  473. var use_dashed = %d;\
  474. var dashtype0 = %d;\
  475. var dashtype1 = %d;\
  476. function user_draw(evt){\
  477. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  478. var x = evt.clientX - canvas_rect.left;\
  479. var y = evt.clientY - canvas_rect.top;\
  480. var lu = userdraw_x.length;\
  481. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  482. if( x_use_snap_to_grid == 1 ){\
  483.  x = snap_to_x(x);\
  484. };\
  485. if( y_use_snap_to_grid == 1 ){\
  486.  y = snap_to_y(y);\
  487. };\
  488. if( evt.which == 1 ){\
  489.  userdraw_x[lu] = x;userdraw_y[lu] = y;\
  490.  if( cnt == 0 ){\
  491.   user_drag(evt);\
  492.   cnt = 1;\
  493.  }\
  494.  else\
  495.  {\
  496.    cnt = 0;\
  497.    draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  498.  }\
  499. }\
  500. else\
  501. {\
  502.  canvas_remove(x,y);\
  503. }\
  504. };\
  505. function user_drag(evt){\
  506. if( cnt == 0){\
  507.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  508.  var x = evt.clientX - canvas_rect.left;\
  509.  var y = evt.clientY - canvas_rect.top;\
  510.  if( x_use_snap_to_grid == 1 ){\
  511.   x = snap_to_x(x);\
  512.  };\
  513.  if( y_use_snap_to_grid == 1 ){\
  514.   y = snap_to_y(y);\
  515.  };\
  516.  var lu = userdraw_x.length;\
  517.  if( lu > 0 ){\
  518.   userdraw_x[lu - 1] = x; userdraw_y[lu - 1] = y;\
  519.   draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  520.  };\
  521. }\
  522. };\
  523. function canvas_remove(x,y){\
  524. if( confirm(\"remove line ?\" )){\
  525.  context_userdraw.clearRect(0,0,xsize,ysize);\
  526.  userdraw_x = [];userdraw_y = [];cnt = 1;\
  527.  return;\
  528. }\
  529. };",draw_type,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  530. }
  531.  
  532. void add_js_segments(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1){
  533. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  534. var canvas_rect;\
  535. var num = %d;\
  536. var line_width = %d;\
  537. var stroke_color = \"%s\";\
  538. var stroke_opacity = %f;\
  539. var use_dashed = %d;\
  540. var dashtype0 = %d;\
  541. var dashtype1 = %d;\
  542. var x0,y0;\
  543. function user_draw(evt){\
  544. var lu = userdraw_x.length;\
  545. if( lu != 0 && lu%%2 == 0){\
  546.  draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  547. }\
  548. var y = evt.clientY - canvas_rect.top;\
  549. if( y < ysize + 1){\
  550.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  551.  var x = evt.clientX - canvas_rect.left;\
  552.  if( x_use_snap_to_grid == 1 ){\
  553.   x = snap_to_x(x);\
  554.  };\
  555.  if( y_use_snap_to_grid == 1 ){\
  556.   y = snap_to_y(y);\
  557.  };\
  558.  if( evt.which == 1 ){\
  559.   if( lu%%2 == 0){\
  560.    x0 = x;y0 = y;\
  561.    if(num == 1){ userdraw_x = [];userdraw_y = [];userdraw_x[0] = x0;userdraw_y[0] = y0;} else {userdraw_x[lu] = x0;userdraw_y[lu] = y0;}\
  562.    draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  563.    user_drag(evt);\
  564.   }\
  565.   else\
  566.   {\
  567.    if( num == 1 ){ userdraw_x[1] = x;userdraw_y[1] = y;} else {userdraw_x[lu] = x;userdraw_y[lu] = y;};\
  568.    draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  569.   }\
  570.  }\
  571.  else\
  572.  {\
  573.   canvas_remove(x,y);\
  574.  }\
  575. }\
  576. };\
  577. function user_drag(evt){\
  578. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  579. var x = evt.clientX - canvas_rect.left;\
  580. var y = evt.clientY - canvas_rect.top;\
  581. var lu = userdraw_x.length;\
  582. if( x_use_snap_to_grid == 1 ){\
  583.   x = snap_to_x(x);\
  584. };\
  585. if( y_use_snap_to_grid == 1 ){\
  586.   y = snap_to_y(y);\
  587. };\
  588. if( lu%%2 != 0 ){\
  589.  context_userdraw.clearRect(0,0,xsize,ysize);\
  590.  draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  591.  draw_circles(context_userdraw,[x],[y],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  592.  draw_segments(context_userdraw,[x0,x],[y0,y],line_width,stroke_color,stroke_opacity);\
  593.  if( lu > 0){\
  594.   draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  595.  }\
  596. }\
  597. };\
  598. function canvas_remove(x,y){\
  599. var marge = 10*line_width;\
  600. for(var p = 0;p < userdraw_x.length ; p++){\
  601.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  602.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  603.    if( confirm(\"remove line ?\" )){\
  604.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  605.     if( p%%2 == 0 ){\
  606.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  607.     }\
  608.     else\
  609.     {\
  610.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  611.     }\
  612.     if(userdraw_x.length < 2){ userdraw_x = [];userdraw_y = [];return;};\
  613.     draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  614.    }\
  615.    return;\
  616.   }\
  617.  }\
  618. }\
  619. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  620. }
  621.  
  622. void add_js_lines(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1){
  623. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  624. var canvas_rect;\
  625. var num = %d;\
  626. var line_width = %d;\
  627. var stroke_color = \"%s\";\
  628. var stroke_opacity = %f;\
  629. var use_dashed = %d;\
  630. var dashtype0 = %d;\
  631. var dashtype1 = %d;\
  632. var x0,y0;\
  633. function user_draw(evt){\
  634. var lu = userdraw_x.length;\
  635. if( lu != 0 && lu%%2 == 0){\
  636.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  637. }\
  638. var y = evt.clientY - canvas_rect.top;\
  639. if( y < ysize + 1){\
  640.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  641.  var x = evt.clientX - canvas_rect.left;\
  642.  if( x_use_snap_to_grid == 1 ){\
  643.   x = snap_to_x(x);\
  644.  };\
  645.  if( y_use_snap_to_grid == 1 ){\
  646.   y = snap_to_y(y);\
  647.  };\
  648.  if( evt.which == 1 ){\
  649.   if( lu%%2 == 0){\
  650.    x0 = x;y0 = y;\
  651.    if(num == 1){ userdraw_x = [];userdraw_y = [];userdraw_x[0] = x0;userdraw_y[0] = y0;} else {userdraw_x[lu] = x0;userdraw_y[lu] = y0;}\
  652.    draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  653.    user_drag(evt);\
  654.   }\
  655.   else\
  656.   {\
  657.    if( num == 1 ){ userdraw_x[1] = x;userdraw_y[1] = y;} else {userdraw_x[lu] = x;userdraw_y[lu] = y;};\
  658.    draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  659.   }\
  660.  }\
  661.  else\
  662.  {\
  663.   canvas_remove(x,y);\
  664.  }\
  665. }\
  666. };\
  667. function user_drag(evt){\
  668. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  669. var x = evt.clientX - canvas_rect.left;\
  670. var y = evt.clientY - canvas_rect.top;\
  671. var lu = userdraw_x.length;\
  672. if( x_use_snap_to_grid == 1 ){\
  673.   x = snap_to_x(x);\
  674. };\
  675. if( y_use_snap_to_grid == 1 ){\
  676.   y = snap_to_y(y);\
  677. };\
  678. if( lu%%2 != 0 ){\
  679.  context_userdraw.clearRect(0,0,xsize,ysize);\
  680.  draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  681.  draw_circles(context_userdraw,[x],[y],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  682.  draw_lines(context_userdraw,[x0,x],[y0,y],line_width,stroke_color,stroke_opacity);\
  683.  if( lu > 0){\
  684.   draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  685.  }\
  686. }\
  687. };\
  688. function canvas_remove(x,y){\
  689. var marge = 10*line_width;\
  690. for(var p = 0;p < userdraw_x.length ; p++){\
  691.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  692.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  693.    if( confirm(\"remove line ?\" )){\
  694.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  695.     if( p%%2 == 0 ){\
  696.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  697.     }\
  698.     else\
  699.     {\
  700.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  701.     }\
  702.     if(userdraw_x.length < 2){ userdraw_x = [];userdraw_y = [];return;};\
  703.     draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  704.    }\
  705.    return;\
  706.   }\
  707.  }\
  708. }\
  709. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  710. }
  711.  
  712. void add_js_arrows(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1,int arrow_head){
  713. /*
  714. constants in draw_arrows() ... for this moment: var type = 1;var use_rotate = 0;var angle = 0;var use_translate = 0 ;var vector = [0,0];\
  715.  
  716. */
  717. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  718. var canvas_rect;\
  719. var num = %d;\
  720. var line_width = %d;\
  721. var stroke_color = \"%s\";\
  722. var stroke_opacity = %f;\
  723. var use_dashed = %d;\
  724. var dashtype0 = %d;\
  725. var dashtype1 = %d;\
  726. var arrow_head = %d;\
  727. var x0,y0;\
  728. var type = 1;var use_rotate = 0;var angle = 0;var use_translate = 0 ;var vector = [0,0];\
  729. function user_draw(evt){\
  730. var lu = userdraw_x.length;\
  731. if( lu != 0 && lu%%2 == 0){\
  732.  draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,use_translate,vector);\
  733. }\
  734. var y = evt.clientY - canvas_rect.top;\
  735. if( y < ysize + 1){\
  736.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  737.  var x = evt.clientX - canvas_rect.left;\
  738.  if( x_use_snap_to_grid == 1 ){\
  739.   x = snap_to_x(x);\
  740.  };\
  741.  if( y_use_snap_to_grid == 1 ){\
  742.   y = snap_to_y(y);\
  743.  };\
  744.  if( evt.which == 1 ){\
  745.   if( lu%%2 == 0){\
  746.    x0 = x;y0 = y;\
  747.    if(num == 1){ userdraw_x = [];userdraw_y = [];userdraw_x[0] = x0;userdraw_y[0] = y0;} else {userdraw_x[lu] = x0;userdraw_y[lu] = y0;}\
  748.    user_drag(evt);\
  749.   }\
  750.   else\
  751.   {\
  752.    if( num == 1 ){ userdraw_x[1] = x;userdraw_y[1] = y;} else {userdraw_x[lu] = x;userdraw_y[lu] = y;};\
  753.    draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,use_translate,vector);\
  754.   }\
  755.  }\
  756.  else\
  757.  {\
  758.   canvas_remove(x,y);\
  759.  }\
  760. }\
  761. };\
  762. function user_drag(evt){\
  763. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  764. var x = evt.clientX - canvas_rect.left;\
  765. var y = evt.clientY - canvas_rect.top;\
  766. var lu = userdraw_x.length;\
  767. if( x_use_snap_to_grid == 1 ){\
  768.   x = snap_to_x(x);\
  769. };\
  770. if( y_use_snap_to_grid == 1 ){\
  771.   y = snap_to_y(y);\
  772. };\
  773. if( lu%%2 != 0 ){\
  774.  context_userdraw.clearRect(0,0,xsize,ysize);\
  775.  draw_arrows(context_userdraw,[x0,x],[y0,y],arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,use_translate,vector);\
  776.  if( lu > 0){\
  777.    draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,use_translate,vector);\
  778.  }\
  779. }\
  780. };\
  781. function canvas_remove(x,y){\
  782. var marge = 10*line_width;\
  783. for(var p = 0;p < userdraw_x.length ; p++){\
  784.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  785.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  786.    if( confirm(\"remove line ?\" )){\
  787.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  788.     if( p%%2 == 0 ){\
  789.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  790.     }\
  791.     else\
  792.     {\
  793.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  794.     }\
  795.     if(userdraw_x.length < 2){ userdraw_x = [];userdraw_y = [];return;};\
  796.     draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,use_translate,vector,type,use_rotate,angle,use_translate,vector);\
  797.    }\
  798.    return;\
  799.   }\
  800.  }\
  801. }\
  802. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,arrow_head);
  803.  
  804. }
  805.  
  806. void add_js_paths(FILE *js_include_file,int num,char *draw_type,int line_width, int closed_path,char *stroke_color,double stroke_opacity,int use_filled, char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  807. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  808. var path_cnt = 0;\
  809. temp_x = [];\
  810. temp_y = [];\
  811. var num = %d;\
  812. xy_cnt=0;\
  813. var line_width = %d;\
  814. var stroke_color = \"%s\";\
  815. var stroke_opacity = %f;\
  816. var fill_color = \"%s\";\
  817. var fill_opacity = %f;\
  818. var use_filled = %d;\
  819. var use_dashed = %d;\
  820. var dashtype0 = %d;\
  821. var dashtype1 = %d;\
  822. var closed_path = 0;\
  823. var click_cnt=0;\
  824. var x0,y0;\
  825. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  826. function user_draw(evt){\
  827. if(evt.which == 1 ){\
  828.  if( click_cnt == 0 ){\
  829.   click_cnt = 1;\
  830.   user_drag(evt);\
  831.  }\
  832.  else\
  833.  {\
  834.   userdraw_x[path_cnt] = new Array();\
  835.   userdraw_y[path_cnt] = new Array();\
  836.   userdraw_x[path_cnt] = temp_x;\
  837.   userdraw_y[path_cnt] = temp_y;\
  838.   path_cnt++;\
  839.   temp_x = [];\
  840.   temp_y = [];\
  841.   click_cnt = 0;\
  842.   xy_cnt = 0;\
  843.  };\
  844. }\
  845. else\
  846. {\
  847.   canvas_remove(evt.clientX - canvas_rect.left,evt.clientY - canvas_rect.top);\
  848. };\
  849. context_userdraw.clearRect(0,0,xsize,ysize);\
  850. for(var p=0; p < path_cnt; p++){\
  851.  if(userdraw_x[p] != null){\
  852.   draw_paths(context_userdraw,userdraw_x[p],userdraw_y[p],line_width,0,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  853.  };\
  854. };\
  855. };\
  856. function user_drag(evt){\
  857. if(click_cnt == 1 ){\
  858.  temp_y[xy_cnt] = evt.clientY - canvas_rect.top;\
  859.  if( temp_y[xy_cnt] < ysize + 1){\
  860.   temp_x[xy_cnt] = evt.clientX - canvas_rect.left;\
  861.   if( x_use_snap_to_grid == 1 ){\
  862.    temp_x[xy_cnt] = snap_to_x(temp_x[xy_cnt]);\
  863.   };\
  864.   if( y_use_snap_to_grid == 1 ){\
  865.    temp_y[xy_cnt] = snap_to_y(temp_y[xy_cnt]);\
  866.   };\
  867.   xy_cnt++;\
  868.   draw_paths(context_userdraw,temp_x,temp_y,line_width,0,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  869.  };\
  870. };\
  871. };\
  872. function canvas_remove(x,y){\
  873. var marge = 4*line_width;\
  874. var tmpx = [];\
  875. var tmpy = [];\
  876. for(var i = 0 ; i < path_cnt; i++){\
  877.  tmpx = userdraw_x[i];\
  878.  if(tmpx != null){\
  879.   tmpy = userdraw_y[i];\
  880.   for(var p = 0;p<tmpx.length;p++){\
  881.    if( x + marge > tmpx[p] &&  x - marge < tmpx[p] ){\
  882.     if( y + marge > tmpy[p] &&  y - marge < tmpy[p] ){\
  883.      if(confirm(\"Remove this drawing ?\")){\
  884.       userdraw_x[i] = null;\
  885.       userdraw_y[i] = null;\
  886.       xy_cnt = 0;click_cnt = 0;\
  887.       return;\
  888.      };\
  889.     };\
  890.    };\
  891.   };\
  892.  };\
  893. };\
  894. };",draw_type,num,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1);
  895. }
  896.  
  897. void add_js_tooltip(int canvas_root_id,char *tooltip_text,char *bgcolor,int xsize,int ysize){
  898. fprintf(stdout,"\n<!-- begin command intooltip %d -->\n\
  899. <script type=\"text/javascript\">\n\
  900. var xsize = %d;\
  901. var ysize = %d;\
  902. var tooltip%d_obj_x = 0;\
  903. var tooltip%d_obj_y = 0;\
  904. var tooltip%d_flipflop = 0;\
  905. var tooltip%d_obj = document.getElementById(\"canvas_div%d\");\
  906. tooltip%d_obj.style.display=\"none\";\
  907. tooltip%d_obj.style.position=\"absolute\";\
  908. var tooltip%d_link = document.createElement(\"a\");\
  909. tooltip%d_link.addEventListener(\"mousemove\",tooltip%d_drag,false);\
  910. tooltip%d_link.setAttribute(\"onclick\",\"tooltip%d_show()\");\
  911. tooltip%d_link.innerHTML  = \"%s\";\
  912. var tooltip_placeholder = document.getElementById(\"tooltip_placeholder%d\");\
  913. tooltip_placeholder.style.display=\"block\";\
  914. tooltip_placeholder.style.position=\"absolute\";\
  915. tooltip_placeholder.style.backgroundColor=\"%s\";\
  916. tooltip_placeholder.appendChild(tooltip%d_link);\
  917. function tooltip%d_drag(action){\
  918. if(!action){ action = event; }\
  919. if(action.clientX){\
  920.  tooltip%d_obj.style.left = (tooltip%d_mouseX(action) + 10) +\"px\";\
  921.  var ytop = tooltip%d_mouseY(action);\
  922.  if(ytop + ysize < window.innerHeight){\
  923.   tooltip%d_obj.style.top = (ytop - 10) +\"px\";\
  924.  }\
  925.  else\
  926.  {\
  927.   tooltip%d_obj.style.top = parseInt(ytop - 0.8*ysize) +\"px\";\
  928.  }\
  929. }\
  930. else\
  931. {\
  932.  return null;\
  933. }\
  934. }\
  935. function tooltip%d_mouseX(action){\
  936. if(action.pageX){\
  937.  return action.pageX;\
  938. }\
  939. else\
  940. {\
  941.  if(action.clientX){\
  942.   return action.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);\
  943.  }\
  944.  else\
  945.  {\
  946.   return null;\
  947.  }\
  948. }\
  949. }\
  950. function tooltip%d_mouseY(action){\
  951. if(action.pageY){\
  952.  return action.pageY;\
  953. }\
  954. else\
  955. {\
  956.  if(action.clientY){\
  957.   return action.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop :document.body.scrollTop);\
  958.  }\
  959.  else\
  960.  {\
  961.   return null;\
  962.  }\
  963. }\
  964. }\
  965. function tooltip%d_show(){\
  966. if(tooltip%d_flipflop == 0){\
  967.  tooltip%d_obj.style.display = \"block\";\
  968.  tooltip%d_flipflop = 1;\
  969. }\
  970. else\
  971. {\
  972.  tooltip%d_flipflop = 0;\
  973.  tooltip%d_obj.style.display = \"none\";\
  974. }\
  975. };\n</script>\n<!-- end command intooltip %d -->\n",canvas_root_id,xsize,ysize,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,tooltip_text,canvas_root_id,bgcolor,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id);
  976.  
  977. }
  978.  
  979. /*
  980. #define BG_CANVAS 0 may be used for floodfill
  981. #define STATIC_CANVAS 1 may be used for floodfill
  982. #define MOUSE_CANVAS 2 xx
  983. #define GRID_CANVAS 3 may be used for floodfill
  984. #define DRAG_CANVAS 4 default for floodfill
  985. #define DRAW_CANVAS 5 may be used for floodfill
  986.  
  987. */
  988. void add_js_floodfill(FILE *js_include_file,int canvas_root_id){
  989. fprintf(js_include_file,"\n<!-- begin command floodfill -->\n\
  990. floodfill = function(interaction,X,Y,color){\
  991. var x;var y;\
  992. var canvas = document.getElementById(\"wims_canvas%d%d\");\
  993. if( ! canvas ){ return; };\
  994. var ctx = canvas.getContext(\"2d\");\
  995. ctx.save();\
  996. if(interaction == 1 ){\
  997.  x = X;\
  998.  y = Y;\
  999.  if( y > ysize - 15){return;}\
  1000. }\
  1001. else\
  1002. {\
  1003.  x = x2px(X);\
  1004.  y = y2px(Y);\
  1005. };\
  1006. x = parseInt(x);y = parseInt(y);\
  1007. var image = ctx.getImageData(0, 0, xsize, ysize);\
  1008. var imageData = image.data;\
  1009. var pixelStack = [[x, y]];\
  1010. var px1;\
  1011. var newPos;\
  1012. var pixelPos;\
  1013. var found_left_border;\
  1014. var found_right_border;\
  1015. function _getPixel(pixelPos){\
  1016.  return {r:imageData[pixelPos], g:imageData[pixelPos+1], b:imageData[pixelPos+2], a:imageData[pixelPos+3]};\
  1017. };\
  1018. function _setPixel(pixelPos){\
  1019.  imageData[pixelPos] = color.r;\
  1020.  imageData[pixelPos+1] = color.g;\
  1021.  imageData[pixelPos+2] = color.b;\
  1022.  imageData[pixelPos+3] = color.a;\
  1023. };\
  1024. function _comparePixel(px2){\
  1025.  return (px1.r === px2.r && px1.g === px2.g && px1.b === px2.b && px1.a === px2.a);\
  1026. };\
  1027. px1 = _getPixel(((y * xsize) + x) * 4);\
  1028. color = {\
  1029.  r: parseInt(color[0], 10),\
  1030.  g: parseInt(color[1], 10),\
  1031.  b: parseInt(color[2], 10),\
  1032.  a: parseInt(color[3] || 255, 10)\
  1033. };\
  1034. if( _comparePixel(color) ) { return true; }\
  1035. while (pixelStack.length) {\
  1036.  newPos = pixelStack.pop();\
  1037.  pixelPos = (newPos[1]*xsize + newPos[0]) * 4;\
  1038.  while(newPos[1]-- >= 0 && _comparePixel(_getPixel(pixelPos))){\
  1039.   pixelPos -= xsize * 4;\
  1040.  }\
  1041.  pixelPos += xsize * 4;\
  1042.  ++newPos[1];\
  1043.  found_left_border = false;\
  1044.  found_right_border = false;\
  1045.  while( newPos[1]++ < ysize-1 && _comparePixel(_getPixel(pixelPos)) ){\
  1046.   _setPixel(pixelPos);\
  1047.   if( newPos[0] > 0 ){\
  1048.    if( _comparePixel(_getPixel(pixelPos - 4)) ){\
  1049.    if( !found_left_border ){\
  1050.     pixelStack.push( [newPos[0] - 1, newPos[1]] );\
  1051.     found_left_border == 1;\
  1052.    }\
  1053.   }\
  1054.   else if( found_left_border ){\
  1055.     found_left_border = false;\
  1056.    }\
  1057.   }\
  1058.   if( newPos[0] < xsize-1 ){\
  1059.    if( _comparePixel(_getPixel(pixelPos + 4)) ){\
  1060.     if( !found_right_border){\
  1061.      pixelStack.push( [newPos[0] + 1, newPos[1]] );\
  1062.      found_right_border == 1;\
  1063.     }\
  1064.    }\
  1065.    else if(found_right_border){\
  1066.      found_right_border = false;\
  1067.     }\
  1068.    }\
  1069.   pixelPos += xsize * 4;\
  1070.  }\
  1071. };\
  1072. if( interaction == 0){\
  1073.  var _canvas = create_canvas%d(21,xsize,ysize);\
  1074.  var _ctx = _canvas.getContext(\"2d\");\
  1075. _ctx.putImageData(image, 0, 0);\
  1076. }else{\
  1077.  ctx.putImageData(image, 0, 0);\
  1078. };\
  1079. ctx.restore();\
  1080. };",canvas_root_id,DRAG_CANVAS,canvas_root_id);
  1081.  
  1082. }
  1083.  
  1084.  
  1085. void add_js_filltoborder(FILE *js_include_file,int canvas_root_id){
  1086. fprintf(js_include_file,"\n<!-- begin command filltoborder -->\n\
  1087. filltoborder_cnt = 200;\
  1088. filltoborder = function(x,y,bordercolor,color){\
  1089. x = x2px(x);\
  1090. y = y2px(y);\
  1091. var canvas;\
  1092. var ctx;\
  1093. suitable_canvases = [4,5,1,0];\
  1094. var c_id;var found = -1;\
  1095. for( var p = 0 ; p < 5; p++ ){\
  1096.  c_id = suitable_canvases[p];\
  1097.  if( document.getElementById(\"wims_canvas%d\"+c_id) ){\
  1098.   canvas = document.getElementById(\"wims_canvas%d\"+c_id);\
  1099.   found = c_id;\
  1100.   break;\
  1101.  };\
  1102. };\
  1103. if( found == -1 ){alert(\"Something is very wrong...\\nNo suitable canvas found for filling operation!!\");return;}\
  1104. ctx = canvas.getContext(\"2d\");ctx.save();\
  1105. var image = ctx.getImageData(0, 0, xsize, ysize);\
  1106. var imageData = image.data;\
  1107. var pixelStack = [[x, y]];\
  1108. var px1;\
  1109. var newPos;\
  1110. var pixelPos;\
  1111. var found_left_border;\
  1112. var found_right_border;\
  1113. function _getPixel(pixelPos){\
  1114.  return {r:imageData[pixelPos], g:imageData[pixelPos+1], b:imageData[pixelPos+2], a:imageData[pixelPos+3]};\
  1115. };\
  1116. function _setPixel(pixelPos){\
  1117.  imageData[pixelPos] = color.r;\
  1118.  imageData[pixelPos+1] = color.g;\
  1119.  imageData[pixelPos+2] = color.b;\
  1120.  imageData[pixelPos+3] = color.a;\
  1121. };\
  1122. function _comparePixel(px2){\
  1123.  return (px1.r === px2.r && px1.g === px2.g && px1.b === px2.b && px1.a === px2.a);\
  1124. };\
  1125. function _checkBorder(px2){\
  1126.  return (bordercolor.r === px2.r && bordercolor.g === px2.g && bordercolor.b === px2.b && bordercolor.a === px2.a);\
  1127. };\
  1128. px1 = _getPixel(((y * xsize) + x) * 4);\
  1129. bordercolor = {\
  1130.  r: parseInt(bordercolor[0], 10),\
  1131.  g: parseInt(bordercolor[1], 10),\
  1132.  b: parseInt(bordercolor[2], 10),\
  1133.  a: parseInt(bordercolor[3] || 255, 10)\
  1134. };\
  1135. color = {\
  1136.  r: parseInt(color[0], 10),\
  1137.  g: parseInt(color[1], 10),\
  1138.  b: parseInt(color[2], 10),\
  1139.  a: parseInt(color[3] || 255, 10)\
  1140. };\
  1141. if( _comparePixel(color) ) { return true; }\
  1142. while (pixelStack.length) {\
  1143.  newPos = pixelStack.pop();\
  1144.  pixelPos = (newPos[1]*xsize + newPos[0]) * 4;\
  1145.  while(newPos[1]-- >= 0 && ( ! _checkBorder(_getPixel(pixelPos))) ){\
  1146.   pixelPos -= xsize * 4;\
  1147.  }\
  1148.  pixelPos += xsize * 4;\
  1149.  ++newPos[1];\
  1150.  found_left_border = false;\
  1151.  found_right_border = false;\
  1152.  while( newPos[1]++ < ysize-1 && ( ! _checkBorder(_getPixel(pixelPos))) ){\
  1153.   _setPixel(pixelPos);\
  1154.   if( newPos[0] > 0 ){\
  1155.    if( _comparePixel(_getPixel(pixelPos - 4)) ){\
  1156.    if( !found_left_border ){\
  1157.     pixelStack.push( [newPos[0] - 1, newPos[1]] );\
  1158.     found_left_border == 1;\
  1159.    }\
  1160.   }\
  1161.   else if( found_left_border ){\
  1162.     found_left_border = false;\
  1163.    }\
  1164.   }\
  1165.   if( newPos[0] < xsize-1 ){\
  1166.    if( _comparePixel(_getPixel(pixelPos + 4)) ){\
  1167.     if( !found_right_border){\
  1168.      pixelStack.push( [newPos[0] + 1, newPos[1]] );\
  1169.      found_right_border == 1;\
  1170.     }\
  1171.    }\
  1172.    else if(found_right_border){\
  1173.      found_right_border = false;\
  1174.     }\
  1175.    }\
  1176.   pixelPos += xsize * 4;\
  1177.  }\
  1178. }\
  1179. var _canvas = create_canvas%d(filltoborder_cnt,xsize,ysize);\
  1180. filltoborder_cnt++;\
  1181. var _ctx = _canvas.getContext(\"2d\");\
  1182. _ctx.putImageData(image, 0, 0);\
  1183. ctx.restore();\
  1184. };",canvas_root_id,canvas_root_id,canvas_root_id);
  1185.  
  1186. }
  1187.  
  1188. void add_js_text(FILE *js_include_file,int canvas_root_id,int font_size,char *font_family,char *font_color,double stroke_opacity,int use_rotate,int angle,int use_translate,int translate_x,int translate_y){
  1189. fprintf(js_include_file,"\n<!-- begin command userdraw text -->\n\
  1190. canvas_div.addEventListener(\"keydown\",user_text,false);\
  1191. var context_userdraw = canvas_userdraw.getContext(\"2d\");\
  1192. var font_color = \"%s\";\
  1193. var font_opacity = %f;\
  1194. var font_size = %d;\
  1195. var font_family = \"%s\";\
  1196. context_userdraw.fillStyle = \"rgba(\"+font_color+\",\"+font_opacity+\")\";\
  1197. context_userdraw.font = font_family;\
  1198. var userdraw_text = new Array();\
  1199. var txt_cnt = 0;\
  1200. var txt=\"\";\
  1201. var x_txt = 0;\
  1202. var y_txt = 0;\
  1203. var w_txt = 0;\
  1204. var typing = 0;\
  1205. var canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1206. function user_draw(evt){\
  1207. y_txt = evt.clientY - canvas_rect.top;\
  1208. x_txt = evt.clientX - canvas_rect.left;\
  1209. if( x_use_snap_to_grid == 1 ){\
  1210.   x_txt = snap_to_x(x_txt);\
  1211. };\
  1212. if( y_use_snap_to_grid == 1 ){\
  1213.   y_txt = snap_to_y(y_txt);\
  1214. };\
  1215. return;\
  1216. };\
  1217. function user_drag(evt){\
  1218. return;\
  1219. };\
  1220. function user_text(evt){\
  1221. var kc = evt.keyCode;\
  1222. if( kc== 8 || kc == 27 || kc == 46 ){\
  1223.  if(typing == 1 ){\
  1224.    w = context_userdraw.measureText(txt).width;\
  1225.    context_userdraw.clearRect(x_txt-2,y_txt-font_size-2,w+2,font_size+2);\
  1226.    txt = \"\";\
  1227.  }\
  1228.  else\
  1229.  {\
  1230.   for( var p=0 ; p < txt_cnt; p++){\
  1231.    var tmp = (userdraw_text[p]).split(\":\");\
  1232.    w = context_userdraw.measureText(tmp[0]).width;\
  1233.    var y1 = y_txt - font_size;\
  1234.    var y2 = y_txt + font_size;\
  1235.    if( tmp[1] < y2 && tmp[1] > y1){\
  1236.     var x1 = x_txt - font_size;\
  1237.     var x2 = x_txt + w;\
  1238.     if( tmp[0] < x2 && tmp[0] > x1){\
  1239.      if (confirm(\"delete this text : \"+tmp[2]+\"?\")){\
  1240.       context_userdraw.clearRect(x1,y1,x2,y2);\
  1241.       userdraw_text.splice(p,1);\
  1242.       txt_cnt--;\
  1243.       return;\
  1244.      };\
  1245.     };\
  1246.    };\
  1247.   };\
  1248.  };\
  1249. }\
  1250. else\
  1251. {\
  1252.  if( kc < 126 && kc > 40 ){\
  1253.   typing = 1;\
  1254.   txt=txt+String.fromCharCode(kc);\
  1255.   w = context_userdraw.measureText(txt).width;\
  1256.   context_userdraw.save();\
  1257.   context_userdraw.fillStyle = \"lightblue\";\
  1258.   context_userdraw.beginPath();\
  1259.   context_userdraw.rect(x_txt,y_txt-font_size,w,font_size);\
  1260.   context_userdraw.closePath();\
  1261.   context_userdraw.fill();\
  1262.   context_userdraw.restore();\
  1263.   context_userdraw.fillText(txt,x_txt,y_txt);\
  1264.  }\
  1265.  else\
  1266.  {\
  1267.   if(kc == 13 ){\
  1268.    w = context_userdraw.measureText(txt).width;\
  1269.    context_userdraw.clearRect(x_txt,y_txt-font_size,w,font_size);\
  1270.    context_userdraw.fillText(txt,x_txt,y_txt);\
  1271.    userdraw_text[txt_cnt] = x_txt+\":\"+y_txt+\":\"+txt;\
  1272.    txt=\"\";\
  1273.    w = 0;\
  1274.    txt_cnt++;\
  1275.    typing = 0;\
  1276.    return;\
  1277.   };\
  1278.  };\
  1279. };\
  1280. };",font_color,stroke_opacity,font_size,font_family);
  1281.  
  1282. }
  1283.  
  1284.  
  1285.  
  1286. /* GNU libmatheval library for evaluating mathematical functions. */
  1287. char *eval(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int plotsteps,int precision){
  1288.     void *f;
  1289.     double x;
  1290.     double y;
  1291.     int X;
  1292.     int i = 0;
  1293.     int xstep =(int)(xsize/plotsteps);
  1294.     double a = (xmax - xmin)/xsize;
  1295.     f = evaluator_create(fun);
  1296.     assert (f);
  1297.     if( f == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;}
  1298.     /* we supply the true x/y values...draw_curve() will convert these (x:y) to pixels : used for pan/scale */
  1299.     double xydata[MAX_BUFFER];/* hmmm */
  1300.     for ( X = 0 ;X < xsize ; X = X+xstep ){
  1301.         x = (double) (X*a + xmin);
  1302.         if( i < MAX_BUFFER - 2){
  1303.             y = evaluator_evaluate_x(f, x);
  1304.             if(y < 4*ymax && y > 4*ymin ){
  1305.                 xydata[i++] = x;
  1306.                 xydata[i++] = y;
  1307.             }
  1308.         }
  1309.         else
  1310.         {
  1311.             canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps or some other means to reduce the amount of data... ");
  1312.         }
  1313.     }
  1314.     evaluator_destroy(f);
  1315.     return double_xy2js_array(xydata,i,find_number_of_digits(precision));
  1316. }
  1317. /* plot parametric function */
  1318. char *eval_parametric(int xsize,int ysize,char *fun1,char* fun2,double xmin,double xmax,double ymin,double ymax, double tmin,double tmax,int plotsteps,int precision){
  1319.     void *fx;
  1320.     void *fy;
  1321.     double t;
  1322.     int i = 0;
  1323.     double tstep = (tmax-tmin)/plotsteps;
  1324.     fx = evaluator_create(fun1);
  1325.     fy = evaluator_create(fun2);
  1326.     assert(fx);
  1327.     assert(fy);
  1328.     if( fx == NULL || fy == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;}
  1329.     char *names[] = { "t" };
  1330.     double values[1];
  1331.     /* we supply the true x/y values...draw_curve() will convert these (x:y) to pixels : used for pan/scale */
  1332.     double xydata[MAX_BUFFER];/* hmmm */
  1333.     double x; /* real x-values */
  1334.     double y; /* real y-values */
  1335.     for( t = tmin ;t <= tmax ; t = t + tstep ){
  1336.         if( i < MAX_BUFFER - 2 ){
  1337.             values[0] = t;
  1338.             y = evaluator_evaluate(fy, 1, names, values);
  1339.             if(y > 4*ymin && y < 4*ymax){
  1340.                 x = evaluator_evaluate(fx, 1, names, values);
  1341.                 xydata[i++] = x;
  1342.                 xydata[i++] = y;
  1343.             }  
  1344.         }
  1345.         else
  1346.         {
  1347.             canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps or some other means to reduce the amount of data... ");
  1348.         }
  1349.     }
  1350.     evaluator_destroy(fx);
  1351.     evaluator_destroy(fy);
  1352.     return double_xy2js_array(xydata,i,find_number_of_digits(precision));
  1353. }
  1354.  
  1355. char *double_xy2js_array(double xy[],int len,int decimals){
  1356.  /*
  1357.     1,2,3,4,5,6,7,8 --> [1,3,5,7],[2,4,6,8]
  1358.     int xy[] is already checked for errors or overflow in "get_real()"
  1359.     just to be sure we double check the size of "temp"
  1360. */
  1361.     char temp[MAX_BUFFER], *string;
  1362.     char *tmp = my_newmem(16);/* <= 9999999999999999  */
  1363.     memset(temp,'\0',MAX_BUFFER);/* clear memory */
  1364.     int i;int space_left;
  1365.     temp[0] = '[';/* start js-array */
  1366.     for(i = 0; i < len;i = i + 2){ /*  x_points[] */
  1367.         if(i == len - 2){sprintf(tmp, "%.*f",decimals, xy[i]);}else{sprintf(tmp, "%.*f,",decimals,xy[i]);}
  1368.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  1369.         if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \n ");}
  1370.     }
  1371.     strncat(temp,"],[",3); /* close js x_values array and start new */
  1372.     for(i = 1; i < len;i = i + 2){ /* y_points */
  1373.         if(i == len - 1){ sprintf(tmp, "%.*f",decimals,xy[i]);}else{sprintf(tmp, "%.*f,",decimals,xy[i]);}
  1374.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  1375.         if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \n");}
  1376.     }
  1377.     strncat(temp,"]",1);
  1378.     string=(char *)my_newmem(sizeof(temp));
  1379.     snprintf(string,sizeof(temp),"%s",temp);
  1380.     return string;
  1381. }
  1382.  
  1383. char *xy2js_array(int xy[],int len){
  1384.  /*
  1385.     1,2,3,4,5,6,7,8 --> [1,3,5,7],[2,4,6,8]
  1386.     int xy[] is already checked for errors or overflow in "get_real()"
  1387.     just to be sure we double check the size of "temp"
  1388. */
  1389.     char temp[MAX_BUFFER], *string;
  1390.     char *tmp = my_newmem(16);/* <= 9999999999999999  */
  1391.     memset(temp,'\0',MAX_BUFFER);/* clear memory */
  1392.     int i;int space_left;
  1393.     temp[0] = '[';/* start js-array */
  1394.     for(i = 0; i < len;i = i + 2){ /*  x_points[] */
  1395.         if(i == len - 2){sprintf(tmp, "%d", xy[i]);}else{sprintf(tmp, "%d,", xy[i]);}
  1396.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  1397.         if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \n ");}
  1398.     }
  1399.     strncat(temp,"],[",3); /* close js x_values array and start new */
  1400.     for(i = 1; i < len;i = i + 2){ /* y_points */
  1401.         if(i == len - 1){ sprintf(tmp, "%d", xy[i]);}else{sprintf(tmp, "%d,", xy[i]);}
  1402.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  1403.         if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \n");}
  1404.     }
  1405.     strncat(temp,"]",1);
  1406.     string=(char *)my_newmem(sizeof(temp));
  1407.     snprintf(string,sizeof(temp),"%s",temp);
  1408.     return string;
  1409. }
  1410.  
  1411. char *data2js_array(int data[],int len){
  1412.  /*
  1413.     1,2,3,4,5,6,7,8 --> [1,2,3,4,5,6,7,8]
  1414.     int data[] is already checked for errors or overflow in "get_real()"
  1415.     just to be sure we double check the size of "temp"
  1416. */
  1417.     char temp[MAX_BUFFER], *string;
  1418.     char *tmp = my_newmem(16);/* <= 9999999999999999  */
  1419.     memset(temp,'\0',MAX_BUFFER);/* clear memory */
  1420.     int i;int space_left;
  1421.     temp[0] = '[';/* start js-array */
  1422.     for(i = 0; i < len; i++){
  1423.         if(i == len - 1){sprintf(tmp, "%d", data[i]);}else{sprintf(tmp, "%d,", data[i]);}
  1424.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  1425.         if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \n ");}
  1426.     }
  1427.     strncat(temp,"]",1);
  1428.     string=(char *)my_newmem(sizeof(temp));
  1429.     snprintf(string,sizeof(temp),"%s",temp);
  1430.     return string;
  1431. }
  1432. void add_drag_code(FILE *js_include_file,int canvas_cnt,int canvas_root_id){
  1433. /* in drag& drop / onclick library:
  1434.     obj_type = 1 == rect
  1435.     obj_type = 2 == point / points (do not scale with zoom)
  1436.     obj_type = 3 == ellipse
  1437.     obj_type = 4 == polyline / segment /line / vline / hline
  1438.     obj_type = 5 == closed path (polygon)
  1439.     obj_type = 6 == roundrect
  1440.     obj_type = 7 == crosshair / crosshairs
  1441.     obj_type = 8 == arrow
  1442.     obj_type = 9 == curve
  1443.     obj_type = 10== arrow2
  1444.     obj_type = 11== parallel  (no drag or onclick)
  1445.     obj_type = 12== arc
  1446.     obj_type = 13== circle (will scale on zoom)
  1447.     obj_type = 14== text (will not scale or pan on zoom)
  1448.     obj_type = 15== animated point on curve
  1449. */
  1450. fprintf(js_include_file,"\n<!-- begin drag_drop_onclick shape library -->\n\
  1451. function Shape(click_cnt,onclick,direction,type,x,y,w,h,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1,use_rotate,angle,text,font_size,font_family,use_affine,affine_matrix){\
  1452. this.text = text || 0;\
  1453. this.font_size = font_size || 12;\
  1454. if( font_family.indexOf('px') > 0 ){this.font_family = font_family;}else{this.font_family = this.font_size+'px Ariel';};\
  1455. this.use_rotate = use_rotate || 0;\
  1456. this.angle = angle*(Math.PI/180) || 0;\
  1457. this.use_affine = use_affine || 0;\
  1458. this.affine_matrix = affine_matrix || [1,0,0,1,0,0];\
  1459. this.click_cnt = click_cnt || 1;\
  1460. this.onclick = onclick || 0;\
  1461. this.direction = direction || 0;\
  1462. this.type = type || 1;\
  1463. this.xorg = x;\
  1464. this.yorg = y;\
  1465. this.x = [x.length];\
  1466. this.y = [x.length];\
  1467. this.w = [x.length];\
  1468. this.h = [x.length];\
  1469. for(var p=0;p<x.length;p++){\
  1470.  this.x[p] = x2px(x[p]);\
  1471.  this.y[p] = y2px(y[p]);\
  1472.  if( p > w.length){\
  1473.    this.w[p] = w[0];\
  1474.    this.h[p] = h[0];\
  1475.  }\
  1476.  else\
  1477.  {\
  1478.    this.w[p] = w[p];\
  1479.    this.h[p] = h[p];\
  1480.  }\
  1481. };\
  1482. this.line_width = line_width || 30;\
  1483. this.stroke_opacity = stroke_opacity || 1.0;\
  1484. this.stroke_color = \"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\" || '#FF0000';\
  1485. this.fill_opacity = fill_opacity || 1.0;\
  1486. this.fill_color = \"rgba(\"+fill_color+\",\"+fill_opacity+\")\" || '#FF0000';\
  1487. this.use_filled = use_filled || 0;\
  1488. this.use_dashed = use_dashed || 0;\
  1489. this.dashtype0 = dashtype0 || 4;\
  1490. this.dashtype1 = dashtype1 || 4;\
  1491. };\
  1492. Shape.prototype.draw = function(ctx)\
  1493. {\
  1494. ctx.lineWidth = this.line_width;\
  1495. ctx.strokeStyle = this.stroke_color;\
  1496. ctx.fillStyle = this.fill_color;\
  1497. ctx.lineJoin = \"round\";\
  1498. ctx.save();\
  1499. if(this.use_rotate == 1){\
  1500. var x_c = x2px(0);\
  1501. var y_c = y2px(0);\
  1502. ctx.translate(x_c,y_c);\
  1503. ctx.rotate(this.angle);ctx.translate(-x_c,-y_c);};\
  1504. if( this.use_affine == 1 ){\
  1505.  ctx.setTransform(this.affine_matrix[0],this.affine_matrix[1],this.affine_matrix[2],this.affine_matrix[3],this.affine_matrix[4],this.affine_matrix[5]);\
  1506. };\
  1507. ctx.beginPath();\
  1508. switch(this.type){\
  1509.  case 1: ctx.rect(this.x[0], this.y[0], this.x[1]-this.x[0], this.y[2] - this.y[0]);break;\
  1510.  case 2: ctx.arc(this.x[0],this.y[0],this.w[0],0,2*Math.PI,false);break;\
  1511.  case 3: var w = 0.5*(scale_x_radius(this.w[0]));var h = 0.5*(scale_y_radius(this.h[0]));ctx.beginPath();ctx.moveTo(this.x[0], this.y[0] - h);ctx.bezierCurveTo(this.x[0] + w, this.y[0] - h,this.x[0] + w, this.y[0] + h,this.x[0],this.y[0] + h);ctx.bezierCurveTo(this.x[0] - w, this.y[0] + h,this.x[0] - w, this.y[0] - h,this.x[0], this.y[0] - h);if(this.use_filled == 1){ ctx.fillStyle = this.fill_color; ctx.fill(); }; ctx.closePath();break;\
  1512.  case 4: for(var p = 0; p < this.x.length - 1;p++){ctx.moveTo(this.x[p], this.y[p]);ctx.lineTo(this.x[p+1],this.y[p+1]);};break;\
  1513.  case 5: ctx.moveTo(this.x[0], this.y[0]);for(var p = 1; p < this.x.length;p++){ctx.lineTo(this.x[p],this.y[p]);};ctx.lineTo(this.x[0],this.y[0]);break;\
  1514.  case 6: var w = this.x[1] - this.x[0];var h = this.y[1] - this.y[0];var r = this.w[0];ctx.beginPath();ctx.moveTo(this.x[0] + r, this.y[0]);ctx.lineTo(this.x[0] + w - r, this.y[0]);ctx.quadraticCurveTo(this.x[0] + w, this.y[0], this.x[0] + w, this.y[0] + r);ctx.lineTo(this.x[0] + w, this.y[0] + h - r);ctx.quadraticCurveTo(this.x[0] + w, this.y[0] + h, this.x[0] + w - r, this.y[0] + h);ctx.lineTo(this.x[0] + r, this.y[0] + h);ctx.quadraticCurveTo(this.x[0], this.y[0] + h, this.x[0], this.y[0] + h - r);ctx.lineTo(this.x[0], this.y[0] + r);ctx.quadraticCurveTo(this.x[0], this.y[0], this.x[0] + r, this.y[0]);ctx.closePath();break;\
  1515.  case 7: ctx.moveTo(this.x[0]-this.w[0],this.y[0]-this.h[0]);ctx.lineTo(this.x[0]+this.w[0],this.y[0]+this.h[0]);ctx.moveTo(this.x[0]-this.w[0],this.y[0]+this.h[0]);ctx.lineTo(this.x[0]+this.w[0],this.y[0]-this.h[0]);break;\
  1516.  case 8: var dx;var dy;var len;var arrow_head = this.w[0];for(var p = 0; p < this.x.length - 1;p++){ctx.restore();ctx.save();dx = this.x[p+1] - this.x[p];dy = this.y[p+1] - this.y[p];len = Math.sqrt(dx*dx+dy*dy);ctx.translate(this.x[p+1],this.y[p+1]);ctx.rotate(Math.atan2(dy,dx));ctx.lineCap = \"round\";ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(-len,0);ctx.closePath();ctx.stroke();ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(-1*arrow_head,-0.5*arrow_head);ctx.lineTo(-1*arrow_head, 0.5*arrow_head);ctx.closePath();ctx.fill();};break;\
  1517.  case 9: ctx.moveTo(this.x[0], this.y[0]);for(var p = 1; p < this.x.length - 1;p++){if( Math.abs(this.y[p] - this.y[p-1]) < ysize && Math.abs(this.y[p+1] - this.y[p]) < ysize ){ctx.lineTo(this.x[p],this.y[p]);}else{ctx.moveTo(this.x[p],this.y[p]);};};break;\
  1518.  case 10: var dx;var dy;var len;ctx.restore();ctx.save();dx = this.x[1] - this.x[0];dy = this.y[1] - this.y[0];len = Math.sqrt(dx*dx+dy*dy);ctx.translate(this.x[1],this.y[1]);ctx.rotate(Math.atan2(dy,dx));ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(-len,0);ctx.closePath();ctx.stroke();ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(-1*this.w[0],-1*this.w[0]);ctx.lineTo(-1*this.w[0],this.w[0]);ctx.closePath();ctx.lineCap = \"round\";ctx.fill();ctx.restore();ctx.save();ctx.translate(this.x[0],this.y[0]);ctx.rotate(Math.atan2(dy,dx));ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(this.w[0],-0.5*this.w[0]);ctx.lineTo(this.w[0], 0.5*this.w[0]);ctx.closePath();ctx.lineCap = \"round\";ctx.fill(); break;\
  1519.  case 11: var x1 = this.x[0];var y1 = this.y[0];var x2 = this.x[1];var y2 = this.y[1];var dx = this.x[2];var dy = this.y[2];var n  = this.w[0];for(var p = 0 ; p < n ; p++ ){ctx.beginPath();ctx.moveTo(x1,y1);ctx.lineTo(x2,y2);ctx.stroke();x1 = x1 + dx;y1 = y1 + dy;x2 = x2 + dx;y2 = y2 + dy;ctx.closePath();};break;\
  1520.  case 12: ctx.save();var start;var end;if(this.h[0] < this.h[1]){start = this.h[0];end = this.h[1]}else{start = this.h[1];end = this.w[0];};start=360-start;end=360-end;var r = this.w[0];ctx.arc(this.x[0], this.y[0], r, start*(Math.PI / 180), end*(Math.PI / 180),true);if(this.use_filled){ctx.lineTo(this.x[0],this.y[0]);ctx.fill();};break;\
  1521.  case 13: ctx.arc(this.x[0],this.y[0],scale_x_radius(this.w[0]),0,2*Math.PI,false);break;\
  1522.  case 14: ctx.font = this.font_family ;ctx.fillText(this.text,this.x[0],this.y[0]);break;\
  1523.  case 15: var animate_canvas = create_canvas%d(%d,xsize,ysize);var animate_ctx = animate_canvas.getContext(\"2d\");animate_ctx.moveTo(this.x[0], this.y[0]);animate_ctx.strokeStyle = this.stroke_color;animate_ctx.fillStyle = this.fill_color;animate_ctx.lineWidth = this.line_width;var p=0;var X = this.x;var Y = this.y;var fps=10;var W = this.w[0];var W2 = 0.5*W;use_filled = true;function animate(){animate_ctx.fillRect(X[p]-W2,Y[p]-W2,W,W);setTimeout(function(){requestAnimationFrame(animate);}, 1000 / fps);p++;if(p == X.length - 1){p = 0;animate_ctx.clearRect(0,0,xsize,ysize);};};animate();break;\
  1524.  default: alert(\"draw primitive unknown\");break;\
  1525. };\
  1526. if(this.use_filled == 1){ ctx.fill();}\
  1527. if(this.use_dashed == 1 ){if( ctx.setLineDash ){ ctx.setLineDash([this.dashtype0,this.dashtype1]);}else{ ctx.mozDash = [this.dashtype0,this.dashtype1];};};\
  1528. ctx.stroke();\
  1529. ctx.restore();\
  1530. };\
  1531. Shape.prototype.contains = function(mx, my){\
  1532. var marge = 2*this.line_width;\
  1533. switch(this.type){\
  1534.  case 1: for(var p = 0 ; p < this.x.length; p++ ){if( mx < this.x[p] + marge &&  mx > this.x[p] - marge ){if( my < this.y[p]+marge && my > this.y[p] - marge ){return p;};};};break;\
  1535.  case 2: for(var p = 0 ; p < this.x.length; p++ ){if( Math.abs(distance(this.x[p],this.y[p],mx,my) ) < this.w[p] + marge ){return p;break;};};break;\
  1536.  case 3: for(var p = 0 ; p < this.x.length; p++ ){if( Math.abs(distance(this.x[p],this.y[p],mx,my) ) < scale_x_radius(this.w[p]) + marge ){return p;break;};};break;\
  1537.  case 4: var diff;var q;var r;for(var p = 0 ; p < this.x.length-1; p = p+2  ){if( ((this.x[p+1] - this.x[p]) != 0)  && ((this.y[p+1]-this.y[p]) != 0) ){r = (this.y[p+1]-this.y[p])/(this.x[p+1]-this.x[p]);q = this.y[p] - (r)*(this.x[p]);diff = distance_to_line(r,q,mx,my);}else{if( (this.y[p+1]-this.y[p]) != 0 ){diff = Math.abs(this.x[p] - mx);}else{diff = Math.abs(this.y[p] - my);};};if( diff  < marge ){ return p;};}; break;\
  1538.  case 6: for(var p = 0 ; p < this.x.length; p++ ){if( mx < this.x[p] + marge &&  mx > this.x[p] - marge ){if( my < this.y[p]+marge && my > this.y[p] - marge ){return p;};};};break;\
  1539.  case 7: for(var p = 0 ; p < this.x.length; p++ ){if( (this.x[p] - this.w[p] <= mx) && (this.x[p] + this.w[p] >= mx) &&  (this.y[p] - this.h[p] <= my) && (this.y[p] + this.h[p] >= my) ){return p;};};break;\
  1540.  case 8: var diff;var q;var r;for(var p = 0 ; p < this.x.length-1; p = p+2  ){if( ((this.x[p+1] - this.x[p]) != 0)  && ((this.y[p+1]-this.y[p]) != 0) ){r = (this.y[p+1]-this.y[p])/(this.x[p+1]-this.x[p]);q = this.y[p] - (r)*(this.x[p]);diff = distance_to_line(r,q,mx,my);}else{if( (this.y[p+1]-this.y[p]) != 0 ){diff = Math.abs(this.x[p] - mx);}else{diff = Math.abs(this.y[p] - my);};};if( diff  < marge ){ return p;};}; break;\
  1541.  case 9: for(var p = 0 ; p < this.x.length; p++ ){if( (this.x[p] - this.line_width <= mx) && (this.x[p] + this.w[p] + this.line_width >= mx) &&  (this.y[p] - this.line_width <= my) && (this.y[p] + this.h[p] +this.line_width  >= my) ){return p;};};break;\
  1542.  case 11: break;\
  1543.  case 12: break;\
  1544.  case 13: for(var p = 0 ; p < this.x.length; p++ ){if( Math.abs(distance(this.x[p],this.y[p],mx,my) ) < scale_x_radius(this.w[p]) + marge ){return p;break;};};break;\
  1545.  case 14: for(var p = 0 ; p < this.x.length; p++ ){if(this.y[p] < my + 0.5*(this.font_size) && this.y[p] > my - 0.5*(this.font_size)){var w = parseInt(0.8*(this.font_size)*((this.text).length));if(this.x[p] < mx + w && this.x[p] > mx - w ){ return p;break;};};};break;\
  1546.  default: for(var p = 0 ; p < this.x.length; p++ ){if( (this.x[p] - this.line_width <= mx) && (this.x[p] + this.w[p] + this.line_width >= mx) &&  (this.y[p] - this.line_width <= my) && (this.y[p] + this.h[p] +this.line_width  >= my) ){return p;};};break;\
  1547. };\
  1548. return -1;\
  1549. };\
  1550. var reply = [];\
  1551. \
  1552. function CanvasState(canvas,container_div){\
  1553. this.canvas = canvas;\
  1554. this.width = canvas.width;\
  1555. this.height = canvas.height;\
  1556. var ctx = canvas.getContext(\"2d\");\
  1557. this.ctx = ctx;\
  1558. this.valid = false;\
  1559. this.shapes = [];\
  1560. this.moved = [];\
  1561. this.dragging = false;\
  1562. this.selection = null;\
  1563. var myState = this;\
  1564. container_div.addEventListener( 'mouseup'    , function(e){myState.dragging = false;}, true);\
  1565. container_div.addEventListener( 'mousemove'  , mousemove,false);\
  1566. container_div.addEventListener( 'mousedown'  , mousedown,false);\
  1567. container_div.addEventListener( 'touchend'   , function(e) {myState.dragging = false;}, true);\
  1568. container_div.addEventListener( 'selectstart', function(e) { e.preventDefault(); return false; }, false);\
  1569. container_div.addEventListener( 'touchstart' , mousedown,false);\
  1570. container_div.addEventListener( 'touchmove'  , mousemove,false);\
  1571. function mousedown(e){\
  1572.  var mouse = myState.getMouse(e);\
  1573.  var mx = mouse.x;\
  1574.  var my = mouse.y;\
  1575.  if( use_pan_and_zoom == 1 && my > ysize - 15){\
  1576.   check_zoom_or_pan(mx);\
  1577.  }\
  1578.  else\
  1579.  {\
  1580.   var shapes = myState.shapes;\
  1581.   var l = shapes.length;\
  1582.   var chk = -1;\
  1583.   for(var i=0;i<l;i++){\
  1584.    chk = shapes[i].contains(mx, my);\
  1585.    if ( chk != -1 ){\
  1586.     if( myState.moved[shapes[i].click_cnt] != 1){\
  1587.      myState.moved[shapes[i].click_cnt] = 1;\
  1588.      myState.x_start = shapes[i].x[chk];\
  1589.      myState.y_start = shapes[i].y[chk];\
  1590.     };\
  1591.     var org_line_width = shapes[i].line_width;\
  1592.     var org_font_family = shapes[i].font_family;\
  1593.     var org_stroke_opacity = shapes[i].stroke_opacity;\
  1594.     myState.chk = chk;\
  1595.     myState.selection = shapes[i];\
  1596.     myState.valid = false;\
  1597.     switch(shapes[i].onclick){\
  1598.      case 0: myState.dragging = false;break;\
  1599.      case 1: myState.selection.line_width = 3*org_line_width;myState.selection.font_family = \"bold italic \"+myState.selection.font_size+\"px Courier\";myState.dragging = false;myState.draw();reply[0] = myState.selection.click_cnt;myState.selection.line_width = org_line_width;myState.selection.font_family = org_font_family;break;\
  1600.      case 2: myState.dragging = true;break;\
  1601.      default:break;\
  1602.     };\
  1603.     return;\
  1604.    };\
  1605.   };\
  1606.  };\
  1607.  myState.selection = null;\
  1608.  myState.valid = true;\
  1609.  return;\
  1610. };\
  1611. function mousemove(e){\
  1612.  if(myState.dragging){\
  1613.   var mouse = myState.getMouse(e);\
  1614.   var dx=mouse.x - myState.selection.x[myState.chk];\
  1615.   var dy=mouse.y - myState.selection.y[myState.chk];\
  1616.   switch(myState.selection.direction){\
  1617.    case 0: myState.selection = move(myState.selection,dx,dy);break;\
  1618.    case 1: myState.selection = move(myState.selection,dx,0);break;\
  1619.    case 2: myState.selection = move(myState.selection,0,dy); break;\
  1620.   };\
  1621.   reply[myState.selection.click_cnt] = \"object number=\"+myState.selection.click_cnt+\" moved  from (\"+px2x(myState.x_start)+\":\"+px2y(myState.y_start)+\") to (\"+px2x(myState.selection.x[myState.chk])+\":\"+px2y(myState.selection.y[myState.chk])+\")\\n\";\
  1622.   myState.valid = false;\
  1623.  };\
  1624. };\
  1625. function check_zoom_or_pan(x){\
  1626.  var key = -1;\
  1627.  for(p = 15 ; p < 106 ; p = p+15){\
  1628.    key++;\
  1629.    if(x > xsize - p){start_canvas%d(key);return;}\
  1630.  }\
  1631.  return;\
  1632. };\
  1633. this.interval = 30;\
  1634. setInterval(function() { myState.draw(); }, myState.interval);\
  1635. };\
  1636. CanvasState.prototype.addShape = function(shape){\
  1637. this.shapes.push(shape);\
  1638. this.valid = false;\
  1639. };\
  1640. CanvasState.prototype.clear = function(){\
  1641. this.ctx.clearRect(0, 0, this.width, this.height);\
  1642. };\
  1643. CanvasState.prototype.draw = function(){\
  1644. if(this.valid == false ){\
  1645.  var shapes = this.shapes;\
  1646.  this.clear();\
  1647.  var l = shapes.length;var shape;\
  1648.  for(var i = 0; i < l; i++){\
  1649.   shape = shapes[i];\
  1650.   shape.draw(this.ctx);\
  1651.  };\
  1652.  this.valid = true;\
  1653. }\
  1654. };\
  1655. CanvasState.prototype.Zoom = function(xmin,xmax,ymin,ymax){\
  1656. (this.ctx).clearRect(0,0,this.width,this.height);\
  1657. for(var i = 0; i < this.shapes.length ; i++){\
  1658.  for(var p = 0 ; p < this.shapes[i].x.length;p++){\
  1659.   this.shapes[i].x[p] = x2px(this.shapes[i].xorg[p]);\
  1660.   this.shapes[i].y[p] = y2px(this.shapes[i].yorg[p]);\
  1661.  }\
  1662.  this.valid = false;\
  1663.  this.shapes[i].draw(this.ctx);\
  1664. };\
  1665. reply = new Array();\
  1666. };\
  1667. CanvasState.prototype.getMouse = function(e){\
  1668. var element = this.canvas, offsetX = 0,offsetY = 0;\
  1669. while( ( element = element.offsetParent) ){\
  1670. offsetX += element.offsetLeft;\
  1671. offsetY += element.offsetTop;\
  1672. }\
  1673. var mx = e.clientX - offsetX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);\
  1674. var my = e.clientY - offsetY + (document.documentElement.scrollTop ? document.documentElement.scrollTop :document.body.scrollTop);\
  1675. return {x: mx, y: my};\
  1676. };\
  1677. function read_dragdrop(){\
  1678. var moved_objects = [];var c = 0;\
  1679. for(var p=0 ; p<reply.length ; p++){\
  1680. if(reply[p]){moved_objects[c] = reply[p];c++}\
  1681. }\
  1682. return moved_objects;\
  1683. };\
  1684. this.read_dragdrop = read_dragdrop;\
  1685. var obj = create_canvas%d(%d,xsize,ysize);\
  1686. var container_div = document.getElementById(\"canvas_div%d\");\
  1687. var dragstuff = new CanvasState(obj,container_div);",canvas_root_id,ANIMATE_CANVAS,canvas_root_id,canvas_root_id,DRAG_CANVAS,canvas_root_id);
  1688. }
  1689.  
  1690. void add_js_mouse(FILE *js_include_file,int canvas_cnt,int canvas_root_id,int precision,char *stroke_color,int font_size,double stroke_opacity){
  1691. fprintf(js_include_file,"\n<!-- begin command mouse on current canvas -->\n\
  1692. function use_mouse_coordinates(){\
  1693. var current_canvas = create_canvas%d(%d,xsize,ysize);\
  1694. var current_context = current_canvas.getContext(\"2d\");\
  1695. current_context.clearRect(0,0,xsize,ysize);\
  1696. current_canvas.addEventListener(\"mousemove\",show_coordinate%d,false);\
  1697. current_canvas.addEventListener(\"touchmove\",show_coordinate%d,false);\
  1698. var prec = Math.log(%d)/(Math.log(10));\
  1699. function show_coordinate%d(evt){\
  1700.  var canvas_rect = (current_canvas).getBoundingClientRect();\
  1701.  var x = evt.clientX - canvas_rect.left;\
  1702.  var y = evt.clientY - canvas_rect.top;\
  1703.  var m_data = \"(\"+(px2x(x)).toFixed(prec)+\":\"+(px2y(y)).toFixed(prec)+\")\";\
  1704.  var s = parseInt(0.8*%d*(m_data.toString()).length);\
  1705.  current_context.font = \"%dpx Ariel\";\
  1706.  current_context.fillStyle = \"rgba(%s,%f)\";\
  1707.  current_context.clearRect(0,0,s,1.2*%d);\
  1708.  current_context.fillText(m_data,0,%d);\
  1709. };\
  1710. };",canvas_root_id,MOUSE_CANVAS,canvas_root_id,canvas_root_id,precision,canvas_root_id,font_size,font_size,stroke_color,stroke_opacity,font_size,font_size);
  1711.  
  1712. }
  1713.  
  1714. /*
  1715. add a table with 2 textarea's labeled 'x' 'y' ( or 'xlabel' 'ylabel' if defined)
  1716. add two buttons: OK and NOK (OK draws; NOK will delete last item pair from userdraw_x / userdraw_y array's
  1717. */
  1718. void add_textarea_xy(FILE *js_include_file, int canvas_root_id){
  1719. fprintf(js_include_file,"\n<!-- begin add_textarea_xy -->\n\
  1720. var userinput_xy_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1721. var label_x = \"x\";var label_y = \"y\";\
  1722. if( typeof xaxislabel !== 'undefined' ){label_x = xaxislabel;}\
  1723. if( typeof yaxislabel !== 'undefined' ){label_y = yaxislabel;}\
  1724. userinput_xy_div.innerHTML=\"<table style=\'border:1px solid black;background-color:#ffffa0\' ><tr><td><em>\"+label_x+\"</em></td><td><em>\"+label_y+\"</em></td><td><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;'/></td></tr><tr><td><textarea rows='5' cols='2' id='userinput_x' style='text-align:center;color:blue;background-color:orange;' ></textarea></td><td><textarea rows='5' cols='2' id='userinput_y' style='text-align:center;color:blue;background-color:orange;' ></textarea></td><td>&nbsp;</td></tr></table>\";\
  1725. var update_button = document.getElementById(\"update_button\");\
  1726. var delete_button = document.getElementById(\"delete_button\");\
  1727. update_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  1728. delete_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);",canvas_root_id);
  1729. }
  1730.  
  1731. /*
  1732. adds 2 inputfields (x:y) and 'ok' | 'nok' button
  1733. these are used for user drawing with inputfields...
  1734. */
  1735. void add_input_xy(FILE *js_include_file, int canvas_root_id){
  1736. fprintf(js_include_file,"\n<!-- begin add_input_xy -->\n\
  1737. var userinput_xy_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1738. var label_x = \"x\";var label_y = \"y\";\
  1739. userinput_xy_div.innerHTML=\"<span><b>( <input type='text' size='6' value='' id='userinput_x' style='text-align:center;color:blue;background-color:orange;' /> : <input type='text' size='6' value='' id='userinput_y' style='text-align:center;color:blue;background-color:orange;' /> )</b><input id='update_button' type='button' value='OK' onclick=''  style='color:red;background-color:lightblue;'/><input id='delete_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'/></span> \";\
  1740. var update_button = document.getElementById(\"update_button\");\
  1741. var delete_button = document.getElementById(\"delete_button\");\
  1742. update_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  1743. delete_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);",canvas_root_id);
  1744. }
  1745.  
  1746. /* adds 4 inputfields (x1:y1) --- (x2:y2) and 'ok' + 'nok' button */
  1747. void add_input_x1y1x2y2(FILE *js_include_file, int canvas_root_id){
  1748. fprintf(js_include_file,"\n<!-- begin add_input_x1y1x2y2 -->\n\
  1749. var userinput_xy_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1750. userinput_xy_div.innerHTML=\"<span><b>( <input type='text' size='6' value='' id='userinput_x1' style='text-align:center;color:blue;background-color:orange;'/> : <input type='text' size='6' value='' id='userinput_y1' style='text-align:center;color:blue;background-color:orange;' /> ) ----- ( <input type='text' size='6' value='' id='userinput_x2' style='text-align:center;color:blue;background-color:orange;' /> : <input type='text' size='6' value='' id='userinput_y2' style='text-align:center;color:blue;background-color:orange;'/> )</b><input id='update_button' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;'/><input id='delete_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'/></span> \";\
  1751. var update_button = document.getElementById(\"update_button\");\
  1752. var delete_button = document.getElementById(\"delete_button\");\
  1753. update_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  1754. delete_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);",canvas_root_id);
  1755. }
  1756.  
  1757. /* adds 3 inputfields Center (x:y) Radius r and 'ok'+'nok' buttons */
  1758. void add_input_xyr(FILE *js_include_file, int canvas_root_id){
  1759. fprintf(js_include_file,"\n<!-- begin add_input_xyr -->\n\
  1760. var userinput_xy_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1761. userinput_xy_div.innerHTML=\"<span><b>Center : ( <input type='text' size='6' value='' id='userinput_x' style='text-align:center;color:blue;background-color:orange;' /> : <input type='text' size='6' value='' id='userinput_y' style='text-align:center;color:blue;background-color:orange;' /> ) Radius : <input type='text' size='6' value='' id='userinput_r' style='text-align:center;color:blue;background-color:orange;' /></b><input id='update_button' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;'/><input id='delete_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'/></span> \";\
  1762. var update_button = document.getElementById(\"update_button\");\
  1763. var delete_button = document.getElementById(\"delete_button\");\
  1764. update_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  1765. delete_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);",canvas_root_id);
  1766. }
  1767.  
  1768. /* THESE JS-FUNCTIONS COULD BE MADE LESS COPY & PASTE "PROGRAMMING" */
  1769.  
  1770. /* draw circle(s) / point(s) via 3 inputfields */
  1771. void add_input_circle(FILE *js_include_file,int type,int num){
  1772. /*
  1773. type = 0 : a point ...radius is fixed
  1774. type = 1 : a circle ... read inputfield userinput_r
  1775. num = 1 : a single point / circle
  1776. num = 2 : multiple points / circles
  1777. */
  1778. fprintf(js_include_file,"\n<!-- begin add_input_circle -->\n\
  1779. function user_redraw(t){\
  1780. var type = %d;\
  1781. var num = %d;\
  1782. var lu = userdraw_x.length;\
  1783. if( t == -1 && lu > 0){\
  1784.  userdraw_x.splice(lu-1,1);\
  1785.  userdraw_y.splice(lu-1,1);\
  1786.  if(type == 1){\
  1787.    userdraw_radius.splice(lu-1,1);\
  1788.  };\
  1789.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1790.  draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  1791.  return;\
  1792. };\
  1793. var add_x = safe_eval( document.getElementById(\"userinput_x\").value );\
  1794. var add_y = safe_eval( document.getElementById(\"userinput_y\").value );\
  1795. if( add_x != null && add_y != null ){\
  1796.  if( type == 2 ){\
  1797.   var add_r = safe_aval( document.getElementById(\"userinput_r\").value );if( add_r == null ){alert(\"illegal radius input \");return;}\
  1798.   if( num == 1 ){\
  1799.    userdraw_radius[0] = parseInt(Math.abs(xsize*(add_r)/(xmax - xmin)));\
  1800.   }\
  1801.   else\
  1802.   {\
  1803.    userdraw_radius[lu] = parseInt(Math.abs(xsize*(add_r)/(xmax - xmin)));\
  1804.   };\
  1805.  }\
  1806.  else\
  1807.  {\
  1808.    userdraw_radius[lu] = userdraw_radius[0];\
  1809.  };\
  1810.  if( num == 1 ){\
  1811.  userdraw_x[0] = x2px(add_x);\
  1812.  userdraw_y[0] = y2px(add_y);\
  1813.  }\
  1814.  else\
  1815.  {\
  1816.    userdraw_x[lu] = x2px(add_x);\
  1817.    userdraw_y[lu] = y2px(add_y);\
  1818.    xy_cnt++;\
  1819.  };\
  1820.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1821.  draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  1822. };\
  1823. return;\
  1824. };",type,num);
  1825. }
  1826. /* draw crosshairs via inputfields x/y */
  1827. void add_input_crosshair(FILE *js_include_file,int num){
  1828. fprintf(js_include_file,"\n<!-- begin add_input_crosshair -->\n\
  1829. function user_redraw(t){\
  1830. var lu = userdraw_x.length;\
  1831. if( t == -1 && lu > 0){\
  1832.  userdraw_x.splice(lu-1,1);\
  1833.  userdraw_y.splice(lu-1,1);\
  1834.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1835.  draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  1836.  return;\
  1837. };\
  1838. var add_x = safe_eval( document.getElementById(\"userinput_x\").value );\
  1839. var add_y = safe_eval( document.getElementById(\"userinput_y\").value );\
  1840. if( add_x != null && add_y != null ){\
  1841.  if( %d == 1 ){\
  1842.   userdraw_x[0] = x2px(add_x);\
  1843.   userdraw_y[0] = y2px(add_y);\
  1844.  }\
  1845.  else\
  1846.  {\
  1847.    userdraw_x[lu] = x2px(add_x);\
  1848.    userdraw_y[lu] = y2px(add_y);\
  1849.    xy_cnt++;\
  1850.  };\
  1851.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1852.  draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  1853. };\
  1854. return;\
  1855. };",num);
  1856. }
  1857.  
  1858. /* draw arrows via inputfields x/y */
  1859. void add_input_arrow(FILE *js_include_file,int num){
  1860. fprintf(js_include_file,"\n<!-- begin add_input_arrow -->\n\
  1861. function user_redraw(t){\
  1862. var lu = userdraw_x.length;\
  1863. if( t == -1 && lu > 1 ){\
  1864.  userdraw_x.splice(lu-2,2);\
  1865.  userdraw_y.splice(lu-2,2);\
  1866.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1867.  draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,use_translate,vector);\
  1868.  return;\
  1869. };\
  1870. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  1871. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  1872. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  1873. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  1874. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  1875.  if( %d == 2 ){\
  1876.    var s = userdraw_x.length;\
  1877.    userdraw_x[lu] = x2px(add_x1);\
  1878.    userdraw_y[lu] = y2px(add_y1);\
  1879.    userdraw_x[lu+1] = x2px(add_x2);\
  1880.    userdraw_y[lu+1] = y2px(add_y2);\
  1881.  }\
  1882.  else\
  1883.  {\
  1884.   userdraw_x[0] = x2px(add_x1);\
  1885.   userdraw_y[0] = y2px(add_y1);\
  1886.   userdraw_x[1] = x2px(add_x2);\
  1887.   userdraw_y[1] = y2px(add_y2);\
  1888.  };\
  1889.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1890.  draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,use_translate,vector);\
  1891. };\
  1892. return;\
  1893. };",num);
  1894. }
  1895.  
  1896. /* draw line via inputfields x/y */
  1897. void add_input_line(FILE *js_include_file,int num){
  1898. fprintf(js_include_file,"\n<!-- begin line via inputfields  -->\n\
  1899. function user_redraw(t){\
  1900. var lu = userdraw_x.length;\
  1901. if( t == -1 && lu > 1){\
  1902.  userdraw_x.splice(lu-2,2);\
  1903.  userdraw_y.splice(lu-2,2);\
  1904.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1905.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,1,0,0);\
  1906.  return;\
  1907. };\
  1908. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  1909. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  1910. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  1911. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  1912. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  1913.  if( %d == 2 ){\
  1914.    userdraw_x[lu] = x2px(add_x1);\
  1915.    userdraw_y[lu] = y2px(add_y1);\
  1916.    userdraw_x[lu+1] = x2px(add_x2);\
  1917.    userdraw_y[lu+1] = y2px(add_y2);\
  1918.  }\
  1919.  else\
  1920.  {\
  1921.   userdraw_x[0] = x2px(add_x1);\
  1922.   userdraw_y[0] = y2px(add_y1);\
  1923.   userdraw_x[1] = x2px(add_x2);\
  1924.   userdraw_y[1] = y2px(add_y2);\
  1925.  };\
  1926.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1927.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,1,0,0);\
  1928. };\
  1929. return;\
  1930. };",num);
  1931. }
  1932.  
  1933.  
  1934. /* draw polyline via inputfields x/y */
  1935. void add_input_polyline(FILE *js_include_file){
  1936. fprintf(js_include_file,"\n<!-- begin polyline_segment via inputfields -->\n\
  1937. function user_redraw(t){\
  1938. var lu = userdraw_x.length;\n\
  1939. if( t == -1 && lu > 0){\
  1940.  userdraw_x.splice(lu-1,1);\n\
  1941.  userdraw_y.splice(lu-1,1);\n\
  1942.  context_userdraw.clearRect(0,0,xsize,ysize);\n\
  1943.  draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\n\
  1944.  cnt = 1;return;\n\
  1945. };\n\
  1946. var add_x = safe_eval( document.getElementById(\"userinput_x\").value );\n\
  1947. var add_y = safe_eval( document.getElementById(\"userinput_y\").value );\n\
  1948. if(add_x != null && add_y != null ){\
  1949.  userdraw_x[lu] = x2px(add_x);\n\
  1950.  userdraw_y[lu] = y2px(add_y);\n\
  1951.  context_userdraw.clearRect(0,0,xsize,ysize);\n\
  1952.  draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\n\
  1953.  cnt = 1;\n\
  1954. };\n\
  1955. return;\n\
  1956. };");
  1957. }
  1958. /* draw segment(s) via inputfields x/y */
  1959. void add_input_segment(FILE *js_include_file,int num){
  1960. fprintf(js_include_file,"\n<!-- begin add_input_segment -->\n\
  1961. function user_redraw(t){\
  1962. var lu = userdraw_x.length;\
  1963. if( t == -1 && lu > 1){\
  1964.  userdraw_x.splice(lu-2,2);\
  1965.  userdraw_y.splice(lu-2,2);\
  1966.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1967.  draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1968.  return;\
  1969. };\
  1970. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  1971. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  1972. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  1973. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  1974. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  1975.  if( %d == 2 ){\
  1976.    var s = userdraw_x.length;\
  1977.    userdraw_x[s] = x2px(add_x1);\
  1978.    userdraw_y[s] = y2px(add_y1);\
  1979.    userdraw_x[s+1] = x2px(add_x2);\
  1980.    userdraw_y[s+1] = y2px(add_y2);\
  1981.  }\
  1982.  else\
  1983.  {\
  1984.   userdraw_x[0] = x2px(add_x1);\
  1985.   userdraw_y[0] = y2px(add_y1);\
  1986.   userdraw_x[1] = x2px(add_x2);\
  1987.   userdraw_y[1] = y2px(add_y2);\
  1988.  };\
  1989.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1990.  draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1991. };\
  1992. return;\
  1993. };",num);
  1994. }
  1995.  
  1996. /* draw polygon via 2 textarea's x/y : split into lines ! */
  1997. void add_textarea_polygon(FILE *js_include_file){
  1998. fprintf(js_include_file,"\n<!-- begin polygon via 2 textareas x / y -->\n\
  1999. function user_redraw(t){\
  2000. var lu = userdraw_x.length;\
  2001. if( t == -1 && lu > 0){\
  2002.  userdraw_x.splice(lu-1,1);\
  2003.  userdraw_y.splice(lu-1,1);\
  2004.  context_userdraw.clearRect(0,0,xsize,ysize);\
  2005.  draw_paths(context_userdraw,userdraw_x,userdraw_y,line_width,closed_path,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,use_rotate,angle,use_translate,vector);\
  2006.  cnt = 1; return;\
  2007. };\
  2008. var add_x_values = (document.getElementById(\"userinput_x\").value).split('\\n');\
  2009. var add_y_values = (document.getElementById(\"userinput_y\").value).split('\\n');\
  2010. var lx = add_x_values.length;\
  2011. var ly = add_y_values.length;\
  2012. if( lx != ly){ if(lx > ly){alert(\'x/y mismatch\\ntoo few y-values\');return}else{alert(\'x/y mismatch\\ntoo many y-values\');return}};\
  2013. var add_x;var add_y;\
  2014. for(var p = 0 ; p < lx ; p++){\
  2015.  add_x = safe_eval( add_x_values[p] );\
  2016.  add_y = safe_eval( add_y_values[p] );\
  2017.  if( add_x == null || add_y == null ){return;};\
  2018.  userdraw_x[lu+p] = x2px(add_x);\
  2019.  userdraw_y[lu+p] = y2px(add_y);\
  2020.  if(p>100){alert(\"hmmmm\");return;};\
  2021. };\
  2022. draw_paths(context_userdraw,userdraw_x,userdraw_y,line_width,closed_path,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,use_rotate,angle,use_translate,vector);\
  2023. cnt = 1;\
  2024. return;\
  2025. };");
  2026. }
  2027.  
  2028. void *my_newmem(size_t size){
  2029.         void    *p;
  2030.         if ((p = malloc(size +1)) == NULL){canvas_error("canvasdraw: ran out of memory\n");}
  2031.         return p;
  2032. }
  2033.  
  2034. void swap(int *a, int *b) {
  2035.         int temp;
  2036.         temp = *b;
  2037.         *b = *a;
  2038.         *a = temp;
  2039. }
  2040. int find_number_of_digits(int i){
  2041.     if(i < 0 ){ i = -1*i;}
  2042.     int digits = 0;
  2043.     while ( i > 0){
  2044.         digits++;
  2045.         i = i/10;
  2046.     }
  2047.     return digits;
  2048. }
  2049. /* change this when colornames / numbers are added to struct */
  2050. #define NUMBER_OF_COLORNAMES    140
  2051. struct {
  2052.     char *hex;
  2053.     char *name;
  2054.     char *rgb;
  2055. } colors[]={
  2056.  {"#FF0000","red","255,0,0"},
  2057.  {"#00FF00","lime","0,255,0"},
  2058.  {"#0000FF","blue","0,0,255"},
  2059.  {"#FFA500","orange","255,165,0"},
  2060.  {"#E9967A","darksalmon","233,150,122"},
  2061.  {"#F0FFFF","azure","240,255,255"},
  2062.  {"#CD5C5C","indianred","205,92,92"},
  2063.  {"#E0FFFF","lightcyan","224,255,255"},
  2064.  {"#FFE4E1","mistyrose","255,228,225"},
  2065.  {"#DC143C","crimson","220,20,60"},
  2066.  {"#FFC0CB","pink","255,192,203"},
  2067.  {"#FFD700","gold","255,215,0"},
  2068.  {"#E6E6FA","lavender","230,230,250"},
  2069.  {"#808080","gray","128,128,128"},
  2070.  {"#F0F8FF","aliceblue","240,248,255"},
  2071.  {"#C71585","mediumvioletred","199,21,133"},
  2072.  {"#FFF0F5","lavenderblush","255,240,245"},
  2073.  {"#DAA520","goldenrod","218,165,32"},
  2074.  {"#FFB6C1","lightpink","255,182,193"},
  2075.  {"#00FFFF","aqua","0,255,255"},
  2076.  {"#FF69B4","hotpink","255,105,180"},
  2077.  {"#00FFFF","cyan","0,255,255"},
  2078.  {"#FF1493","deeppink","255,20,147"},
  2079.  {"#7FFFD4","aquamarine","127,255,212"},
  2080.  {"#FA8072","salmon","250,128,114"},
  2081.  {"#DEB887","burlywood","222,184,135"},
  2082.  {"#DB7093","palevioletred","219,112,147"},
  2083.  {"#D2B48C","tan","210,180,140"},
  2084.  {"#BDB76B","darkkhaki","189,183,107"},
  2085.  {"#B22222","firebrick","178,34,34"},
  2086.  {"#FF4500","orangered","255,69,0"},
  2087.  {"#8B4513","saddlebrown","139,69,19"},
  2088.  {"#FF8C00","darkorange","255,140,0"},
  2089.  {"#FFFFE0","lightyellow","255,255,224"},
  2090.  {"#FFFF00","yellow","255,255,0"},
  2091.  {"#FFFACD","lemonchiffon","255,250,205"},
  2092.  {"#F5F5DC","beige","245,245,220"},
  2093.  {"#FFEFD5","papayawhip","255,239,213"},
  2094.  {"#FAFAD2","lightgoldenrodyellow","250,250,210"},
  2095.  {"#FFE4B5","moccasin","255,228,181"},
  2096.  {"#B8860B","darkgoldenrod","184,134,11"},
  2097.  {"#FFF8DC","cornsilk","255,248,220"},
  2098.  {"#FFEBCD","blanchedalmond","255,235,205"},
  2099.  {"#FFE4C4","bisque","255,228,196"},
  2100.  {"#FFDEAD","navajowhite","255,222,173"},
  2101.  {"#F5DEB3","wheat","245,222,179"},
  2102.  {"#CD853F","peru","205,133,63"},
  2103.  {"#D2691E","chocolate","210,105,30"},
  2104.  {"#A0522D","sienna","160,82,45"},
  2105.  {"#A52A2A","brown","165,42,42"},
  2106.  {"#BC8F8F","rosybrown","188,143,143"},
  2107.  {"#F08080","lightcoral","240,128,128"},
  2108.  {"#FFA07A","lightsalmon","255,160,122"},
  2109.  {"#8B0000","darkred","139,0,0"},
  2110.  {"#800000","maroon","128,0,0"},
  2111.  {"#FAA460","sandybrown","250,164,96"},
  2112.  {"#FF7F50","coral","255,127,80"},
  2113.  {"#FF6347","tomato","255,99,71"},
  2114.  {"#FFDAB9","peachpuff","255,218,185"},
  2115.  {"#EEE8AA","palegoldenrod","238,232,170"},
  2116.  {"#F0E68C","khaki","240,230,140"},
  2117.  {"#D8BFD8","thistle","216,191,216"},
  2118.  {"#DDA0DD","plum","221,160,221"},
  2119.  {"#FF00FF","fuchsia","255,0,255"},
  2120.  {"#FF00FF","magenta","255,0,255"},
  2121.  {"#EE82EE","violet","238,130,238"},
  2122.  {"#DA70D6","orchid","218,112,214"},
  2123.  {"#BA55D3","mediumorchid","186,85,211"},
  2124.  {"#9370DB","mediumpurple","147,112,219"},
  2125.  {"#8A2BE2","blueviolet","138,43,226"},
  2126.  {"#9400D3","darkviolet","148,0,211"},
  2127.  {"#9932CC","darkorchid","153,50,204"},
  2128.  {"#8B008B","darkmagenta","139,0,139"},
  2129.  {"#800080","purple","128,0,128"},
  2130.  {"#4B0082","indigo","75,0,130"},
  2131.  {"#483D8B","darkslateblue","72,61,139"},
  2132.  {"#6A5ACD","slateblue","106,90,205"},
  2133.  {"#7B68EE","mediumslateblue","123,104,238"},
  2134.  {"#98FB98","palegreen","152,251,152"},
  2135.  {"#ADFF2F","greenyellow","173,255,47"},
  2136.  {"#7FFF00","chartreuse","127,255,0"},
  2137.  {"#7CFC00","lawngreen","124,252,0"},
  2138.  {"#00FF7F","springgreen","0,255,127"},
  2139.  {"#00FA9A","mediumspringgreen","0,250,154"},
  2140.  {"#90EE90","lightgreen","144,238,144"},
  2141.  {"#32CD32","limegreen","50,205,50"},
  2142.  {"#3CB371","mediumseagreen","60,179,113"},
  2143.  {"#2E8B57","seagreen","46,139,87"},
  2144.  {"#228B22","forestgreen","34,139,34"},
  2145.  {"#008000","green","0,128,0"},
  2146.  {"#006400","darkgreen","0,100,0"},
  2147.  {"#9ACD32","yellowgreen","154,205,50"},
  2148.  {"#6B8E23","olivedrab","107,142,35"},
  2149.  {"#808000","olive","128,128,0"},
  2150.  {"#556B2F","darkolivegreen","85,107,47"},
  2151.  {"#8FBC8F","darkseagreen","143,188,143"},
  2152.  {"#66CDAA","mediumaquamarine","102,205,170"},
  2153.  {"#20B2AA","lightseagreen","32,178,170"},
  2154.  {"#008B8B","darkcyan","0,139,139"},
  2155.  {"#008080","teal","0,128,128"},
  2156.  {"#AFEEEE","paleturquoise","175,238,238"},
  2157.  {"#40E0D0","turquoise","64,224,208"},
  2158.  {"#48D1CC","mediumturquoise","72,209,204"},
  2159.  {"#00CED1","darkturquoise","0,206,209"},
  2160.  {"#5F9EA0","cadetblue","95,158,160"},
  2161.  {"#4682B4","steelblue","70,130,180"},
  2162.  {"#B0C4DE","lightsteelblue","176,196,222"},
  2163.  {"#B0E0E6","powderblue","176,224,230"},
  2164.  {"#ADD8E6","lightblue","173,216,230"},
  2165.  {"#87CEEB","skyblue","135,206,235"},
  2166.  {"#87CEFA","lightskyblue","135,206,250"},
  2167.  {"#00BFFF","deepskyblue","0,191,255"},
  2168.  {"#1E90FF","dodgerblue","30,144,255"},
  2169.  {"#6495ED","cornflowerblue","100,149,237"},
  2170.  {"#4169E1","royalblue","65,105,225"},
  2171.  {"#0000CD","mediumblue","0,0,205"},
  2172.  {"#00008B","darkblue","0,0,139"},
  2173.  {"#000080","navy","0,0,128"},
  2174.  {"#191970","midnightblue","25,25,112"},
  2175.  {"#DCDCDC","gainsboro","220,220,220"},
  2176.  {"#D3D3D3","lightgrey","211,211,211"},
  2177.  {"#808080","grey","128,128,128"},
  2178.  {"#C0C0C0","silver","192,192,192"},
  2179.  {"#A9A9A9","darkgray","169,169,169"},
  2180.  {"#778899","lightslategray","119,136,153"},
  2181.  {"#708090","slategray","112,128,144"},
  2182.  {"#696969","dimgray","105,105,105"},
  2183.  {"#2F4F4F","darkslategray","47,79,79"},
  2184.  {"#000000","black","0,0,0"},
  2185.  {"#F5FFFA","mintcream","245,255,250"},
  2186.  {"#FFFFFF","white","255,255,255"},
  2187.  {"#F0FFF0","honeydew","240,255,240"},
  2188.  {"#F5F5F5","whitesmoke","245,245,245"},
  2189.  {"#F8F8FF","ghostwhite","248,248,255"},
  2190.  {"#FFFFF0","ivory","255,255,240"},
  2191.  {"#FFFAFA","snow","255,250,250"},
  2192.  {"#FFFAF0","floralwhite","255,250,240"},
  2193.  {"#FFF5EE","seashell","255,245,238"},
  2194.  {"#FDF5E6","oldlace","253,245,230"},
  2195.  {"#FAF0E6","linen","250,240,230"},
  2196.  {"#FAEBD7","antiquewhite","250,235,215"},
  2197.  };
  2198.