Subversion Repositories wimsdev

Rev

Rev 18669 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
15111 schaersvoo 1
/*27/7/2013 version  0.01
7614 schaersvoo 2
"Inspired" by FLY program: http://martin.gleeson.com/fly
3
*********************************************************************************
18552 bpr 4
* J.M. Evers 7/2013        *
5
* This is all just amateur scriblings... So no copyrights.      *
6
* This source code file, and compiled objects derived from it,      *
7
* can be used and distributed without restriction, including for commercial use  *
8
* No warrenty whatsoever      *
7614 schaersvoo 9
*********************************************************************************
10
*/
18552 bpr 11
#define VERSION    "0.5"
18104 georgesk 12
 
13
#define _GNU_SOURCE
14
#include <string.h>
15
 
7848 bpr 16
#include "canvasdraw.h"
15348 bpr 17
void *tmp_buffer;
18552 bpr 18
FILE  *js_include_file;
7614 schaersvoo 19
/******************************************************************************
20
**  Internal Functions
21
******************************************************************************/
18552 bpr 22
void  add_to_buffer(char *tmp); /* add tmp_buffer to the buffer */
23
void  sync_input(FILE *infile);/* proceed with inputfile */
24
void  reset();/* reset some global variables like "use_filled", "use_dashed" */
25
int  get_token(FILE *infile); /* read next char until EOL*/
18623 bpr 26
char *fillcolor;
27
int  x2px(double x);
28
int  y2px(double y);
18606 bpr 29
 
18552 bpr 30
double   px2x(int x);
31
double   px2y(int y);
32
double  get_real(FILE *infile,int last); /* read a value; calculation and symbols allowed */
33
char  *str_replace ( const char *word, const char *sub_word, const char *rep_word );
18623 bpr 34
char  *get_color(FILE *infile,int last); /* read hex-color or colorname -> hex */
18552 bpr 35
char  *get_string(FILE *infile,int last); /* get the string at the end of a command */
36
char  *get_string_argument(FILE *infile,int last); /* the same, but with "comma" as  separator */
18558 bpr 37
int hypgeodaux(double *q, double* res, int full);
18552 bpr 38
char   *convert_hex2rgb(char *hexcolor);
39
void  make_js_include(int canvas_root_id);
40
void  check_string_length(int length);/* checks if the length of string argument of command is correct */
41
FILE   *js_include_file;
42
FILE  *get_file(int *line_number, char **filename);
43
FILE   *infile;    /* will be stdin */
7614 schaersvoo 44
/******************************************************************************
45
** global
46
******************************************************************************/
47
int finished = FALSE;/* main variable for signalling the end of the fly-script ; if finished = 1 ; write to stdout or canvasz */
48
int line_number = 1;/* used in canvas_error() ; keep track of line number in canvasdraw/fly - script */
49
/* set some variables to avoid trouble (NaN) in case of syntax and other usage errors */
50
int xsize = 320;
51
int ysize = 320;
52
double xmin = 0.0;
53
double xmax = 320.0;
54
double ymin = 0.0;
55
double ymax = 320.0;
11893 schaersvoo 56
double tmax = 0;
57
double tmin = 0;
7614 schaersvoo 58
/* flag to indicate parsing of line status */
8224 bpr 59
int done = FALSE;
7614 schaersvoo 60
int type; /* eg command number */
15111 schaersvoo 61
int onclick = 0;
62
/*
15116 bpr 63
 
64
1 = onclick ;
65
2 = draggable ;
66
3 = click+slideable ;
67
4 = slideable without click
15111 schaersvoo 68
5 = draggable + slideable
69
*/
14208 schaersvoo 70
char *slider_type="0";
15111 schaersvoo 71
char *my_sliders = "[-1]";
72
int use_slider = -1;
73
int last_slider = 0;
74
double double_data[MAX_INT+1];
75
int int_data[MAX_INT+1];
76
int dragstuff[MAX_DRAGSTUFF];
77
int js_function[MAX_JS_FUNCTIONS]; /* javascript functions include objects on demand basis: only once per object type */
78
double affine_matrix[] = {1,0,0,1,0,0};
7785 schaersvoo 79
int use_affine = FALSE;
7614 schaersvoo 80
int use_rotate = FALSE;
14078 bpr 81
int use_filled = 0; /* 0:no fill, 1:fill,2=grid?,3=hatch?,4=diamond?,5=dot?,6=image? */
82
int use_dashed = FALSE; /* dashing not natively supported in firefox, for now... */
15111 schaersvoo 83
double angle = 0.0;
7614 schaersvoo 84
char buffer[MAX_BUFFER];/* contains js-functions with arguments ... all other basic code is directly printed into js-include file */
9329 schaersvoo 85
char *getfile_cmd = "";
15111 schaersvoo 86
int reply_format = 0;
87
unsigned int canvas_root_id;
88
char *css_class;
89
int font_size;
90
char *draw_type;
91
int jsplot_cnt = -1;     /* keepint track on the curve identity */
92
int input_cnt = 0;
93
int dashtype[2] = { 4 , 4 }; /* just line_px and space_px: may have more arguments...if needed in future */
94
char *function_label = "[\"f(x)=\",\"g(x)=\",\"h(x)=\"]";
95
int drag_type = -1;/* 0,1,2: xy,x,y */
96
int use_offset = 0;/* use_offset only for text shape objects... 0=none;1=yoffset;2=xoffset;3=xyoffset;4=centered*/
97
int linegraph_cnt = 0; /* identifier for command 'linegraph' ; multiple line graphs may be plotted in a single plot*/
98
int barchart_cnt = 0; /* identifier for command 'barchart' ; multiple charts may be plotted in a single plot*/
99
int legend_cnt = -1; /* to allow multiple legends to be used, for multiple piecharts etc  */
100
int use_axis = FALSE;
101
int use_axis_numbering = -1;
102
int no_reset = FALSE;
103
 
7614 schaersvoo 104
/******************************************************************************
105
** Main Program
106
******************************************************************************/
107
int main(int argc, char *argv[]){
18552 bpr 108
  /* need unique id for every call to canvasdraw: rand(); is too slow...will result in many identical id's */
109
  struct timeval tv;struct timezone tz;gettimeofday(&tv, &tz);
110
  canvas_root_id = (unsigned int) tv.tv_usec;
111
  infile = stdin;/* read flyscript via stdin */
112
  int i,c;
113
  for(i=0;i<MAX_DRAGSTUFF;i++){dragstuff[i] = 0;}
114
  for(i=0;i<MAX_INT;i++){int_data[i]=0;double_data[i]=0;}
115
  int use_snap = 0; /* 0 = none 1=grid: 2=x-grid: 3=y-grid: 4=snap to points */
116
  int print_drag_params_only_once = FALSE;/* avoid multiple useless identical lines about javascript precision and use_dragdrop */
18589 bpr 117
  int line_width = 2;
18552 bpr 118
  int decimals = 2;
119
  int use_dragstuff = 0;
120
  int precision = 100; /* 10 = 1;100=2;1000=3 decimal display for mouse coordinates or grid coordinate.May be redefined before every object */
121
  int use_userdraw = 0; /* 0=none,1=userdraw,2=multidraw flag to indicate user interaction */
122
  int use_tooltip = -1; /* 1= tooltip 2= popup window*/
123
  int use_parametric = FALSE;/* will be reset after parametric plotting */
124
  char *tooltip_text = "Click here";
125
  char *temp = ""; /* */
126
  char *bgcolor = "";/* used for background of canvas_div ; default is tranparent */
127
  char *stroke_color = "255,0,0";
128
  char *fill_color = "255,255,255";
129
  char *font_family = "12px Arial"; /* commands xaxistext,yaxistext,legend,text/textup/string/stringup may us this */
130
  char *font_color = "#00000";
131
  draw_type = "points";
132
  char *fly_font = "normal";
133
  css_class = "none";
134
  char *flytext = "";
135
  int canvas_type = DRAG_CANVAS; /* to use a specific canvas  for filling etc */
136
  int pixelsize = 1;
137
  int fill_cnt = 0;
138
  int use_zoom = 0;
139
  font_size = 12;/* this may lead to problems when using something like <code>fontfamily Italic 24px Arial</code> the ''fontsize`` value is not substituted into fontfamily !! */
140
  int fly_font_size = 12; /*fly_font_size is relative to this... */
141
  for(i=0;i<MAX_JS_FUNCTIONS;i++){js_function[i]=0;}
142
  int arrow_head = 8; /* size in px needed for arrow based  userdraw:  "userdraw arrow,color" */
143
  int crosshair_size = 5; /* size in px*/
18669 bpr 144
  int level_step = 1; /* resolution in pixels of level curves */
18552 bpr 145
  int plot_steps = 250;/* the js-arrays with x_data_points and y_data_points will have size 250 each: use with care !!! use jscurve when precise plots are required  */
146
  int found_size_command = 0; /* 1 = found size ; 2 = found xrange; 3 = found yrange: just to flag an error message */
147
  int object_cnt = 0; /*counter to identify the "onclick" ojects ; 0 is first object set onclick: reply[object_cnt]=1 when clicked ; otherwise reply[object_cnt]=0 ; object_cnt is only increased when another object is set  again */
148
  int clock_cnt = 0; /* counts the amount of clocks used -> unique object clock%d */
149
  int boxplot_cnt = 0;
150
  int drawxml_cnt = 0;
151
  int numberline_cnt = 0;
152
  int snap_to_points_cnt = 0;
153
  int reply_precision = 100; /* used for precision of student answers / drawings */
154
  char *rotation_center = "null";/* needs to be removed... but is used for canvas CTX based rotation*/
155
  double rotationcenter[] = {0,0}; /* use for recalculating x/y values on rotation() */
156
  int use_animate = 0; /* used for jscurve / js parametric  */
157
  int use_input_xy = 0; /* 1= input fields 2= textarea 3=calc y value*/
158
  size_t string_length = 0; /* measure the size of the user input fly-string */
18609 bpr 159
  double stroke_opacity = 0.95; /* use some opacity as default */
18552 bpr 160
  double fill_opacity = 0.5;/* use some opacity as default */
161
  char *URL = "http://localhost/images";
162
  memset(buffer,'\0',MAX_BUFFER);
163
  void *tmp_buffer = "";
18615 bpr 164
  double res[10];
18552 bpr 165
  /* default writing a unzipped js-include file into wims getfile directory */
166
  char *w_wims_session = getenv("w_wims_session");
167
  if( w_wims_session == NULL || *w_wims_session == 0 ){canvas_error("Hmmm, your wims environment does not exist...\nCanvasdraw should be used within wims.");}
168
  int L0=strlen(w_wims_session) + 21;
169
  char *getfile_dir = my_newmem(L0); /* create memory to fit string precisely */
170
  snprintf(getfile_dir,L0, "../sessions/%s/getfile",w_wims_session);/* string will fit precisely  */
171
  mode_t process_mask = umask(0); /* check if file exists */
172
  int result = mkdir(getfile_dir, S_IRWXU | S_IRWXG | S_IRWXO);
173
  if( result == 0 || errno == EEXIST ){
174
    umask(process_mask); /* be sure to set correct permission */
175
    char *w_session = getenv("w_session");
176
    int L1 = (int) (strlen(w_session)) + find_number_of_digits(canvas_root_id) + 48;
177
    getfile_cmd = my_newmem(L1); /* create memory to fit string precisely */
178
    snprintf(getfile_cmd,L1,"wims.cgi?session=%s&cmd=getfile&special_parm=%d.js",w_session,canvas_root_id);/* extension ".gz" is MANDATORY for webserver */
13306 obado 179
    /* write the include tag to html page:<script src="wims.cgi?session=%s&cmd=getfile&special_parm=11223344_js"></script> */
7614 schaersvoo 180
    /* now write file into getfile dir*/
14066 bpr 181
    char *w_wims_home = getenv("w_wims_home"); /* "/home/users/wims": we need absolute path for location */
7614 schaersvoo 182
    int L2 = (int) (strlen(w_wims_home)) + (int) (strlen(w_wims_session)) + find_number_of_digits(canvas_root_id) + 23;
183
    char *location = my_newmem(L2); /* create memory to fit string precisely */
184
    snprintf(location,L2,"%s/sessions/%s/getfile/%d.js",w_wims_home,w_wims_session,canvas_root_id);/*absolute path */
185
    js_include_file = fopen(location,"w");/* open the file location for writing */
14066 bpr 186
    /* check on opening...if nogood: mount readonly? disk full? permissions not set correctly? */
187
    if(js_include_file == NULL){ canvas_error("SHOULD NOT HAPPEN: could not write to javascript include file...check your system logfiles !" );}
7614 schaersvoo 188
 
189
/* ----------------------------------------------------- */
11997 schaersvoo 190
 
18552 bpr 191
/*  while more lines to process */
7614 schaersvoo 192
 
193
    while(!finished){
18552 bpr 194
      if(line_number>1 && found_size_command == 0 && use_tooltip != 2 ){canvas_error("command \"size xsize,ysize\" needs to come first ! ");}
195
      type = get_token(infile);
196
      done = FALSE;
197
  /*
198
  @ canvasdraw
199
  @ Canvasdraw will try use the same basic syntax structure as flydraw
18627 bpr 200
  @ General syntax <ul><li>The transparency of all objects can be controlled by command <a href="#opacity">opacity [0-255],[0,255]</a></li><li>Line width of any object can be controlled by command <a href="#linewidth">linewidth int</a></li><li>Any may be dashed by using keyword <a href="#dashed">dashed</a> before the object command.<br> the dashing type can be controled by command <a href="#dashtype">dashtype int,int</a>please note: dashing may have different spacing depending on the angle of the line<br>see https://wimsedu.info/?topic=dashed-arrows-not-dashed-in-canvasdraw</li><li>A fillable object can be set fillable by starting the object command with an ''f`` (like ''frect``,''fcircle``,''ftriangle`` ...) or by using the keyword <a href="#filled">filled</a> before the object command.<br>Non-solid filling (grid,hatch,diamond,dot,text) is provided using command <a href="#fillpattern">fillpattern a_pattern</a><br>note: do not use a <b>f</b> with this non-solid pattern filling.<br>For <a href="#filltoborder">filltoborder x0,y0,bordercolor,color</a> (fill a region around x0,y0 with color until a border of color borderolor is encountered) or <a href="#filltoborder">fill x0,y0,color</a> type filling (fill a region around x0,y0 with color until a border is encountered), there are non-solid pattern fill analogues:<ul><li><a href="#gridfill">gridfill x,y,dx,dy,color</a></li><li><a href="#hatchfill">hatchfill x,y,dx,dy,color</a></li><li><a href="#diamondfill">diamondfill x,y,dx,dy,color</a></li><li><a href="#dotfill">dotfill x,y,dx,dy,color</a></li><li><a href="#textfill">textfill x,y,color,sometext_or_char</a></li></ul></li><li>All draggable objects may have a <a href="#slider">slider</a> for translation / rotation; several objects may be translated / rotated by a single slider</li><li>A draggable object can be set draggable by a preceding command <a href="#drag">drag x/y/xy</a><br>The translation can be read by javascript:read_dragdrop();The replyformat is: object_number : x-orig : y-orig : x-drag : y-drag<br>The x-orig/y-orig will be returned in maximum precision (javascript float)...<br>the x-drag/y-drag will be returned in defined ''precision`` number of decimals<br>Multiple objects may be set draggable / clickable (no limit)<br>not all flydraw objects may be dragged / clicked<br>Only draggable / clickable objects will be scaled on <a href="#zoom">zoom</a> and will be translated in case of panning.</li><li>A ''onclick object`` can be set ''clickable`` by the preceding keyword <a href="#onclick">onclick</a><br>Not all flydraw objects can be set clickable</li><li><b>Remarks using a '';`` as command separator</b>. Commands with only numeric or color arguments may be using a '';`` as command separator (instead of a new line). Commands with a string argument may not use a '';`` as command separator.<br>These exceptions are not really straight forward... so keep this in mind.</li><li>Almost every <a href="#userdraw">userdraw object,color</a> or <a href="#multidraw">multidraw</a> command ''family`` may be combined with keywords <a href="#snaptogrid">"snaptogrid | xsnaptogrid | ysnaptogrid | snaptofunction</a> or command <code>snaptopoints x1,y1,x2,y2,...</code></li><li>Every draggable | onclick object may be combined with keywords <a href="#snaptogrid">snaptogrid | xsnaptogrid | ysnaptogrid | snaptofunction</a> or command <code>snaptopoints x1,y1,x2,y2,...</code></li><li>Almost every command for a single object has a multiple objects counterpart: <ul>general syntax rule:<li><code>object x1,y1,...,color</code></li><li><code>objects color,x1,y1,...</code></li></ul><li>All inputfields or textareas generated, can be styled individually using command <a href="#css">css some_css</a>: the fontsize used for labeling these elements can be controlled by command <a href="#fontsize">fontsize int</a> command <code>fontfamily</code> is <b>not</b> active for these elements.</li></ul>
201
  @ If needed multiple interactive scripts (*) may be used in a single webpage.<br>A function <code>read_canvas()</code> and / or <code>read_dragdrop()</code> can read all interactive userdata from these images.<br>The global array <code>canvas_scripts</code>will contain all unique random "canvas_root_id" of the included scripts.<br>The included local javascript "read" functions ''read_canvas%d()`` and ''read_dragdrop%d()`` will have this ''%d = canvas_root_id``<br>e.g. canvas_scripts[0] will be the random id of the first script in the page and will thus provide a function<br><code>fun = eval("read_canvas"+canvas_scripts[0])</code> to read user based drawings / inputfield in this first image.<br>The read_dragdrop is analogue.<br>If the default reply formatting is not suitable, use command <a href='#replyformat'>replyformat</a> to format the replies for an individual canvas script,<br>To read all user interactions from all included canvas scripts, use something like:<br><code>function read_all_canvas_images(){<br>&nbsp;var script_len = canvas_scripts.length;<br>&nbsp;var draw_reply = "";<br>&nbsp;var found_result = false;<br>&nbsp;for(var p = 0 ; p < script_len ; p++){<br>&nbsp;&nbsp;var fun = eval("read_canvas"+canvas_scripts[p]);<br>&nbsp;&nbsp;if( typeof fun === 'function'){<br>&nbsp;&nbsp;&nbsp;var result = fun();<br>&nbsp;&nbsp;&nbsp;if( result&nbsp;&nbsp;&& result.length != 0){<br>&nbsp;&nbsp;&nbsp;&nbsp;if(script_len == 1 ){.return result;};<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;found_result = true;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;draw_reply = draw_reply + result + "newline";<br>&nbsp;&nbsp;&nbsp;&nbsp;};<br>&nbsp;&nbsp;&nbsp;};<br>&nbsp;&nbsp;};<br>&nbsp;if( found_result ){return draw_reply;}else{return null;};<br>};</code> <br>(*) Note: the speed advantage over <em>canvas-do-it-all</em> libraries is reduced to zero, when multiple canvasdraw scripts are present in a single page... For example a typical canvasdraw script is between 5 and 40 kB...a large library like JSXgraph is approx 600 kB. In these cases it would be much faster to load a static general HTML5 canvas javascript draw library and parse it multiple raw fly instructions.
202
  @ Canvasdraw can be used to paint a html5 bitmap image by generating a tailor-made javascript include file: providing only the js-functionality needed to perform the job, thus ensuring a minimal strain on the client browser (unlike some popular ''canvas-do-it-all`` libraries, who have proven to be not suitable for low-end computers found in schools...)
18552 bpr 203
  @ You can check the javascript reply format in the wims tool <a href="http://localhost/wims/wims.cgi?lang=en&module=tool/directexec">direct exec</a>
204
  @ For usage within OEF (without anstype ''draw``), something like this (a popup function plotter) will work:<br><code>\\text{popup_grapher=wims(exec canvasdraw <br>popup<br>size 400,400<br>xrange -10,10<br>yrange -10,10<br>axis<br>axisnumbering<br>opacity 100,100<br>grid 2,2,grey,2,2,6,black<br>snaptogrid<br>linewidth 2<br>jsplot red,5*sin(1/x)<br>strokecolor green<br>functionlabel f(x)=<br>userinput function<br>mouse blue,22<br>)<br>}<br>\\statement{<br>\\popup_grapher<br>}</code>.
18627 bpr 205
  @ Be aware that older browsers will probably not work correctly. no effort has been undertaken to add glue code for older browsers !! In any case it is not wise to use older browsers...not just for canvasdraw.
18552 bpr 206
  @ Be aware that combining several different objects and interactivity may lead to problems.
207
  @ If you find flaws, errors or other incompatibilities -not those mentioned in this document- send <a href='mailto:jm.evers-at-schaersvoorde.nl'>me</a> an email with screenshots and the generated javascript include file.
18627 bpr 208
  @ There is limited support for touch devices: touchstart, touchmove and touchend in commands <a href="#userdraw">userdraw primitives </a>, <a href="#multidraw">multidraw primitives </a>, <a href="#protractor">protractor</a>, <a href="#ruler">ruler</a> and probably a few others... Only single finger gestures are supported (for now). The use of a special pen is advised for interactive drawing on touch devices. For more accurate user-interaction (numeric, eg keyboard driven drawings) with canvasdraw on touch devices: use the command family <a href="#userinput_xy">userinput</a>.
18552 bpr 209
  */
210
      switch(type){
211
        case END:finished = 1;done = TRUE;break;
212
        case 0:sync_input(infile);break;
213
        case AFFINE:
214
  /*
18556 bpr 215
  @ affine a,b,c,d,tx,ty
216
  @ defines a transformation matrix for subsequent objects
217
  @ use keyword <a href='#killaffine'>killaffine</a> to end the transformation...the next objects will be drawn in the original x/y-range
218
  @ a: Scales the drawings horizontally
219
  @ b: Skews the drawings horizontally
220
  @ c: Skews the drawings vertically
221
  @ d: Scales the drawings vertically
222
  @ tx: Moves the drawings horizontally in xrange coordinate system
223
  @ ty: Moves the drawings vertically in yrange coordinate system
224
  @ the data precision may be set by preceding command ''precision int``
225
  @ <b>note</b>: not all affine operations on canvasdraw objects will be identical to flydraw's behaviour. Make sure to check !
226
  @%affine%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%#use larger linewith to improve selecting a draggable object !%linewidth 4%drag xy%frect 0,5,3,3,red%affine cos(pi/4),sin(pi/4),-cos(pi/2),sin(pi/2),-5,-5%drag xy%frect 0,5,3,3,red
227
  @%affine+latex%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%strokecolor blue%fontfamily 42px Arial%centered%drag xy%latex 5,5,\\frac{123}{\\pi^{234}}%affine cos(pi/4),sin(pi/4),-cos(pi/2),sin(pi/2),-5,-5%drag xy%latex 5,5,\\frac{123}{\\pi^{234}}
18552 bpr 228
  */
229
          for(i = 0 ; i<6;i++){
230
            switch(i){
231
              case 0: affine_matrix[0] = get_real(infile,0);break;
232
              case 1: affine_matrix[1] = get_real(infile,0);break;
233
              case 2: affine_matrix[2] = get_real(infile,0);break;
234
              case 3: affine_matrix[3] = get_real(infile,0);break;
235
              case 4: affine_matrix[4] = get_real(infile,0);break;
236
              case 5: affine_matrix[5] = get_real(infile,1);
237
              use_affine = TRUE;
238
              break;
239
              default: break;
240
            }
241
          }
242
          break;
14394 schaersvoo 243
        case ALLOW_DUPLICATES:
18556 bpr 244
  /*
245
  @ duplicates || allowdups
246
  @ keyword (no arguments)
247
  @ only useful in case of a <a href="#multidraw">multidraw</a> student reply.
248
  @ only useful in default <a href="#replyformat">replyformat</a> (eg in case of a not specified replyformat).
249
  @ if set, duplicate (x:y) coordinates will not be removed from the student reply.
250
  @ technical: a javascript variable "allow_duplicate_answer = 1;" is declared.
251
  @ default for command multidraw is: removal of duplicates.
252
  */
18552 bpr 253
          fprintf(js_include_file,"var allow_duplicate_answers = 1;");
254
          break;
255
        case ANGLE:
18556 bpr 256
  /*
257
  @ angle xc,yc,width,start_angle,end_angle,color
258
  @ width is in x-range
259
  @ angles are in degrees
260
  @ not compatible with ''flydraw``
261
  @ will zoom in/out
262
  @ may be set onclick or drag&amp;drop
263
  @ if angle size is controlled by command <a href='#slider'>slider</a>, use radians to set limits of slider
264
  @ ''angle`` and <a href="#arc">arc</a>  are exceptions in case of sliders...they are always active (e.g. not click-activated)
265
  @%angle%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor orange%angle 0,0,4,10,135,blue
266
  @%angle_slider%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 3%strokecolor blue%slider -2*pi,2*pi,260,28,angle active degree,blue arrow%arrow 0,0,8,0,8,blue%fillpattern diamond%angle 0,0,2,0,0,blue%killslider%strokecolor red%slider -2*pi,2*pi,260,28,angle active radian,red arrow%arrow 0,1,8,1,8,red%fillpattern dot%angle 0,1,2,0,0,red
267
  */
18552 bpr 268
          for(i=0;i<7;i++){
269
            switch(i){
270
              case 0:double_data[0] = get_real(infile,0);break; /* x-values */
271
              case 1:double_data[1] = get_real(infile,0);
272
              if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);}
273
              if(use_affine == TRUE ){ transform(2,2);}
274
              break; /* y-values */
275
              case 2:double_data[2] = get_real(infile,0);break; /* width x-range ! */
276
              case 3:double_data[3] = 0.0174532925*(get_real(infile,0) - angle);break; /* start angle in degrees -> radians  */
277
              case 4:double_data[4] = 0.0174532925*(get_real(infile,0) - angle);break; /* end angle in degrees -> radians */
278
              case 5:stroke_color = get_color(infile,1);/* name or hex color */
279
              if( use_slider != -1 ){ onclick = 3; }/* always active in case of slider */
280
              decimals = find_number_of_digits(precision);
18557 bpr 281
              tmp_buffer=my_newmem(MAX_BUFFER);
282
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,17,[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[0],decimals,double_data[1],decimals,double_data[1],decimals,double_data[2],decimals,double_data[2],decimals,double_data[3],decimals,double_data[4],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 283
              add_to_buffer(tmp_buffer);
284
              dragstuff[17] = 1;
285
              if(use_dragstuff == 0 ){ use_dragstuff = 1; }
286
              if(onclick != 0){object_cnt++;}/* object_cnt++;*/
287
              break;
288
            }
289
          }
290
          break;
291
        case ANIMATE:
292
  /*
18556 bpr 293
  @ animate
294
  @ keyword
295
  @ if set, it will animate a point on a curve
296
  @ all other canvas object or group of objects (like lines,circles,rects,points...images,svg,latex,mathml etc)<br>may be animated using command <a href='#slider'>slider</a> with keyword 'anim'
18627 bpr 297
  @ the animated point is a filled rectangle ; adjust color with command <code>fillcolor colorname/hexnumber</code>
18556 bpr 298
  @ use linewidth to adjust size of the points
299
  @ will animate a point on -only- the next <a href='#jsplot'>jsplot/jscurve command</a>. Only a single call to <code>animate</code> is allowed...in case of multiple <code>animate</code> keywords, only the last one is valid
300
  @ only usable in combination with command <a href='#jsplot'>jsplot</a> (normal functions or parametric)
301
  @ moves repeatedly from <a href='#xrange'>xmin to xmax</a> or in case of a parametric function from <a href='#trange'>tmin to tmax</a>
302
  @ use commands <a href='#multilinewidth'>multilinewidth</a>, <a href='#multistrokecolor'>multistrokecolor</a> etc in case of multiple animated functions.<br>use multiple functions as argument in a single call to <a href='#jsplot'>jsplot color,fun1,fun2,fun3...fun_n</a>
303
  @%animate_1%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 100%linewidth 4%fillcolor red%animate%trange -2*pi,2*pi%linewidth 1%opacity 255,50%canvastype 100%fill 1.2,1.2,red%canvastype 101%fill -1.2,-1.2,blue%jsplot blue,7*cos(x),5*sin(2*x)
304
  @%animate_2%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 100%linewidth 4%fillcolor red%animate%trange -2*pi,2*pi%linewidth 1%opacity 255,50%canvastype 100%fill 1.2,1.2,red%canvastype 101%fill -1.2,-1.2,blue%multistrokecolors blue,blue,green,green,orange,orange%multilinewidth 2,2,3,3,1,1%jsplot blue,7*cos(x),5*sin(2*x),9*sin(x),5*cos(x),x^2,x
18552 bpr 305
  */
306
          use_animate++;
307
          if( use_animate == 1 ){
308
            fprintf(js_include_file,"\nvar trace_canvas  = create_canvas%d(%d,xsize,ysize);\
309
              var trace_ctx = trace_canvas.getContext('2d');\
310
              trace_ctx.fillStyle = 'rgba(%s,%f)';\
311
              trace_ctx.strokeStyle = 'rgba(%s,%f)';\
312
              trace_ctx.lineWidth = %d;var anim_pos = 0;\n\
313
              function animate_this(){\
314
              var sync;\
315
              var synchrone = Math.floor(animation_steps/animation_funs);\
316
              trace_ctx.clearRect(0,0,xsize,ysize);\
317
              for(var p=0; p<animation_funs;p++){\
318
               sync = p*synchrone;\
319
               trace_ctx.fillRect(x_anim_points[sync+anim_pos]-%d, y_anim_points[sync+anim_pos]-%d,%d,%d);\
320
              };\
321
              setTimeout(function(){\
322
               requestAnimationFrame(animate_this);  anim_pos++;}, 50\
323
              );\
324
              if(anim_pos >= animation_steps){anim_pos = 0;};\
325
              };",canvas_root_id,ANIMATE_CANVAS,fill_color,fill_opacity,stroke_color,stroke_opacity,line_width,line_width,line_width,2*line_width,2*line_width);
326
          } else {
327
            canvas_error("animate can only be used once<br>multiple curves may be animated using something like:<br>jsplot red,sin(x),cos(x),x^2,sin(2*x)");
328
          }
329
          break;
330
        case ARC:
331
  /*
18556 bpr 332
  @ arc xc,yc,x-width,y-height,start_angle,end_angle,color
333
  @ may be set ''onclick`` or ''drag xy``
334
  @ compatible with ''flydraw``
335
  @ attention: width &amp; height in x/y-range
336
  @ for arrow hats on an arc, see  command <a href='#arcarrow'>arcarrow or arrowarc</a>
337
  @ better use command <a href='#angle'>angle</a> for use with a <a href='#slider'>slider</a>
338
  @%arc%size 400,400%xrange -10,10%yrange -10,10%arc 0,0,4,4,10,135,red
339
  @%arc_filled%size 400,400%xrange -10,10%yrange -10,10%opacity 255,60%filled%fillcolor green%arc 0,0,4,4,10,135,red
18552 bpr 340
  */
18641 bpr 341
          if(fillcolor) {fill_color=fillcolor;} else {fill_color=stroke_color;}
18552 bpr 342
          for(i=0;i<7;i++){
343
            switch(i){
344
              case 0:double_data[0] = get_real(infile,0);break; /* x-values */
345
              case 1:double_data[1] = get_real(infile,0);
346
              if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);}
347
              if(use_affine == TRUE ){ transform(4,2);}
348
              break; /* y-values */
349
              case 2:double_data[2] = get_real(infile,0);break; /* width x-range no pixels ! */
350
              case 3:double_data[3] = get_real(infile,0);
351
              break; /* height y-range no pixels ! */
352
              case 4:double_data[4] = get_real(infile,0) - angle ;break; /* start angle in degrees */
353
              case 5:double_data[5] = get_real(infile,0) - angle;break; /* end angle in degrees */
354
              case 6:stroke_color = get_color(infile,1);/* name or hex color */
355
        /* in Shape library:
356
      x[0] = x[1] = xc = double_data[0]
357
      y[0] = y[1] = yc = double_data[1]
358
      w[0] = width = double_data[2]
359
      w[1] = height = double_data[3]
360
      h[0] = start_angle = double_data[4]
361
      h[1] = end_angle = double_data[5]
362
        */
18555 bpr 363
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
364
                decimals = find_number_of_digits(precision);
18557 bpr 365
 
366
                tmp_buffer=my_newmem(MAX_BUFFER);
367
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,12,[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[0],decimals,double_data[1],decimals,double_data[1],decimals,double_data[2],decimals,double_data[3],decimals,double_data[4],decimals,double_data[5],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18555 bpr 368
                add_to_buffer(tmp_buffer);reset();
369
                dragstuff[12] = 1;
370
                if(onclick != 0){object_cnt++;}
371
                if(use_dragstuff == 0 ){ use_dragstuff = 1; }
18552 bpr 372
              break;
373
            }
374
          }
375
          break;
376
        case ARCARROW:
377
  /*
18556 bpr 378
  @ arrowarc xc,yc,x-width,y-height,start_angle,end_angle,color,type
379
  @ alternative: arcarrow
380
  @ uses same syntax as <a href='#arc'>arc</a>
381
  @ for arrow hat: type = 1 : right<br>type = 2 : left<br>type = 3 : left&amp;right
382
  @ if the default arrow hat/head is not satisfactory , the size of the arrow may be set with command <a href='#arrowhead'>arrowhead</a>
383
  @ no other arrow types are implemented...yet
384
  @ may be set draggable or onclick
385
  @ attention: when width ad height are very different, the arrow hat is not drawn correctly. This is a flaw and not a feature...(for now: too much calculations to correct)
386
  @%arcarrow%size 400,400%xrange -10,10%yrange -10,10%noreset%onclick%arcarrow 0,0,7,7,50,275,blue,3%arcarrow 0,0,8,8,50,275,red,2%arcarrow 0,0,9,9,50,275,green,1
18552 bpr 387
  */
388
          for(i=0;i<8;i++){
389
            switch(i){
390
              case 0:double_data[0] = get_real(infile,0);break; /* x-values */
391
              case 1:double_data[1] = get_real(infile,0);
392
                if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);}
393
                if(use_affine == TRUE ){ transform(4,2);}
394
                break; /* y-values */
395
              case 2:double_data[2] = get_real(infile,0);break; /* width x-range no pixels ! */
396
              case 3:double_data[3] = get_real(infile,0);
397
                break; /* height y-range no pixels ! */
398
              case 4:double_data[4] = get_real(infile,0) - angle ;break; /* start angle in degrees */
399
              case 5:double_data[5] = get_real(infile,0) - angle;break; /* end angle in degrees */
400
              case 6:stroke_color = get_color(infile,0);/* name or hex color */
401
                break;
402
              case 7:int_data[0] = (int) get_real(infile,1);
403
                switch(int_data[0]){
404
                  case 1: int_data[1] = 24;break; /* right */
405
                  case 2: int_data[1] = 25;break; /* left */
406
                  case 3: int_data[1] = 26;break; /* left&right */
407
                  default:int_data[1] = 24;break;
408
                }
409
              if(int_data[0] == 1 ){int_data[1] = 24;}
410
              if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
411
              decimals = find_number_of_digits(precision);
18557 bpr 412
 
413
              tmp_buffer=my_newmem(MAX_BUFFER);
414
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"var arrow_head = %d;dragstuff.addShape(new Shape(%d,%d,%d,%d,%d,[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",arrow_head,drag_type,object_cnt,onclick,use_snap,int_data[1],decimals,double_data[0],decimals,double_data[0],decimals,double_data[1],decimals,double_data[1],decimals,double_data[2],decimals,double_data[3],decimals,double_data[4],decimals,double_data[5],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 415
              add_to_buffer(tmp_buffer);
416
              dragstuff[int_data[1]] = 1;
417
              if(onclick != 0){object_cnt++;}
418
              if(use_dragstuff == 0 ){ use_dragstuff = 1; }
419
              js_function[JS_ARROWHEAD] = 1;
420
              reset();
421
            }
422
          }
423
          break;
424
        case ARROW:
425
  /*
426
  @ arrow x1,y1,x2,y2,h,color
427
  @ alternative: vector
428
  @ draw a single headed arrow / vector from (x1:y1) to (x2:y2)<br>with arrowhead size h in px and in color ''color``
429
  @ use command <code>linewidth int</code> to adjust thickness of the arrow
430
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
431
  @%arrow_drag%size 400,400%xrange -10,10%yrange -10,10%cursor move%linewidth 2%drag xy%arrow 0,0,4,3,8,blue%drag xy%arrow 0,0,-4,3,8,green%drag xy%arrow 0,0,4,-3,8,orange%drag xy%arrow 0,0,-4,-3,8,cyan
432
  @%arrow_click%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%%onclick%arrow 0,0,4,4,8,blue%onclick%arrow 0,0,-4,5,8,green%onclick%arrow 0,0,4,-6,8,orange%onclick%arrow 0,0,-4,-2,8,cyan
433
  */
434
          for(i=0;i<6;i++){
435
            switch(i){
436
              case 0: double_data[0] = get_real(infile,0);break; /* x */
437
              case 1: double_data[1] = get_real(infile,0);break; /* y */
438
              case 2: double_data[2] = get_real(infile,0);break; /* x */
439
              case 3: double_data[3] = get_real(infile,0);break; /* y */
440
              case 4: arrow_head = (int) get_real(infile,0);break;/* h */
441
              case 5: stroke_color = get_color(infile,1);/* name or hex color */
442
                if(use_rotate == TRUE ){rotate(4,angle,rotationcenter,2);}
443
                if(use_affine == TRUE ){ transform(4,2);}
444
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
445
                decimals = find_number_of_digits(precision);
18557 bpr 446
                tmp_buffer=my_newmem(MAX_BUFFER);
447
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,8,[%.*f,%.*f],[%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[1],decimals,double_data[3],arrow_head,arrow_head,arrow_head,arrow_head,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 448
                if(onclick != 0){object_cnt++;}
449
          /* object_cnt++;*/
450
                add_to_buffer(tmp_buffer);reset();
451
                dragstuff[8] = 1;
452
                if(use_dragstuff == 0 ){ use_dragstuff = 1; }
453
              break;
454
            }
455
          }
456
          break;
457
        case ARROWS:
458
  /*
459
  @ arrows color,head (px),x1,y1,x2,y2...x_n,y_n
460
  @ alternative: vectors
461
  @ draw single headed arrows / vectors from (x1:y1) to (x2:y2) ... (x3:y3) to (x4:y4) etc ... in color 'color'
462
  @ use command <code>linewidth int</code> to adjust thickness of the arrow
463
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually
464
  @%arrows_click%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%onclick%arrows red,8,0,0,4,3,0,0,2,4,0,0,-2,4,0,0,-3,-4,0,0,3,-2%
465
  @%arrows_drag%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%drag xy%arrows red,8,0,0,4,3,0,0,2,4,0,0,-2,4,0,0,-3,-4,0,0,3,-2%
466
  @%arrows_drag_slider%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%drag xy%# Click arrow(s) to activate %slider 0,2*pi,300,30,angle degrees,Rotate%slider -5,5*pi,300,30,x display,move in x-direction%slider -10,10*pi,300,30,y display,move in y-direction%arrows red,8,0,0,4,3,0,0,2,4,0,0,-2,4,0,0,-3,-4,0,0,3,-2%
467
  */
468
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
469
          fill_color = stroke_color;
470
          arrow_head = (int) get_real(infile,0);/* h */
471
          i=0;
472
          while( ! done ){     /* get next item until EOL*/
473
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
474
            if(i%2 == 0 ){
475
              double_data[i] = get_real(infile,0); /* x */
476
            } else {
477
              double_data[i] = get_real(infile,1); /* y */
478
            }
479
          i++;
480
          }
481
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
482
          if( use_affine == TRUE ){ transform(i-1,2);}
483
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
484
          decimals = find_number_of_digits(precision);
485
          for(c = 0 ; c < i-1 ; c = c+4){
18557 bpr 486
            tmp_buffer=my_newmem(MAX_BUFFER);
487
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,8,[%.*f,%.*f],[%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],arrow_head,arrow_head,arrow_head,arrow_head,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 488
            add_to_buffer(tmp_buffer);
489
            if(onclick != 0){object_cnt++;}/* object_cnt++; */
490
          }
491
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
492
          dragstuff[8] = 1;
493
          reset();
494
          break;
495
        case ARROW2:
496
  /*
497
  @ arrow2 x1,y1,x2,y2,h,color
498
  @ draw a double headed arrow/vector from (x1:y1) to (x2:y2)<br>with arrowhead size h in px and in color ''color``
499
  @ use command <code>arrowhead int</code> to adjust the arrow head size
500
  @ use command <code>linewidth int</code> to adjust thickness of the arrow
501
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
502
  @%arrow2%size 400,400%xrange -10,10%yrange -10,10%drag xy%arrow2 0,0,4,3,8,blue%
503
  */
504
          for(i=0;i<6;i++){
505
            switch(i){
506
              case 0: double_data[0] = get_real(infile,0);break; /* x */
507
              case 1: double_data[1] = get_real(infile,0);break; /* y */
508
              case 2: double_data[2] = get_real(infile,0);break; /* x */
509
              case 3: double_data[3] = get_real(infile,0);break; /* y */
510
              case 4: arrow_head = (int) get_real(infile,0);break;/* h */
511
              case 5: stroke_color = get_color(infile,1);/* name or hex color */
512
                if(use_rotate == TRUE ){rotate(4,angle,rotationcenter,2);}
513
                if( use_affine == 1 ){ transform(4,2);}
514
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
515
                decimals = find_number_of_digits(precision);
18557 bpr 516
                tmp_buffer=my_newmem(MAX_BUFFER);
517
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,10,[%.*f,%.*f],[%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[1],decimals,double_data[3],arrow_head,arrow_head,arrow_head,arrow_head,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 518
                add_to_buffer(tmp_buffer);
519
                if(onclick != 0){object_cnt++;}/* object_cnt++;*/
520
                if(use_dragstuff == 0 ){ use_dragstuff = 1; }
521
                dragstuff[10] = 1;
522
                reset();
523
                break;
524
            }
525
          }
526
          break;
527
        case ARROWS2:
528
  /*
529
  @ arrows2 color,head (px),x1,y1,x2,y2...x_n,y_n
530
  @ draw double headed arrows / vectors from (x1:y1) to (x2:y2) ... (x3:y3) to (x4:y4) etc ... in color ''color``
531
  @ use command <code>linewidth int</code> to adjust thickness of the arrows
532
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually
533
  @%arrows2%size 400,400%xrange -10,10%yrange -10,10%onclick%arrows2 red,8,0,0,4,3,1,1,2,4,2,2,-2,4,3,3,-3,-4,0,0,3,-2%
534
  */
535
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
536
          fill_color = stroke_color;
537
          arrow_head = (int) get_real(infile,0);/* h */
538
          i=0;
539
          while( ! done ){     /* get next item until EOL*/
540
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
541
            if(i%2 == 0 ){
542
              double_data[i] = get_real(infile,0); /* x */
543
            } else {
544
              double_data[i] = get_real(infile,1); /* y */
545
            }
546
            i++;
547
          }
548
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
549
          if( use_affine == 1 ){ transform(i-1,2);}
550
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
8386 schaersvoo 551
 
18552 bpr 552
          decimals = find_number_of_digits(precision);
553
          for(c = 0 ; c < i-1 ; c = c+4){
18557 bpr 554
            tmp_buffer=my_newmem(MAX_BUFFER);
555
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,10,[%.*f,%.*f],[%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],arrow_head,arrow_head,arrow_head,arrow_head,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 556
            add_to_buffer(tmp_buffer);
557
            if(onclick != 0){object_cnt++;}/* object_cnt++; */
558
          }
559
          dragstuff[10] = 1;
560
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
561
          reset();
562
          break;
563
        case ARROWHEAD:
564
  /*
565
  @ arrowhead int
566
  @ default 8 (pixels)
567
  */
568
          arrow_head = (int) (get_real(infile,1));
569
          break;
570
        case AUDIO:
571
  /*
572
  @ audio x,y,w,h,loop,visible,audiofile location
573
  @ x,y: left top corner of audio element (in xrange / yrange)
574
  @ w,y: width and height in pixels
575
  @ loop: 0 or 1 ( 1 = loop audio fragment)
576
  @ visible: 0 or 1 (1 = show controls)
577
  @ audio format may be in *.mp3 or *.ogg
578
  @ If you are using *.mp3: be aware that FireFox will not (never) play this ! (Pattented format)
579
  @ if you are using *.ogg: be aware that Microsoft based systems not support it natively
580
  @ To avoid problems supply both types (mp3 and ogg) of audiofiles.<br>the program will use both as source tag
581
  */
582
          js_function[DRAW_AUDIO] = 1;
583
          for(i=0;i<7;i++){
584
            switch(i){
585
              case 0: int_data[0] = x2px(get_real(infile,0)); break; /* x in x/y-range coord system -> pixel */
586
              case 1: int_data[1] = y2px(get_real(infile,0)); break; /* y in x/y-range coord system  -> pixel */
587
              case 2: int_data[2] = (int) (get_real(infile,0)); break; /* pixel width */
588
              case 3: int_data[3] = (int) (get_real(infile,0)); break; /* height pixel height */
589
              case 4: int_data[4] = (int) (get_real(infile,0)); if(int_data[4] != TRUE){int_data[4] = FALSE;} break; /* loop boolean */
590
              case 5: int_data[5] = (int) (get_real(infile,0)); if(int_data[5] != TRUE){int_data[5] = FALSE;} break; /* visible boolean */
591
              case 6:
592
                temp = get_string(infile,1);
593
                if( strstr(temp,".mp3") != 0 ){ temp = str_replace(temp,".mp3","");}
594
                if( strstr(temp,".ogg") != 0 ){ temp = str_replace(temp,".ogg","");}
18557 bpr 595
                tmp_buffer=my_newmem(MAX_BUFFER);
596
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_audio(%d,%d,%d,%d,%d,%d,%d,\"%s.ogg\",\"%s.mp3\");\n", canvas_root_id, int_data[0],int_data[1],int_data[2],int_data[3],int_data[4],int_data[5],temp,temp));
18552 bpr 597
                add_to_buffer(tmp_buffer);
598
                break;
599
              default:break;
600
            }
601
          }
602
          reset();
603
          break;
604
        case AXIS_NUMBERING:
605
  /*
18556 bpr 606
  @ axisnumbering
607
  @ keyword (no arguments required)
608
  @ for special numbering of x-axis or y-axis see grid related commands <a href="#axis">axis</a> <a href="#xaxis">xaxis</a>, <a href="#xaxisup">xaxisup</a>, <a href="#noxaxis">noxaxis</a>, <a href="#yaxis">yaxis</a>, <a href="#yaxisup">yaxisup</a>, <a href="#noyaxis">noyaxis</a>
609
  @ to be used before command grid (see <a href="#grid">command grid</a>)
18552 bpr 610
  */
611
          use_axis_numbering++;
612
          break;
613
        case AXIS:
614
  /*
18556 bpr 615
  @ axis
616
  @ keyword (no arguments required)
617
  @ to be used before command grid (see <a href="#grid">command grid</a>)
8386 schaersvoo 618
 
18552 bpr 619
  */
620
          use_axis = TRUE;
621
          break;
622
        case BARCHART:
623
  /*
624
  @ barchart x_1:y_1:color_1:x_2:y_2:color_2:...x_n:y_n:color_n
625
  @ may <b>only</b> to be used together with command <a href='#grid'>grid</a>
626
  @ can be used together with freestyle x-axis/y-axis texts: see commands <a href='#xaxis'>xaxis</a>,<a href='#xaxisup'>xaxisup</a> and <a href='#yaxis'>yaxis</a>
627
  @ use command <a href='#legend'>legend</a> to provide an optional legend in right-top-corner
628
  @ multiple barchart command may be used in a single script
629
  @ also see command <a href='#piechart'>piechart</a>
630
  @ note: your arguments are not checked by canvasdraw: use your javascript console in case of trouble...
631
  @%barchart%size 400,400%xrange -1,10%yrange -2,14%legend legend Z:legend A:this is B:C:D:E:F:G:H:X%legendcolors green:red:orange:lightblue:cyan:gold:purple:darkred:yellow:lightgreen%xaxis 0:Z:1:A:2:B:3:C:4:D:5:E:6:F:7:G:8:H:9:X%noyaxis%precision 1%fontfamily bold 15px Arial%grid 1,1,white%barchart 0:5.5:green:2:5.5:red:4:6.5:orange:6:8:lightblue:8:11:cyan:1:5.5:gold:3:9:purple:5:4:darkred:7:7:yellow:9:1:lightgreen%mouse red,14
632
  */
633
          temp = get_string(infile,1);
634
          if( strstr( temp,":" ) != 0 ){ temp = str_replace(temp,":","\",\""); }
635
          fprintf(js_include_file,"var barchart_%d = [\"%s\"];",barchart_cnt,temp);
636
          barchart_cnt++;
637
          reset();
638
          break;
639
        case BEZIER:
640
  /*
641
  @ bezier color,x_start,y_start,x_first,y_first,x_second,y_second,x_end,y_end
642
  @ draw a bezier curve between points, starting from (x_start:y_start)
643
  @ can <b>not</b> be dragged or set onclick
644
  */
645
          js_function[DRAW_BEZIER] = 1;
646
          decimals = find_number_of_digits(precision);
647
          for(i = 0 ; i < 9; i++){
648
            switch(i){
649
              case 0: stroke_color = get_color(infile,0);break;
650
              case 1: double_data[0] = get_real(infile,0);break;/* start x */
651
              case 2: double_data[1] = get_real(infile,0);break;/* start y */
652
              case 3: double_data[2] = get_real(infile,0);break;/*The x-coordinate of the first Bézier control point */
653
              case 4: double_data[3] = get_real(infile,0);break;/*The y-coordinate of the first Bézier control point */
654
              case 5: double_data[4] = get_real(infile,0);break;/*The x-coordinate of the second Bézier control point */
655
              case 6: double_data[5] = get_real(infile,0);break;/*The y-coordinate of the second Bézier control point */
656
              case 7: double_data[6] = get_real(infile,0);break;/*The x-coordinate of the Bézier end point */
657
              case 8: double_data[7] = get_real(infile,1);/*The y-coordinate of the Bézier end point */
658
                if(use_rotate == TRUE ){rotate(8,angle,rotationcenter,2);}
659
                if(use_affine == TRUE ){ transform(2,5);}
18557 bpr 660
                tmp_buffer=my_newmem(MAX_BUFFER);
661
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"draw_bezier(%d,%d,[%f,%f,%f,%f,%f,%f,%f,%f],\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.2f);",STATIC_CANVAS,line_width,double_data[0],double_data[1],double_data[2],double_data[3],double_data[4],double_data[5],double_data[6],double_data[7],fill_color,fill_opacity,stroke_color,stroke_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle));
18552 bpr 662
                add_to_buffer(tmp_buffer);
663
                break;
664
              default: break;
665
            }
666
          }
667
          reset();
668
          break;
669
        case BGCOLOR:
670
  /*
18556 bpr 671
  @ bgcolor colorname or #hex
672
  @ use this color as background of the "div" containing the canvas(es)
673
  @%bgcolor%size 400,400%xrange -10,10%yrange -10,10%bgcolor lightblue
18552 bpr 674
  */
675
  /* [255,255,255]*/
676
          bgcolor = get_string(infile,1);
677
          if(strstr(bgcolor,"#") == NULL){ /* convert colorname -> #ff00ff */
678
            int found = 0;
679
            for( i = 0; i < NUMBER_OF_COLORNAMES ; i++ ){
680
              if( strcmp( colors[i].name , bgcolor ) == 0 ){
681
                bgcolor = colors[i].hex;
682
                found = 1;
683
              break;
684
              }
685
            }
686
            if(found == 0){canvas_error("your bgcolor is not in my rgb.txt data list: use hexcolor...something like #a0ffc4");}
687
          }
688
          fprintf(js_include_file,"/* set background color of canvas div */\ncanvas_div.style.backgroundColor = \"%s\";canvas_div.style.opacity = %f;\n",bgcolor,fill_opacity);
689
          break;
690
        case BGIMAGE:
691
  /*
18556 bpr 692
  @ bgimage image_location
693
  @ use an image as background; technical: we use the background of ''canvas_div``
694
  @ the background image will be resized to match "width = xsize" and "height = ysize"
695
  @%bgimage%size 400,400%xrange -10,10%yrange -10,10%bgimage https://wims.unice.fr/wims/gifs/en.gif
18552 bpr 696
  */
697
          URL = get_string(infile,1);
698
          fprintf(js_include_file,"/* set background image to canvas div */\ncanvas_div.style.backgroundImage = \"url(%s)\";canvas_div.style.backgroundSize = \"%dpx %dpx\";\n",URL,xsize,ysize);
699
          break;
700
        case BLINK:
701
  /*
18556 bpr 702
  @ blink time(seconds)
703
  @ NOT IMPLEMETED -YET
18552 bpr 704
  */
705
          break;
706
        case BOXPLOT:
707
  /*
708
  @ boxplot x_or_y,box-height_or_box-width,position,min,Q1,median,Q3,max
709
  @ example:<br><code>xrange 0,300<br>yrange 0,10<br>boxplot x,4,8,120,160,170,220,245</code><br>meaning: create a boxplot in x-direction, with height 4 (in yrange) and centered around line y=8
710
  @ example:<br><code>xrange 0,10<br>yrange 0,300<br>boxplot y,4,8,120,160,170,220,245</code><br>meaning: create a boxplot in y-direction, with width 4 (in xrange) and centered around line x=8
711
  @ use command <a href='#filled'>filled</a> to fill the box<br><b>note:</b> the strokecolor is used for filling Q1, the fillcolor is used for filling Q3
712
  @ use command <a href='#fillpattern'>fillpattern some_pattern</a> to use a (diamond for Q1, hatch for Q3) pattern.
18627 bpr 713
  @ use command <a href='#opacity'>opacity</a> to adjust fill_opacity of stroke and fill colors
18552 bpr 714
  @ use command <a href='#legend'>legend</a> to automatically create a legend <br>unicode allowed in legend<br>use command <a href='#fontfamily'>fontfamily</a> to set the font of the legend.
715
  @ there is no limit to the number of boxplots used.
716
  @ can <b>not</b> be set draggable and <a href='#onclick'>onclick</a> is not ready yet
717
  @ use keyword <a href="#userboxplot">userboxplot</a> before command boxplot, if a pupil must draw a boxplot (using his own min,Q1,median,Q3,max data)
718
  @ use keyword <a href="#userboxplotdata">userboxplotdata</a> before command boxplot, if a pupil must generate the data by some means.
719
  @ use command <a href="#boxplotdata">boxplotdata</a> when the boxplot should be drawn from wims-generated raw statistical date
720
  @%boxplot_1%size 400,400%xrange 0,300%yrange 0,10%opacity 120,50%filled%fillcolor orange%strokecolor blue%linewidth 2%boxplot x,4,8,120,160,170,220,245
721
  @%boxplot_2%size 400,400%xrange 0,10%yrange 0,300%opacity 120,50%filled%fillcolor orange%strokecolor blue%linewidth 2%boxplot y,4,8,120,160,170,220,245
722
  @%boxplot_3%size 400,400%xrange 0,100%yrange 0,10%fillpattern hatch%linewidth 3%fillcolor red%strokecolor green%boxplot x,1,2,4,14,27,39,66%strokecolor blue%boxplot x,1,4,15,45,50,66,87%strokecolor red%boxplot x,1,6,45,70,80,90,100%strokecolor orange%boxplot x,1,8,28,38,48,56,77%mouse red,16
723
  */
724
          js_function[DRAW_BOXPLOT] = 1;
725
          for(i=0;i<8;i++){
726
            switch(i){
727
              case 0: temp = get_string_argument(infile,0);
728
                if( strstr(temp,"x") != 0){int_data[0] = 1;}else{int_data[0] = 0;} break; /* x or y */
729
              case 1: double_data[0] = get_real(infile,0);break;/* height | width  */
730
              case 2:
731
                if( js_function[DRAW_JSBOXPLOT] == 0 ){
732
                  double_data[1] = get_real(infile,0);
733
                  fprintf(js_include_file,"var boxplot_source = 0;\n");/* we use given min,Q1,median,Q3,max */
734
                }
735
                else {
736
                  double_data[1] = get_real(infile,1);
737
                  double_data[2] = 1;
738
                  double_data[3] = 1;
739
                  double_data[4] = 1;
740
                  double_data[5] = 1;
741
                  double_data[6] = 1;
742
                  double_data[7] = 1;
743
                  i=8;
744
                }
745
                break;/* center value x or y */
746
              case 3: double_data[2] = get_real(infile,0); break;/* min */
747
              case 4: double_data[3] = get_real(infile,0); break;/* Q1 */
748
              case 5: double_data[4] = get_real(infile,0); break;/* median */
749
              case 6: double_data[5] = get_real(infile,0); break;/* Q3 */
750
              case 7: double_data[6] = get_real(infile,1); break;/* max */
751
              default:break;
752
            }
753
          }
754
          decimals = find_number_of_digits(precision);
755
          /*function draw_boxplot(canvas_type,xy,hw,cxy,data,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1)*/
18557 bpr 756
          tmp_buffer=my_newmem(MAX_BUFFER);
757
          check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"draw_boxplot(%d,%d,%.*f,%.*f,[%.*f,%.*f,%.*f,%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d);\n",BOXPLOT_CANVAS+boxplot_cnt,int_data[0],decimals,double_data[0],decimals,double_data[1],decimals,double_data[2],decimals,double_data[3],decimals,double_data[4],decimals,double_data[5],decimals,double_data[6],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1]));
18552 bpr 758
          add_to_buffer(tmp_buffer);
759
          boxplot_cnt++;
760
          reset();
761
          break;
762
        case BOXPLOTDATA:
763
  /*
764
  @ boxplotdata some_data
765
  @ 'some_data' are a list of numbers separated by a comma "," (items)
766
  @ only be used before command <code>boxplot</code>: the command <a href="#boxplot">boxplot</a> will provide the boxplot drawing of the data.
767
  @ xrange 0,100<br>yrange 0,10<br>boxplotdata 11,22,13,15,23,43,12,12,14,2,45,32,44,13,21,24,13,19,35,21,24,23<br>boxplot x,4,5
768
  @ note: wims will not check your data input | format. use js-error console to debug any problems.
769
  @ a javascript function <code>statistics()</code> will parse the data and calculate the values [min,Q1,median,Q3,max] and hand them to the boxplot draw function.
770
  @ only a single call to <code>boxplotdata</code> can be made. If multiple boxplots should be present in a single canvas, then use multiple calls to command <a href='#boxplot'>boxplot</a>
771
  @%boxplotdata%size 400,400%xrange 0,100%yrange 0,10%strokecolor orange%fillpattern hatch%linewidth 3%strokecolor green%boxplotdata 11,22,13,15,23,43,12,12,14,2,45,32,44,13,21,24,13,19,35,21,24,23%boxplot x,2,2%mouse red,16
772
  */
773
          js_function[DRAW_JSBOXPLOT] = 1;
774
          js_function[DRAW_BOXPLOT] = 1;
775
          fprintf(js_include_file,"var boxplot_source = 1;var jsboxplot_data = [%s];\n",get_string(infile,1));
776
          break;
777
        case CANVASTYPE:
778
          canvas_type = (int) (get_real(infile,1));
779
  /*
780
  @ canvastype TYPE
781
  @ for now only useful before commands filltoborder / floodfill / clickfill etc operations<br>Only the images of this TYPE will be scanned and filled
782
  @ default value of TYPE is DRAG_CANVAS e.g. 5 (all clickable / draggable object are in this canvas)
783
  @ use another TYPE, if you know what you are doing...
18627 bpr 784
  @ other possible canvasses (e.g. transparent PNG pictures, xsize &times; ysize on top of each other)<ul><li>EXTERNAL_IMAGE_CANVAS 0</li><li>BG_CANVAS   1</li><li> STATIC_CANVAS  2</li><li> MOUSE_CANVAS  3</li><li> GRID_CANVAS  4</li><li> DRAG_CANVAS  5</li><li> DRAW_CANVAS  6</li><li> TEXT_CANVAS  7</li><li> CLOCK_CANVAS  8</li><li> ANIMATE_CANVAS  9</li><li> TRACE_CANVAS  10</li><li>BOXPLOT_CANVAS 11</li><li> JSPLOT_CANVAS  100, will increase with every call</li><li> FILL_CANVAS  200, will increase with every call</li><li> USERDRAW_JSPLOT 300, will increase with every call</li><li>CLICKFILL_CANVAS 400, will increase with every call/click</li><li>BOXPLOT_CANVAS 500, will increase with every call</li></ul>
18552 bpr 785
  */
786
          break;
787
        case CENTERED:
788
          use_offset = 4;
789
   /*
18556 bpr 790
  @ centered
791
  @ keyword ; to place the text centered (in width and height) on the text coordinates(x:y)
792
  @ may be used for text exactly centered on its (x;y)
793
  @ use <a href="#fontfamily">fontfamily</a> for setting the font
794
  @ may be active for commands <a href="#text">text</a> and <a href="#string">string</a> (e.g. objects in the ''drag/drop/onclick-library``)
795
  @%centered%size 400,400%xrange -10,10%yrange -10,10%fontfamily 12pt Arial%string blue,-9,-9,no offset%point -9,-9,red%centered%string blue,-6,-6,centered%point -6,-6,red%xoffset%string blue,-3,-3,xoffset%point -3,-3,red%yoffset%string blue,0,0,yoffset%point 0,0,red%xyoffset%string blue,3,3,xyoffset%point 3,3,red%resetoffset%string blue,6,6,resetoffset%point 6,6,red
18552 bpr 796
  */
18556 bpr 797
          break;
18552 bpr 798
        case CENTERSTRING:
799
  /*
18556 bpr 800
  @ centerstring color,y-value,the text string
801
  @ title color,y-value,the text string
802
  @ draw a string centered on the canvas at y = y-value
803
  @ can not be set ''onclick`` or ''drag xy`` (...)
804
  @ unicode supported: <code>centerstring red,5,\\u2232</code>
805
  @ use a command like <code>fontfamily italic 24pt Arial</code> to set fonts on browser that support font change
806
  @%centerstring%size 400,400%xrange -10,10%yrange -10,10%bgcolor lightblue%fontfamily italic 22pt Courier%centerstring blue,7,the center
18552 bpr 807
  */
808
          js_function[DRAW_CENTERSTRING] = 1;
809
          for(i=0;i<3;i++){
810
            switch(i){
811
              case 0: stroke_color = get_color(infile,0);break;/* name or hex color */
812
              case 1: double_data[0] = get_real(infile,0);break; /* y in xrange*/
813
              case 2: temp = get_string_argument(infile,1);
814
                /* draw_text = function(canvas_type,y,font_family,stroke_color,stroke_opacity,text) */
815
                decimals = find_number_of_digits(precision);
18557 bpr 816
                tmp_buffer=my_newmem(MAX_BUFFER);
817
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_centerstring(%d,%.*f,\"%s\",\"%s\",%.2f,\"%s\");\n",canvas_root_id,decimals,double_data[0],font_family,stroke_color,stroke_opacity,temp));
18552 bpr 818
                add_to_buffer(tmp_buffer);
819
                break;
820
              default:break;
821
            }
822
          }
823
          break;
824
        case CHEMTEX:
825
  /*
826
  chemtex
827
  keyword...needs to be the first command in the script (even before the ''size`` command)
828
  only for KaTeX enabled typesetting !
829
  will include 80kB large js-library for chemisty typesetting
830
  using <a href="http://85.148.206.56/wims/download/katex.for.wims.tar.gz">KaTeX</a> : <code>katex x,y,\\ce{ chemistry tex code} like : \\ce{ Hg^2+ ->[I-] HgI2 ->[I-] [Hg^{II}I4]^2- }</code>
831
  using MathJaX : <code>latex x,y,\\ce{ chemistry tex code} like : \\ce{ Hg^2+ ->[I-] HgI2 ->[I-] [Hg^{II}I4]^2- }</code>
832
  see https://mhchem.github.io/MathJax-mhchem/
833
  %chemtex_katex_mathjax%chemtex%size 400,400%xrange -10,10%yrange -10,10%snaptogrid%fontfamily 22px Arial%strokecolor red%drag xy%centered%latex 0,8,\\ce{Hg^2+}%drag xy%centered%latex 0,4,\\ce{\\xrightarrow{\\text{I}^{-}}}%drag xy%centered%latex 0,0,\\ce{HgI2}%centered%drag xy%latex 0,-4,\\ce{\\xrightarrow{\\text{I}^{-}}}%drag xy%centered%latex 0,-8,\\ce{[Hg^{II}I4]^2-}
834
  */
835
          found_size_command = 1;
836
          fprintf(stdout,"\n<script src=\"scripts/js/KaTeX/mhchem.js\" defer></script>\n");
837
          break;
8386 schaersvoo 838
 
18552 bpr 839
        case CIRCLE:
840
  /*
841
  @ circle xc,yc,width (2*r in pixels),color
842
  @ use command <code>fcircle xc,yc,d,color</code>
843
  @ alternative: disk
844
  @ use command <code>fillcolor color</code> to set the fillcolor
845
  @ may be set <a href='#drag'>draggable</a> / <a href='#onclick'>onclick</a>
846
  @ will shrink / expand on zoom out / zoom in
847
  @%circle%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor lightblue%opacity 255,50%drag xy%circle 0,0,60,red%zoom red
848
  */
849
          for(i=0;i<4;i++){
850
            switch(i){
851
              case 0: double_data[0] = get_real(infile,0);break; /* x */
852
              case 1: double_data[1] = get_real(infile,0);break; /* y */
853
              case 2: double_data[2] = px2x((get_real(infile,0))/2) - px2x(0);break; /* for zoom in/out: radius in 'dx' xrange*/
854
              case 3: stroke_color = get_color(infile,1);/* name or hex color */
18623 bpr 855
                if(fillcolor) {fill_color=fillcolor;} else {fill_color=stroke_color;}
18552 bpr 856
                if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);}
857
                if(use_affine == TRUE ){ transform(2,2);}
858
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
859
                decimals = find_number_of_digits(precision);
18557 bpr 860
                tmp_buffer=my_newmem(MAX_BUFFER);
18623 bpr 861
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,13,[%.*f],[%.*f],[%.3f],[%.3f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[1],double_data[2],double_data[2],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 862
                add_to_buffer(tmp_buffer);
863
                if(onclick != 0){object_cnt++;}/* object_cnt++;*/
864
                dragstuff[13] = 1;
865
                if(use_dragstuff == 0 ){ use_dragstuff = 1; }
866
                reset();
867
                break;
868
              default : break;
869
            }
870
          }
871
          break;
872
        case CIRCLES:
873
  /*
874
  @ circles color,xc1,yc1,r1,xc2,yc2,r2...xc_n,yc_n,r_n
875
  @ <b>attention</b> r = radius in x-range (!)
876
  @ use keyword <code>filled</code> or command <code>fcircles</code> to produce solid circles
877
  @ alternative: disks
878
  @ use command <code>fillcolor color</code> to set the fillcolor
879
  @ may be set <a href='#drag'>draggable</a> / <a href='#onclick'>onclick</a> (individually)
880
  @ will shrink / expand on zoom out / zoom in
881
  @%circles_drag%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor lightblue%opacity 255,50%drag xy%circles blue,0,0,2,2,2,3,-3,-3,3,3,3,4,3,-4,2%zoom red
882
  @%circles_onclick%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor lightblue%opacity 255,50%onclick%circles blue,0,0,2,2,2,3,-3,-3,3,3,3,4,3,-4,2%zoom red
883
  @%circles_drag_slider%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%drag xy%# Click circles(s) to activate%opacity 200,50%fillcolor orange%rotationcenter 2,3%slider 0,2*pi,300,30,angle degrees,Rotate%slider -5,5*pi,300,30,x display,move in x-direction%slider -10,10*pi,300,30,y display,move in y-direction%fcircles blue,0,0,0.5,2,2,1,-3,-3,1.5,3,3,0.5,3,-4,0.5
884
  */
885
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
18623 bpr 886
          if(fillcolor) {fill_color=fillcolor;} else {fill_color=stroke_color;}
18552 bpr 887
          i=1;
888
          while( ! done ){     /* get next item until EOL*/
889
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
890
            switch (i%3){
891
              case 1:double_data[i-1] = get_real(infile,0);break; /* x */
892
              case 2:double_data[i-1] = get_real(infile,0);break; /* y */
893
              case 0:double_data[i-1] = get_real(infile,1);break; /* r */
894
            }
895
            i++;
896
          }
897
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,3);}
898
          if(use_affine == TRUE ){ transform(i-1,3);}
899
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
8386 schaersvoo 900
 
18552 bpr 901
          decimals = find_number_of_digits(precision);
902
          for(c = 0 ; c < i-1 ; c = c+3){
18557 bpr 903
            tmp_buffer=my_newmem(MAX_BUFFER);
18623 bpr 904
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,13,[%.*f],[%.*f],[%.3f],[%.3f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+1],double_data[c+2],double_data[c+2],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 905
            add_to_buffer(tmp_buffer);
906
            if(onclick != 0){object_cnt++;}/* object_cnt++; */
907
          }
908
          reset();
909
          dragstuff[13] = 1;
910
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
911
          break;
912
        case CLEARBUTTON:
913
  /*
18556 bpr 914
  @ clearbutton value
915
  @ alternative: delete
916
  @ alternative: erase
917
  @ adds a button to clear the <a href="#userdraw">userdraw</a> canvas with text ''value``
18572 bpr 918
  @ <b>attention</b> command <code>clearbutton</code> is incompatible with <a href="#multidraw">multidraw</a> based drawings<br>(in <code>multidraw</code> there is always a remove_object_button for every draw primitive)
18556 bpr 919
  @ normally <a href="#userdraw">userdraw</a> primitives have the option to use middle/right mouse button on<br> a point of the object to remove this specific object...this clear button will remove all drawings
920
  @ uses the tooltip placeholder div element: may not be used with command <code>intooltip</code>
921
  @ use command <a href="#css">css</a> to style the button...
922
  @ the clearbutton will have id="canvas_scripts[%d]" ; starting with %d=0 for the first script<br>to change the style of all ''clearbutton`` of all included canvasdraw scripts, use something like<br><code>if(document.getElementById("clearbutton"+canvas_scripts[0])){<br>&nbsp;var p = 0;<br>&nbsp;while(document.getElementById("clearbutton"+canvas_scripts[p])){<br>&nbsp;&nbsp;document.getElementById("clearbutton"+canvas_scripts[p]).className="some_class_name";<br>&nbsp;&nbsp;&lt;!&minus;&minus;</code> or <code>document.getElementById("clearbutton"+canvas_scripts[p]).setAttribute("style","some_style"); &minus;&minus;&gt;<br>&nbsp;&nbsp;p++;<br>&nbsp;};<br>};</code>
923
  @%clearbutton%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor lightblue%opacity 255,50%userdraw circles,red%clearbutton Remove All
18552 bpr 924
  */
925
          if(reply_format == 29){/* eg multidraw is selected */
926
  // canvas_error("command clearbutton incompatible with multidraw...only suitable for userdraw");
927
          }
928
          add_clear_button(css_class,get_string(infile,1));
929
          break;
930
        case CLOCK:
931
  /*
932
  @ clock x,y,r(px),H,M,S,type hourglass,interactive [ ,H_color,M_color,S_color,background_color,foreground_color ]
933
  @ use command <code>opacity stroke-opacity,fill-opacity</code> to adjust foreground (stroke) and background (fill) transparency
934
  @ type hourglass:<br>type = 0: only segments<br>type = 1: only numbers<br>type = 2: numbers and segments
18627 bpr 935
  @ colors are optional: if not defined, default values will be used<br>default colors: clock 0,0,60,4,35,45,1,2<br>custom colors: clock 0,0,60,4,35,45,1,2,,,,yellow,red<br>custom colors: clock 0,0,60,4,35,45,1,2,white,green,blue,black,yellow
18552 bpr 936
  @ if you don't want a seconds hand (or minutes...), just make it invisible by using the background color of the hourglass...
937
  @ interactive <ul><li>0: not interactive, just clock(s)</li><li>1: function read_canvas() will read all active clocks in H:M:S format<br>The active clock(s) can be adjusted by pupils</li><li>2: function read_canvas() will return the clicked clock <br>(like multiplechoice; first clock in script in nr. 0 )</li><li>3: no prefab buttons...create your own buttons (or other means) to make the clock(s) adjustable by javascript function set_clock(num,type,diff)<br>wherein: num = clock id (starts with 0) ; type = 1 (hours) ; type = 2 (minutes) ; type = 3 (seconds) <br>and diff = the increment of 'type' (positive or negative)</li></ul>
938
  @ canvasdraw will not check validity of colornames...the javascript console is your best friend
939
  @ no combinations with other reply_types allowed, for now
940
  @ if interactive is set to ''1``, 6 buttons per clock will be displayed for adjusting a clock (H+ M+ S+ H- M- S-)<br> set_clock(clock_id,type,incr) <br>first clock has clock_id=0 ; type: H=1,M=2,S=3 ; incr: increment integer
18627 bpr 941
  @ note: if you need multiple -interactive- clocks on a webpage, use multiple ''clock`` commands in a single script<br>and <i>not multiple canvas scripts</i> in a single page
18552 bpr 942
  @ note: clocks will not zoom or pan, when using command <a href='#zoom'>zoom</a>
943
  @%clock_1%size 400,400%xrange -10,10%yrange -10,10%clock 0,0,120,4,35,45,0,0,red,green,blue,lightgrey,black
944
  @%clock_2%size 400,400%xrange -10,10%yrange -10,10%clock 0,0,120,4,35,45,1,1,red,green,blue,lightgrey,black
945
  @%clock_3%size 400,400%xrange -10,10%yrange -10,10%clock -5,0,80,4,35,45,2,2,red,green,blue,lightgrey,black%clock 5,0,80,3,15,65,2,2,red,green,blue,lightgrey,black
946
  @%clock_4%size 400,400%xrange -10,10%yrange -10,10%clock 0,0,120,4,35,45,0,0,red,green,blue,lightgrey,black
947
  @%clock_5%size 400,400%xrange -10,10%yrange -10,10%clock 0,0,120,4,35,45,1,1,red,green,blue,lightgrey,black
948
  @%clock_6%size 400,400%xrange -10,10%yrange -10,10%clock -5,0,80,4,35,45,2,2,red,green,blue,lightgrey,black%clock 5,0,80,8,55,15,2,2,red,green,blue,lightgrey,black
949
  @%clock_7%size 400,400%xrange -10,10%yrange -10,10%clock 0,0,120,4,35,45,2,0,red,green,blue,lightgrey,black
950
  */
951
          js_function[DRAW_CLOCK] = 1;
952
          js_function[INTERACTIVE] = 1;
8386 schaersvoo 953
 
18552 bpr 954
  /*    var clock = function(xc,yc,radius,H,M,S,h_color,m_color,s_color,bg_color,fg_color) */
955
          for(i=0;i<9;i++){
956
            switch(i){
957
              case 0: int_data[0] = x2px(get_real(infile,0)); break; /* xc */
958
              case 1: int_data[1] = y2px(get_real(infile,0)); break; /* yc */
959
              case 2: int_data[2] = get_real(infile,0);break;/* radius in px */
960
              case 3: int_data[3] = get_real(infile,0);break;/* hours */
961
              case 4: int_data[4] = get_real(infile,0);break;/* minutes */
962
              case 5: int_data[5] = get_real(infile,0);break;/* seconds */
963
              case 6: int_data[6] = get_real(infile,0);if(int_data[6] < 0 || int_data[6] > 2){canvas_error("hourglass can be 0,1 or 2");}break;/* type hourglass */
964
              case 7: int_data[7] = (int)(get_real(infile,1));/* interactive 0,1,2*/
965
                switch(int_data[7]){
966
                  case 0:break;
967
                  case 1:
968
                    if(clock_cnt == 0){
969
                      if( reply_format == 0 ){
970
                        reply_format = 18; /* user sets clock */
18557 bpr 971
                  /*
972
                     tmp_buffer=my_newmem(MAX_BUFFER);
973
                     check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "set_clock = function(num,type,diff){var name = eval(\"clocks\"+num);switch(type){case 1:name.H = parseInt(name.H+diff);break;case 2:name.M = parseInt(name.M+diff);break;case 3:name.S = parseInt(name.S+diff);break;default: break;};name = clock(name.xc,name.yc,name.radius,name.H,name.M,name.S,name.type,name.interaction,name.H_color,name.M_color,name.S_color,name.bg_color,name.fg_color);};\n"));
18552 bpr 974
                     add_to_buffer(tmp_buffer);
975
                 */
976
                        fprintf(js_include_file,"set_clock = function(num,type,diff){if(wims_status == \"done\"){return;};var name = eval(\"clocks\"+num);switch(type){case 1:name.H = parseInt(name.H+diff);break;case 2:name.M = parseInt(name.M+diff);break;case 3:name.S = parseInt(name.S+diff);break;default: break;};name = new clock(name.xc,name.yc,name.radius,name.H,name.M,name.S,name.type,name.interaction,name.H_color,name.M_color,name.S_color,name.bg_color,name.fg_color);};\n");
977
                      }
978
                      else {
979
                        canvas_error("interactive clock may not be used together with other reply_types...");
980
                      }
981
                    }
982
                    fprintf(stdout,"<p style=\"text-align:center\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,1,1)\" value=\"H+\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,2,1)\" value=\"M+\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,3,1)\" value=\"S+\"><br><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,1,-1)\" value=\"H&minus;\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,2,-1)\" value=\"M&minus;\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,3,-1)\" value=\"S&minus;\"></p>",css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt);
983
                    break;
984
                  case 3:
985
                    if(clock_cnt == 0){
986
                      if( reply_format == 0 ){
987
                        reply_format = 18; /* user sets clock */
988
                        fprintf(js_include_file,"set_clock = function(num,type,diff){if(wims_status == \"done\"){return;};var name = eval(\"clocks\"+num);switch(type){case 1:name.H = parseInt(name.H+diff);break;case 2:name.M = parseInt(name.M+diff);break;case 3:name.S = parseInt(name.S+diff);break;default: break;};name = new clock(name.xc,name.yc,name.radius,name.H,name.M,name.S,name.type,1,name.H_color,name.M_color,name.S_color,name.bg_color,name.fg_color);};\n");
989
                       }
990
                      else {
991
                        canvas_error("interactive clock may not be used together with other reply_types...");
992
                      }
993
                    }
994
          /*
995
          fprintf(stdout,"<p style=\"text-align:center\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,1,1)\" value=\"H+\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,2,1)\" value=\"M+\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,3,1)\" value=\"S+\"><br><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,1,-1)\" value=\"H&minus;\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,2,-1)\" value=\"M&minus;\"><input class=\"%s\" type=\"button\" onclick=\"javascript:set_clock(%d,3,-1)\" value=\"S&minus;\"></p>",css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt,css_class,clock_cnt);
996
         */
997
                  break;
998
                  case 2:
999
                    if( reply_format == 0 ){
1000
                      reply_format = 19; /* "onclick */
1001
                      js_function[INTERACTIVE] = 1;
1002
                      fprintf(js_include_file,"\n/* begin onclick handler for clocks */\nvar reply = new Array();canvas_div.addEventListener( 'mousedown', user_click,false);\n\nfunction user_click(evt){if(evt.button == 1){var canvas_rect = clock_canvas.getBoundingClientRect();var x = evt.clientX - canvas_rect.left;var y = evt.clientY - canvas_rect.top;var p = 0;var name;var t = true;while(t){try{name = eval('clocks'+p);if( x < name.xc + name.radius && x > name.xc - name.radius ){if( y < name.yc + name.radius && y > name.yc - name.radius ){reply[0] = p;name = new clock(name.xc,name.yc,name.radius,name.H,name.M,name.S,name.type,name.interaction,name.H_color,name.M_color,name.S_color,\"lightblue\",name.fg_color);};}else{clock_ctx.clearRect(name.xc-name.radius,name.yc-name.radius,name.xc+name.radius,name.yc+name.radius);name = new clock(name.xc,name.yc,name.radius,name.H,name.M,name.S,name.type,name.interaction,name.H_color,name.M_color,name.S_color,name.bg_color,name.fg_color);};p++;}catch(e){t=false;};};};};\n");
1003
                    }
1004
                    else {
1005
                      if( reply_format != 19){
1006
                        canvas_error("clickable clock(s) may not be used together with other reply_types...");
1007
                      }
1008
                    }
1009
                    break;
1010
                  default: canvas_error("interactive must be set 0,1 or 2");break;
1011
                }
1012
                break;
1013
              case 8:
1014
                if(clock_cnt == 0 ){ /* set opacity's just once .... it should be a argument to clock(), for now it's OK */
1015
                  fprintf(js_include_file,"var clock_bg_opacity = %.2f;var clock_fg_opacity = %.2f;",fill_opacity,stroke_opacity);
1016
                }
1017
                temp = get_string(infile,3);/* optional colors, like: ,,red,,blue*/
1018
                if( strstr( temp,",") != 0 ){ temp = str_replace(temp,",","\",\""); }
1019
                else{
1020
                /* h_color,m_color,s_color,bg_color,fg_color */
1021
                  temp = ",black\",\"black\",\"black\",\"white\",\"black";}
18557 bpr 1022
                tmp_buffer=my_newmem(MAX_BUFFER);
1023
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "clocks%d = new clock(%d,%d,%d,%d,%d,%d,%d,%d,\"%s\");\n",clock_cnt,int_data[0],int_data[1],int_data[2],int_data[3],int_data[4],int_data[5],int_data[6],int_data[7],temp));
18552 bpr 1024
                add_to_buffer(tmp_buffer);
1025
                fprintf(js_include_file,"var clocks%d;",clock_cnt);
1026
                clock_cnt++;
1027
                break;
1028
              default:break;
1029
            }
1030
          }
1031
          break;
1032
        case COLORPALETTE:
1033
  /*
18556 bpr 1034
  @ colorpalette color_name_1,color_name_2,...,color_name_8
1035
  @ opacity will be the same for all colors and is set by command <a href="#opacity">opacity [0-255],[0-255]</a>
1036
  @ can be used with command <a href='#userdraw'>userdraw clickfill,color</a> when more than one fillcolor is wanted.<br>in that case use for example <a href='#replyformat'>replyformat 10</a> ... reply=x1:y1:color1,x2:y2:color2...<br>the pupil can choose from the given colors by clicking small coloured buttons.<br> the click coordinates and corresponding fillcolor will be stored in read_canvas()...when using the appropriate replyformat.<br>the first color of the palette is color=0
18642 schaersvoo 1037
  @ make sure to include the ''remove button`` by using command <a href='#clearbutton'>clearbutton some_text</a><br/>please note: right mouse click will alse remove last added item...
1038
  @%colorpalette%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%circles blue,0,0,4,1,1,6,3,3,3,-3,-3,5%opacity 255,100%colorpalette red,green,yellow,blue%userdraw clickfill,green%clearbutton REMOVE
18552 bpr 1039
  */
1040
          if( use_tooltip == 1 ){canvas_error("command 'colorpalette' is incompatible with command 'intooltip tip_text'");}
1041
          fprintf(js_include_file,"var multifillcolors = [];var palettecolors = [");
1042
          while( ! done ){
1043
            temp = get_color(infile,1);
18642 schaersvoo 1044
            fprintf(js_include_file,"\"%s,%d\",",temp,(int) (255*fill_opacity));
18552 bpr 1045
          }
1046
          fprintf(js_include_file,"];");/* add black to avoid trouble with dangling comma... */
1047
          add_color_palette(css_class);
1048
          break;
15111 schaersvoo 1049
 
18552 bpr 1050
        case COMMENT:
1051
          sync_input(infile);
1052
          break;
11806 schaersvoo 1053
 
18552 bpr 1054
        case COPY:
1055
  /*
1056
  @ copy x,y,x1,y1,x2,y2,[filename URL]
1057
  @ The image may be "bitmap" or "SVG"
1058
  @ Insert the region from (x1,y1) to (x2,y2) (in pixels) of [filename] to (x,y) in x/y-range
1059
  @ If x1=y1=x2=y2=-1, the whole [filename URL] is copied.
1060
  @ [filename] is the URL of the image
1061
  @ <em>TODO:move special image functions to generic 'dragstuff' library</em>
1062
  @ URL is normal URL of network reachable image file location
1063
  @ if command <a href="#drag">drag x/y/xy</a> is set before command ''copy``, the images will be draggable<br>javascript function read_canvas(); will return the x/y coordinate data in xrange/yrange of all -including non draggable- images<br>the command drag is only valid for the next image<br>draggable / non-draggable images may be mixed<br>may be used together with preceding keywords ''snaptogrid``, ''xsnaptogrid``, ''ysnaptogrid`` or <code>snaptopoints x1,y1,x2,y2...</code>.
1064
  @ if keyword <a href="#onclick">onclick</a> is set before command ''copy`` the image(s) is clickable (marked with a green rectangle around the image)<br>use 'read_dragdrop' to get the number of the clicked image(s)<br>use command 'clearbutton some_text' to reset the reply/click array.<br>example: 4 images; student clicked on image 2 and 3: reply = 0,1,1,0<br>after clicking the clear button: reply = 0,0,0,0<br>May be mixed with commands ''drag x|y|xy`` (use javascript read_canvas to get the new coordinates
1065
  @ ''onclick`` for external images may be mixed with canvas generated stuff (like lines,curves, embeded XML etc)
1066
  @ you may draw / userdraw / drag other stuff on top of an "imported" image
1067
  @ the use of a slider is not possible: if needed, use command <a href='#html'>html x,y,&lt;img src=my_image.svg /&gt; </a>
1068
  @ use keyword <a href='#centered'>centered</a> before command ''copy`` to place image center at given coordinates.
1069
  @%copy_onclick%size 400,400%xrange -10,10%yrange -10,10%onclick%copy -5,5,-1,-1,-1,-1,gifs/fr.gif%onclick%copy 5,5,-1,-1,-1,-1,gifs/en.gif%onclick%copy 5,-5,-1,-1,-1,-1,gifs/it.gif%onclick%copy -5,-5,-1,-1,-1,-1,gifs/cn.gif
1070
  @%copy_drag_xy%size 400,400%xrange -10,10%yrange -10,10%# attention: left mouse click on the image will activate dragging...%# keep left mouse button pressed while moving the image !%drag xy%copy -5,5,-1,-1,-1,-1,gifs/fr.gif%drag xy%copy 5,5,-1,-1,-1,-1,gifs/en.gif%drag xy%copy 5,-5,-1,-1,-1,-1,gifs/it.gif%drag xy%copy -5,-5,-1,-1,-1,-1,gifs/cn.gif
1071
  @%copy_drag_xy_snaptogrid%size 400,400%xrange -10,10%yrange -10,10%grid 2,2,grey%# attention: left mouse click on the image will activate dragging...%# keep left mouse button pressed while moving the image !%drag xy%# a function read_canvas_images() %copy -6,6,-1,-1,-1,-1,gifs/fr.gif%snaptogrid%drag xy%copy 6,6,-1,-1,-1,-1,gifs/en.gif%snaptogrid%drag xy%copy 6,-6,-1,-1,-1,-1,gifs/it.gif%snaptogrid%drag xy%copy -6,-6,-1,-1,-1,-1,gifs/cn.gif
1072
  */
1073
          for(i = 0 ; i<7;i++){
1074
            switch(i){
1075
              case 0: double_data[0]=get_real(infile,0);break; /* x left top corner in x/y range  */
1076
              case 1: double_data[1]=get_real(infile,0);break; /* y left top corner in x/y range */
1077
              case 2: int_data[2]=(int)(get_real(infile,0));break;/* x1 in px of external image */
1078
              case 3: int_data[3]=(int)(get_real(infile,0));break;/* y1 in px of external image */
1079
              case 4: int_data[4]=(int)(get_real(infile,0));break;/* x2 --> width  */
1080
              case 5: int_data[5]=(int)(get_real(infile,0)) ;break;/* y2 --> height */
1081
              case 6: URL = get_string(infile,1);
1082
                if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);}
1083
                if(use_affine == TRUE ){transform(2,2);}
1084
                int_data[0] = x2px(double_data[0]);
1085
                int_data[1] = y2px(double_data[1]);
1086
                int_data[6] = int_data[4] - int_data[2];/* swidth & width (if not scaling )*/
1087
                int_data[7] = int_data[5] - int_data[3];/* sheight & height (if not scaling )*/
1088
                if( onclick == 0 ){ /* no mouse needed static image copy  */
1089
                  if(js_function[DRAW_EXTERNAL_IMAGE] == 0){/* create canvas just once */
1090
                    fprintf(js_include_file,"var image_copy_canvas = create_canvas%d(%d,xsize,ysize);",canvas_root_id,STATIC_IMAGE_CANVAS);
1091
                    js_function[DRAW_EXTERNAL_IMAGE] = 1;
1092
                  }
18557 bpr 1093
                  tmp_buffer=my_newmem(MAX_BUFFER);
1094
                  check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_external_image(\"%s\",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d);\n",URL,int_data[2],int_data[3],int_data[6],int_data[7],int_data[0],int_data[1],int_data[6],int_data[7],use_offset,int_data[10]));
18552 bpr 1095
                }
1096
                else /* onclick or drag & drop external copy images */
1097
                {
1098
                  js_function[DRAG_EXTERNAL_IMAGE] = 1;
18557 bpr 1099
                  tmp_buffer=my_newmem(MAX_BUFFER);
1100
                  check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "drag_external_image(\"%s\",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d);\n",URL,int_data[2],int_data[3],int_data[6],int_data[7],int_data[0],int_data[1],int_data[6],int_data[7],onclick,object_cnt,use_offset,use_snap,int_data[10]));
18552 bpr 1101
                }
1102
                add_to_buffer(tmp_buffer);
1103
                object_cnt++;
1104
                break;
1105
              default: break;
1106
            }
1107
          }
1108
          reset();
1109
          break;
11806 schaersvoo 1110
/*
1111
HTML5 specs:
1112
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
18552 bpr 1113
img   Specifies the image, canvas, or video element to use
1114
sx   The x coordinate where to start clipping: x1 = int_data[0]
1115
sy   The y coordinate where to start clipping: x2 = int_data[1]
1116
swidth   The width of the clipped image: int_data[2] - int_data[0]
14066 bpr 1117
sheight The height of the clipped image: int_data[3] - int_data[1]
18552 bpr 1118
x   The x coordinate where to place the image on the canvas: dx1 = int_data[4]
1119
y   The y coordinate where to place the image on the canvas: dy1 = int_data[5]
1120
width   The width of the image to use (stretch or reduce the image): dx2 - dx1 = int_data[6]
1121
height   The height of the image to use (stretch or reduce the image): dy2 - dy1 = int_data[7]
11806 schaersvoo 1122
*/
18552 bpr 1123
        case COPYRESIZED:
1124
  /*
1125
  @ copyresized x1,y2,x2,y2,dx1,dy1,dx2,dy2,image_file_url
1126
  @ The image may be any "bitmap" or "SVG"
1127
  @ Insert the region from (x1,y1) to (x2,y2) (in pixels) of [ filename], <br>possibly resized,<br>to the region of (dx1,dy1) to (dx2,dy2) in x/y-range
1128
  @ (dx1:dy1) must be left top corner; (dx2:dy2) must be right bottom corner of inserted image
1129
  @ If x1=y1=x2=y2=-1, the whole [filename / URL ] is copied and resized.
1130
  @ URL is normal URL of network reachable image file location<br>(as seen from public_html-root or network reachable 'http://some_server/my_images/test.gif'<br>(eg no special wims paths are searched !!)
1131
  @ if command <a href="#drag">drag x/y/xy</a> is set before command ''copy``, the images will be draggable<br>javascript function read_canvas(); will return the x/y coordinate data in xrange/yrange of all -including non draggable- images<br>the command drag is only valid for the next image<br>draggable / non-draggable images may be mixed<br>may be used together with preceding keywords ''snaptogrid``,''xsnaptogrid``,''ysnaptogrid`` or <code>snaptopoints x1,y1,x2,y2...</code>
1132
  @ if keyword <a href="#onclick">onclick</a> is set before command ''copy`` the image(s) is clickable (marked with a green rectangle around the image)<br>use ''read_dragdrop`` to get the number of the clicked image(s)<br>use command 'clearbutton some_text' to reset the reply/click array.<br>example: 4 images; student clicked on image 2 and 3: reply = 0,1,1,0<br>after clicking the clear button: reply = 0,0,0,0<br>May be mixed with commands ''drag x|y|xy`` (use javascript read_canvas to get the new coordinates
1133
  @ ''onclick`` for external images may be mixed with canvas generated stuff (like lines,curves etc)
1134
  @ you may draw / userdraw / drag stuff on top of an "imported" image
1135
  @ when set draggable, there will be special function 'read_canvas_images()'<br>now dragging external images may be combined with 'read_canvas()' from <a href='#userdraw'>userdraw</a> or <a href='#multidraw'>multidraw</a><br>set command <a href='#precision'>precision</a> before command ''copy``
1136
  @ use keyword <a href='#centered'>centered</a> before command 'copyresized' to place image center at given coordinates.
1137
  @ <em>TODO:move special image functions to generic 'dragstuff' library</em>
1138
  */
1139
          for(i = 0 ; i<9;i++){
1140
           switch(i){
1141
            case 0: int_data[0] = (int)(get_real(infile,0));break; /* x1 */
1142
            case 1: int_data[1] = (int)(get_real(infile,0));break; /* y1 */
1143
            case 2: int_data[2] = (int)(get_real(infile,0));break;/* x2 */
1144
            case 3: int_data[3] = (int)(get_real(infile,0));break;/* y2 */
1145
            case 4: int_data[4] = x2px(get_real(infile,0));break;/* dx1 */
1146
            case 5: int_data[5] = y2px(get_real(infile,0));break;/* dy1 */
1147
            case 6: int_data[6] = x2px(get_real(infile,0));break;/* dx2 */
1148
            case 7: int_data[7] = y2px(get_real(infile,0));break;/* dy2 */
1149
            case 8: URL = get_string(infile,1);
1150
              if( int_data[1] == -1 ){ int_data[10] = 1; }else{int_data[10] = 0; }/* resized / not resized */
1151
          /* flag error when wrong diagonal:  copyresized -1,-1,-1,-1,0,0,7,7,testfig.gif */
1152
              if( int_data[7] < int_data[5] || int_data[6] < int_data[4]){
1153
                canvas_error("in copyresized,  use:<br>left top corner (dx1:dy1) and right bottom corner (dx2:dy2) ! ");
1154
              }
1155
              int_data[2] = abs(int_data[2] - int_data[0]);/* swidth */
1156
              int_data[3] = abs(int_data[3] - int_data[1]);/* sheight */
1157
              int_data[6] = abs(int_data[6] - int_data[4]);/* width */
1158
              int_data[7] = abs(int_data[7] - int_data[5]);/* height */
1159
              if( onclick == 0 ){ /* no mouse needed static image copy  */
1160
                if(js_function[DRAW_EXTERNAL_IMAGE] == 0){
1161
                  fprintf(js_include_file,"var image_copy_canvas = create_canvas%d(%d,xsize,ysize);",canvas_root_id,STATIC_IMAGE_CANVAS);
1162
                  js_function[DRAW_EXTERNAL_IMAGE] = 1;
1163
                }
18557 bpr 1164
                tmp_buffer=my_newmem(MAX_BUFFER);
1165
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_external_image(\"%s\",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d);\n",URL,int_data[0],int_data[1],int_data[2],int_data[3],int_data[4],int_data[5],int_data[6],int_data[7],use_offset,int_data[10]));
18552 bpr 1166
              }
1167
              else /* onclick or drag & drop external copy images */
1168
              {
1169
                js_function[DRAG_EXTERNAL_IMAGE] = 1;
18557 bpr 1170
                tmp_buffer=my_newmem(MAX_BUFFER);
1171
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "drag_external_image(\"%s\",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d);\n",URL,int_data[0],int_data[1],int_data[2],int_data[3],int_data[4],int_data[5],int_data[6],int_data[7],onclick,object_cnt,use_offset,use_snap,int_data[10]));
18552 bpr 1172
                object_cnt++;
1173
              }
1174
              add_to_buffer(tmp_buffer);
1175
              break;
1176
            default: break;
1177
            }
1178
          }
1179
          reset();
1180
          break;
8386 schaersvoo 1181
 
18552 bpr 1182
        case CROSSHAIR:
1183
  /*
1184
  @ crosshair x,y,color
1185
  @ draw a single crosshair point at (x;y) in color ''color``
1186
  @ use command <code>crosshairsize int</code> and / or <code>linewidth int</code> to adjust
1187
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
1188
  @%crosshair%size 400,400%xrange -10,10%yrange -10,10%opacity 255,255%linewidth 2%onclick%crosshair 0,0,red%linewidth 1%onclick%crosshair 1,1,blue%linewidth 3%onclick%crosshair 3,3,green%linewidth 4%xrosshair 4,4,orange
1189
  */
1190
          for(i=0;i<3;i++){
1191
            switch(i){
1192
              case 0: double_data[0] = get_real(infile,0);break; /* x */
1193
              case 1: double_data[1] = get_real(infile,0);break; /* y */
1194
              case 2: stroke_color = get_color(infile,1);/* name or hex color */
1195
                if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);}
1196
                if(use_affine == TRUE ){ transform(2,2);}
1197
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
1198
                decimals = find_number_of_digits(precision);
18557 bpr 1199
                tmp_buffer=my_newmem(MAX_BUFFER);
1200
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,7,[%.*f],[%.*f],[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[1],crosshair_size,crosshair_size,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,0,0,0,use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 1201
                add_to_buffer(tmp_buffer);
1202
                if(onclick != 0){object_cnt++;}
1203
          /* object_cnt++ */
1204
                reset();
1205
                dragstuff[7] = 1;
1206
                break;
1207
              default:break;
1208
            }
1209
          }
1210
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
1211
          break;
11806 schaersvoo 1212
 
18552 bpr 1213
        case CROSSHAIRS:
1214
  /*
1215
  @ crosshairs color,x1,y1,x2,y2,...,x_n,y_n
1216
  @ draw multiple crosshair points at given coordinates in color ''color``
1217
  @ use command <code>crosshairsize int</code> and / or <code>linewidth int</code> to adjust
1218
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually (!)
1219
  @%crosshairs_1%size 400,400%xrange -10,10%yrange -10,10%opacity 255,255%snaptogrid%linewidth 2%drag xy%crosshairs red,0,0,1,1,2,2,3,3%drag x%crosshairs blue,0,1,1,2,2,3,3,4
1220
  @%crosshairs_2%size 400,400%xrange -10,10%yrange -10,10%opacity 255,255%linewidth 2%onclick%crosshairs red,0,0,1,1,2,2,3,3%onclick%crosshairs blue,0,1,1,2,2,3,3,4
12107 schaersvoo 1221
*/
18552 bpr 1222
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
1223
          fill_color = stroke_color;
1224
          i=0;
1225
          while( ! done ){     /* get next item until EOL*/
1226
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
1227
            if(i%2 == 0 ){
1228
              double_data[i] = get_real(infile,0); /* x */
1229
            }
1230
            else {
1231
              double_data[i] = get_real(infile,1); /* y */
1232
            }
1233
            i++;
1234
          }
1235
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
1236
          if(use_affine == TRUE ){ transform(i-1,2);}
1237
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
1238
          decimals = find_number_of_digits(precision);
1239
          for(c=0 ; c < i-1 ; c = c+2){
18557 bpr 1240
            tmp_buffer=my_newmem(MAX_BUFFER);
1241
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,7,[%.*f],[%.*f],[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+1],crosshair_size,crosshair_size,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,1,0,0,0,use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 1242
            add_to_buffer(tmp_buffer);
1243
            if(onclick != 0){object_cnt++;}/* object_cnt++; */
1244
          }
1245
          dragstuff[7] = 1;
1246
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
1247
          reset();
1248
          break;
1249
        case CROSSHAIRSIZE:
1250
  /*
1251
  @ crosshairsize int
1252
  @ default 8 (px)
1253
  */
1254
          crosshair_size = (int) (get_real(infile,1));
1255
          break;
1256
        case CSS:
1257
  /*
1258
  @ css css_class
1259
  @ may be used before any ''style-able`` html object (like inputfields or buttons) or some html objects that are generated by some canvasdraw commands
1260
  @ in case of <a href="#multidraw">multidraw</a> this command must be a table css class, for example "wimstable"
1261
  @%css%size 400,400%xrange -10,10%yrange -10,10%css wims_button_help%input 0,0,10,1,Hello
1262
  */
1263
          css_class = get_string(infile,1);
1264
          break;
1265
        case CURSOR:
1266
  /*
1267
  @ cursor some CSS cursor_style
1268
  @ alternative: pointer
1269
  @ style can be any valid CSS property value
1270
  @ choose from these types:<br>alias,all-scroll,auto,cell,context-menu,col-resize,copy,crosshair,default,e-resize,<br>ew-resize,grab,grabbing,help,move,n-resize,ne-resize,nesw-resize,ns-resize,nw-resize,<br>nwse-resize,no-drop,none,not-allowed,pointer,progress,row-resize,s-resize,se-resize,<br>sw-resize,text,url(myBall.cur),auto,vertical-text,w-resize,wait,zoom-in,zoom-out,initial
1271
  @ note: wims will not check the validity of your cursor declaration
1272
  @%cursor_css%size 400,400%xrange -10,10%yrange -10,10%cursor move%linewidth 3%drag xy%opacity 200,75%fcircles blue,-5,5,3,-4,-2,6,0,0,5,3,4,2,4,-5,4
1273
  */
1274
          fprintf(js_include_file,"canvas_div%d.style.cursor = \"%s\";",canvas_root_id,get_string(infile,1));
1275
         break;
1276
        case CURVE:
1277
  /*
18556 bpr 1278
  @ curve color,formula(x)
1279
  @ alternative: plot
18572 bpr 1280
  @ use command <a href="#trange">trange</a> in parametric functions before <b>every</b> command curve / plot <code>trange -pi,pi<br>curve color,formula1(t),formula2(t)</code><br>A next parametric curve will only be correctly plot when trange is set again !<br>this is a design flaw and not a feature...
18556 bpr 1281
  @ use command <a href="#precision">precision</a> to increase the number of digits of the plotted points
1282
  @ use command <a href="#plotsteps">plotsteps</a> to increase / decrease the amount of plotted points (default 150)
1283
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
1284
  @ if you need a plot beyond xrange / yrange, use <a href="#jsplot">jsplot</a> (command ''curve`` will only calculate points within the xrange)
18569 bpr 1285
  @%curve%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%xlabel x-axis%ylabel y-axis%precision 1%grid 2,2,grey,2,2,6,grey%precision 1000%curve red,4*sqrt(x)%curve green,2*sqrt(abs(x))%curve blue,3*1/sqrt(x)%curve orange,4*sin(4/x)%dashed%curve red,4*cos(x)
18552 bpr 1286
  */
1287
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
11806 schaersvoo 1288
 
18552 bpr 1289
          if( use_parametric == TRUE ){ /* parametric color,fun1(t),fun2(t)*/
1290
            use_parametric = FALSE;
1291
            stroke_color = get_color(infile,0);
1292
            char *fun1 = get_string_argument(infile,0);
1293
            char *fun2 = get_string_argument(infile,1);
1294
            if( strlen(fun1) == 0 || strlen(fun2) == 0 ){canvas_error("parametric functions are NOT OK !");}
18557 bpr 1295
            tmp_buffer=my_newmem(MAX_BUFFER);
18634 schaersvoo 1296
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,9,%s,[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,eval_parametric(xsize,ysize,fun1,fun2,xmin-10,xmax+10,ymin-10,ymax+10,tmin,tmax,plot_steps,precision,rotationcenter),2*line_width,2*line_width,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 1297
            add_to_buffer(tmp_buffer);
1298
          }
1299
          else{
1300
            stroke_color = get_color(infile,0);
1301
            char *fun1 = get_string_argument(infile,1);
1302
            if( strlen(fun1) == 0 ){canvas_error("function is NOT OK !");}
18557 bpr 1303
            tmp_buffer=my_newmem(MAX_BUFFER);
18634 schaersvoo 1304
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,9,%s,[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,eval(xsize,ysize,fun1,xmin-10,xmax+10,ymin-10,ymax+10,plot_steps,precision,rotationcenter),line_width,line_width,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 1305
            add_to_buffer(tmp_buffer);
1306
          }
1307
          if(onclick != 0){object_cnt++;}/* object_cnt++; */
1308
          dragstuff[9] = 1;
1309
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
1310
          reset();
1311
          break;
1312
        case CURVEDARROW:
14038 schaersvoo 1313
    /*
18556 bpr 1314
  @ curvedarrow x1,y1,xc,yc,x2,y2,color
1315
  @ draw a single headed curved arrow from (x1:y1) in direction of (xc:yc) to point (x2:y2)<br> note: the curve will <b>not go through</b> point (xc:yc)
1316
  @ use command <a href='#arrowhead'>arrowhead</a> to set the size of the arrow head.
1317
  @ use command <code>linewidth int</code> to adjust thickness of the arrow
1318
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
1319
  @%curvedarrow_drag%size 400,400%xrange -10,10%yrange -10,10%cursor move%linewidth 2%drag xy%curvedarrow -5,0,0,10,5,0,blue
1320
  @%curvedarrow_click%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%%onclick%curvedarrow -5,0,0,-10,5,0,blue%onclick%curvedarrow -8,0,0,5,8,3,green
11806 schaersvoo 1321
 
14029 schaersvoo 1322
h[0] = arrowhead
14066 bpr 1323
h[1] = type: 1 = single 2=double arrow
15111 schaersvoo 1324
function Shape(object_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_slider,rotation_center,use_offset)
14038 schaersvoo 1325
    */
18552 bpr 1326
          for(i=0;i<7;i++){
1327
            switch(i){
1328
              case 0: double_data[0] = get_real(infile,0);break; /* x1 */
1329
              case 1: double_data[1] = get_real(infile,0);break; /* y1 */
1330
              case 2: double_data[2] = get_real(infile,0);break; /* xc */
1331
              case 3: double_data[3] = get_real(infile,0);break; /* yc */
1332
              case 4: double_data[4] = get_real(infile,0);break; /* y3 */
1333
              case 5: double_data[5] = get_real(infile,0);break; /* y3 */
1334
              case 6: stroke_color = get_color(infile,1);/* name or hex color */
1335
                if(use_rotate == TRUE ){rotate(6,angle,rotationcenter,2);}
1336
                if(use_affine == TRUE ){ transform(6,2);}
1337
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
1338
                decimals = find_number_of_digits(precision);
18557 bpr 1339
                tmp_buffer=my_newmem(MAX_BUFFER);
1340
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,21,[%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[4],decimals,double_data[1],decimals,double_data[3],decimals,double_data[5],arrow_head,arrow_head,arrow_head,1,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 1341
                add_to_buffer(tmp_buffer);
1342
                if(onclick != 0){object_cnt++;}/* object_cnt++;*/
1343
                reset();
1344
                break;
1345
            }
1346
          }
1347
          dragstuff[21] = 1;
1348
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
1349
          break;
1350
        case CURVEDARROW2:
14038 schaersvoo 1351
    /*
18556 bpr 1352
  @ curvedarrow2 x1,y1,xc,yc,x2,y2,color
1353
  @ draw a double headed curved arrow from (x1:y1) in direction of (xc:yc) to point (x2:y2)<br> note: the curve will <b>not go through</b> point (xc:yc)
1354
  @ use command <a href='#arrowhead'>arrowhead</a> to set the size of the arrow head.
1355
  @ use command <code>linewidth int</code> to adjust thickness of the arrow
1356
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
1357
  @%curvedarrow_drag%size 400,400%xrange -10,10%yrange -10,10%cursor move%linewidth 2%drag xy%curvedarrow2 -5,0,0,10,5,0,blue
18569 bpr 1358
  @%curvedarrow_click%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%%onclick%curvedarrow2 -5,0,0,-10,5,0,blue%onclick%curvedarrow -8,0,0,5,8,3,green
14029 schaersvoo 1359
 
1360
h[0] = arrowhead
14066 bpr 1361
h[1] = type: 1 = single 2=double arrow
15111 schaersvoo 1362
function Shape(object_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_slider,rotation_center,use_offset)
14038 schaersvoo 1363
    */
18552 bpr 1364
          for(i=0;i<7;i++){
1365
            switch(i){
1366
              case 0: double_data[0] = get_real(infile,0);break; /* x1 */
1367
              case 1: double_data[1] = get_real(infile,0);break; /* y1 */
1368
              case 2: double_data[2] = get_real(infile,0);break; /* xc */
1369
              case 3: double_data[3] = get_real(infile,0);break; /* yc */
1370
              case 4: double_data[4] = get_real(infile,0);break; /* y3 */
1371
              case 5: double_data[5] = get_real(infile,0);break; /* y3 */
1372
              case 6: stroke_color = get_color(infile,1);/* name or hex color */
1373
              if(use_rotate == TRUE ){rotate(6,angle,rotationcenter,2);}
1374
              if(use_affine == TRUE ){ transform(6,2);}
1375
              if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
1376
              decimals = find_number_of_digits(precision);
18557 bpr 1377
              tmp_buffer=my_newmem(MAX_BUFFER);
1378
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,21,[%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[4],decimals,double_data[1],decimals,double_data[3],decimals,double_data[5],arrow_head,arrow_head,arrow_head,2,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 1379
              add_to_buffer(tmp_buffer);
1380
              if(onclick != 0){object_cnt++;}/* object_cnt++;*/
1381
              dragstuff[21] = 1;
1382
              if(use_dragstuff == 0 ){ use_dragstuff = 1; }
1383
              reset();
1384
              break;
1385
            }
1386
          }
1387
          break;
1388
        case CURVEDARROWS:
14038 schaersvoo 1389
    /*
18556 bpr 1390
  @ curvedarrows color,x1,y1,xc,yc,x2,y2,...,x_(n-1),y_(n-1),xc,yc,x_n,y_n
1391
  @ draw curved arrows from (x1:y1) in direction of (xc:yc) to point (x2:y2), etc<br> note: the curve will <b>not go through</b> point (xc:yc)
1392
  @ use command <a href='#arrowhead'>arrowhead</a> to set the size of the arrow head.
1393
  @ use command <code>linewidth int</code> to adjust thickness of the arrow
1394
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
1395
  @%curvedarrows_drag%size 400,400%xrange -10,10%yrange -10,10%cursor move%linewidth 2%drag xy%curvedarrows red,-8,0,0,8,8,0,-5,5,0,-10,6,3
1396
  @%curvedarrows_click%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%%onclick%curvedarrows red,-8,0,0,8,8,0,-5,5,0,-10,6,3
14029 schaersvoo 1397
 
14030 schaersvoo 1398
h[0] = arrowhead
14066 bpr 1399
h[1] = type: 1 = single 2=double arrow
15111 schaersvoo 1400
function Shape(object_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_slider,rotation_center,use_offset)
14038 schaersvoo 1401
    */
18552 bpr 1402
          stroke_color = get_color(infile,0);/* name or hex color */
1403
          i = 0;
1404
          decimals = find_number_of_digits(precision);
1405
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
1406
          while( ! done ){
1407
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
1408
            double_data[0] = get_real(infile,0); /* x1 */
1409
            double_data[1] = get_real(infile,0); /* y1 */
1410
            double_data[2] = get_real(infile,0); /* xc */
1411
            double_data[3] = get_real(infile,0); /* yc */
1412
            double_data[4] = get_real(infile,0); /* x3 */
1413
            double_data[5] = get_real(infile,1); /* y3 */
18557 bpr 1414
            tmp_buffer=my_newmem(MAX_BUFFER);
1415
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,21,[%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[4],decimals,double_data[1],decimals,double_data[3],decimals,double_data[5],arrow_head,arrow_head,arrow_head,1,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 1416
            add_to_buffer(tmp_buffer);
1417
            if(onclick != 0){object_cnt++;}
1418
            i = i + 6;
1419
          }
1420
          if(use_rotate == TRUE ){rotate(i-6,angle,rotationcenter,2);}
1421
          if(use_affine == TRUE ){ transform(i-6,2);}
1422
          dragstuff[21] = 1;
1423
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
1424
          reset();
1425
          break;
1426
        case CURVEDARROWS2:
14038 schaersvoo 1427
    /*
18556 bpr 1428
  @ curvedarrows2 color,x1,y1,xc,yc,x2,y2,...x_(n-1),y_(n-1),xc,yc,x_n,y_n
1429
  @ draw double headed curved arrows from (x1:y1) in direction of (xc:yc) to point (x2:y2), etc. <br> note: the curve will <b>not go through</b> point (xc:yc)
1430
  @ use command <a href='#arrowhead'>arrowhead</a> to set the size of the arrow head.
1431
  @ use command <code>linewidth int</code> to adjust thickness of the arrow
1432
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
1433
  @%curvedarrows2_drag%size 400,400%xrange -10,10%yrange -10,10%cursor move%linewidth 2%drag xy%curvedarrows2 red,-8,0,0,8,8,0,-5,5,0,-10,6,3
1434
  @%curvedarrows2_click%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%%onclick%curvedarrow -5,0,0,-10,5,0,blue%onclick%curvedarrows2 red,-8,0,0,8,8,0,-5,5,0,-10,6,3
14030 schaersvoo 1435
 
1436
h[0] = arrowhead
14066 bpr 1437
h[1] = type: 1 = single 2=double arrow
15111 schaersvoo 1438
function Shape(object_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_slider,rotation_center,use_offset)
14038 schaersvoo 1439
    */
18552 bpr 1440
          stroke_color = get_color(infile,0);/* name or hex color */
1441
          i = 0;
1442
          decimals = find_number_of_digits(precision);
1443
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
1444
          while( ! done ){
1445
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
1446
            double_data[0] = get_real(infile,0); /* x1 */
1447
            double_data[1] = get_real(infile,0); /* y1 */
1448
            double_data[2] = get_real(infile,0); /* xc */
1449
            double_data[3] = get_real(infile,0); /* yc */
1450
            double_data[4] = get_real(infile,0); /* x3 */
1451
            double_data[5] = get_real(infile,1); /* y3 */
18557 bpr 1452
            tmp_buffer=my_newmem(MAX_BUFFER);
1453
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,21,[%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[4],decimals,double_data[1],decimals,double_data[3],decimals,double_data[5],arrow_head,arrow_head,arrow_head,2,line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 1454
            add_to_buffer(tmp_buffer);
1455
            if(onclick != 0){object_cnt++;}
1456
            i = i + 6;
1457
          }
1458
          if(use_rotate == TRUE ){rotate(i-6,angle,rotationcenter,2);}
1459
          if(use_affine == TRUE ){ transform(i-6,2);}
1460
          dragstuff[21] = 1;
1461
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
1462
          reset();
1463
          break;
1464
        case DASHED:
1465
  /*
1466
  @ dashed
1467
  @ keyword (no arguments required)
1468
  @ next object will be drawn with a dashed line
1469
  @ change dashing scheme by using command <a href="#dashtype">dashtype</a>
1470
  @%dashed%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%line -5,-5,-5,5,red%dashtype 1,1%dline -4,-5,-4,5,green%dashtype 2,2%dline -3,-5,-3,5,blue%dashtype 3,3%dline 0,-5,0,5,orange%dashtype 4,4%dline 3,-5,3,5,brown
1471
  */
1472
          use_dashed = TRUE;
1473
          break;
1474
        case DASHTYPE:
1475
  /*
1476
  @ dashtype line_width_px,space_width_px
1477
  @ every indiviual object may have its own dashtype, if needed...
1478
  @ When keyword <a href='#dashed'>dashed</a> is set, the objects will be drawn with this dashtype
1479
  @ default value <code>dashtype 2,2</code> e.g. 2px line and 2px space
1480
  @ HTML5 canvas specification supports more arguments (dashing schemes) ... but not all modern browsers are yet capable
1481
  @%dashtype%size 400,400%xrange -10,10%yrange -10,10%dashtype 1,1%dhline 0,9,red%dashtype 2,2%dhline 0,8,red%dashtype 4,4%dhline 0,7,red%dashtype 6,6%dhline 0,6,red%dashtype 8,8%dhline 0,5,red%dashtype 10,10%dhline 0,4,red%dashtype 1,2%dhline 0,3,red%dashtype 2,4%dhline 0,2,red%dashtype 3,6%dhline 0,1,red%dashtype 4,8%dhline 0,0,red%linewidth 2%dashtype 1,1%dhline 0,-9,red%dashtype 2,2%dhline 0,-8,red%dashtype 4,4%dhline 0,-7,red%dashtype 6,6%dhline 0,-6,red%dashtype 8,8%dhline 0,-5,red%dashtype 10,10%dhline 0,-4,red%dashtype 1,2%dhline 0,-3,red%dashtype 2,4%dhline 0,-2,red%dashtype 4,8%dhline 0,-1,red
1482
  */
1483
          for(i=0;i<2;i++){
1484
            switch(i){
1485
              case 0 : dashtype[0] = (int) line_width*( get_real(infile,0)) ; break;
1486
              case 1 : dashtype[1] = (int) line_width*( get_real(infile,1)) ; break;
1487
            }
1488
          }
1489
          break;
1490
        case DIAMONDFILL:
1491
  /*
1492
  @ diamondfill x0,y0,dx,dy,color
1493
  @ x0,y0 in xrange / yrange
1494
  @ distances dx,dy in pixels
1495
  @ there is also a command <a href="#userdraw">userdraw diamondfill,color</a>
1496
  @%diamondfill%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%circles red,-4,0,6,4,0,6%linewidth 1%diamondfill 0,0,5,8,blue%diamondfill 0,7,8,8,lightgreen
1497
  */
1498
          js_function[DRAW_DIAMONDFILL] = 1;
1499
          if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */
1500
            js_function[DRAW_FILLTOBORDER] = 1;
1501
            add_js_filltoborder(canvas_type);
1502
          }
1503
          decimals = find_number_of_digits(precision);
1504
          for(i=0;i<5;i++){
1505
            switch(i){
1506
              case 0: double_data[0] = get_real(infile,0); break; /* x */
1507
              case 1: double_data[1] = get_real(infile,0); break; /* y  */
1508
              case 2: int_data[0] = (int) (get_real(infile,0)); break; /* dx pixel */
1509
              case 3: int_data[1] = (int) (get_real(infile,0)); break; /* dy pixel*/
1510
              case 4: stroke_color = get_color(infile,1);
1511
                if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);}
1512
                if(use_affine == TRUE ){ transform(2,2);}
18573 bpr 1513
              /* draw_diamondfill(ctx,x0,y0,dx,dy,linewidth,color,opacity,xsize,ysize) */
18557 bpr 1514
                tmp_buffer=my_newmem(MAX_BUFFER);
1515
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_diamondfill(%d,%.*f,%.*f,%d,%d,%d,\"%s\",%.2f,%d,%d);\n",STATIC_CANVAS+fill_cnt,decimals,double_data[0],decimals,double_data[1],int_data[0],int_data[1],line_width,stroke_color,stroke_opacity,xsize,ysize));
18552 bpr 1516
                add_to_buffer(tmp_buffer);
1517
                fill_cnt++;
1518
                reset();
1519
                break;
1520
              default:break;
1521
            }
1522
          }
1523
          break;
1524
        case DOTFILL:
1525
  /*
1526
  @ dotfill x0,y0,dx,dy,color
1527
  @ x0,y0 in xrange / yrange
1528
  @ distances dx,dy in pixels
1529
  @ radius of dots is linewidth
1530
  @ there is also a command <a href="#userdraw">userdraw dotfill,color</a>
1531
  @%dotfill%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%circles red,-4,0,6,4,0,6%dotfill 0,0,5,8,blue%dotfill 0,7,8,8,lightgreen
1532
  */
1533
          js_function[DRAW_DOTFILL] = 1;
1534
          if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */
1535
            js_function[DRAW_FILLTOBORDER] = 1;
1536
            add_js_filltoborder(canvas_type);
1537
          }
1538
          decimals = find_number_of_digits(precision);
1539
          for(i=0;i<5;i++){
1540
            switch(i){
1541
              case 0: double_data[0] = get_real(infile,0); break; /* x in px */
1542
              case 1: double_data[1] = get_real(infile,0); break; /* y in py */
1543
              case 2: int_data[0] = (int) (get_real(infile,0)); break; /* dx pixel */
1544
              case 3: int_data[1] = (int) (get_real(infile,0)); break; /* dy pixel*/
1545
              case 4: stroke_color = get_color(infile,1);
1546
                if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);}
1547
                if(use_affine == TRUE ){ transform(2,2);}
1548
        /* draw_dotfill(ctx,x0,y0,dx,dy,radius,color,opacity,xsize,ysize) */
18557 bpr 1549
                tmp_buffer=my_newmem(MAX_BUFFER);
1550
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_dotfill(%d,%.*f,%.*f,%d,%d,%d,\"%s\",%.2f,%d,%d);\n",FILL_CANVAS+fill_cnt,decimals,double_data[0],decimals,double_data[1],int_data[0],int_data[1],line_width,stroke_color,stroke_opacity,xsize,ysize));
18552 bpr 1551
                add_to_buffer(tmp_buffer);
1552
                fill_cnt++;
1553
                reset();
1554
                break;
1555
              default:break;
1556
            }
1557
          }
1558
          break;
1559
        case DRAG:
1560
  /*
18556 bpr 1561
  @ drag [x][y][xy]
1562
  @ the next object will be draggable in x / y / xy direction
1563
  @ the displacement can be read by <code>javascript:read_dragdrop();</code>
1564
  @ the precision (default 2 decimals) in the student reply may be set with command <a href="#precision">precision</a>.<br>Use this 'precision' command before this command 'drag x|y|xy' !
1565
  @ <a href='#onclick'>onclick</a> and ''drag x|y|xy`` may be combined (for different objects: a single object can either be onclick or drag, not both )
1566
  @ ''multi_objects`` will be numbered in the given x/y-sequence (example: points red,0,0,1,1,2,2,3,3: point (0:0) is object_number 1)
1567
  @ <b>attention</b>: static objects and ''onclick/drag`` objects of the same type (like point,circle,etc) with the same coordinates (e.g. objects that overlap) will give problems in the ''recognition algorithm``) in this example<br> <code>linewidth 4<br>point 0,0,red<br>drag xy<br>point 0,0,blue</code><br>the red point will not be recognised as draggable ! in the example<br><code>linewidth 4<br>drag xy<br>point 0,0,red<br>drag xy<br>point 0,0,blue</code><br>both points will be recognised
1568
  @ the answer is: drag_or_onclick_object_number : Xorg : Yorg : Xnew : Ynew<br>wherein object_number is the sequence number of the draggable &amp; onclick objects in your script.<br>Only draggable & onclick objects will have an object_number (e.g things like point,crosshair,line,segment,circle,rect,triangle...etc)
1569
  @ use keyword <a href='#snaptogrid'>snaptogrid</a>, <a href='#xsnaptogrid'>xsnaptogrid</a>, <a href='#ysnaptogrid'>ysnaptogrid</a> or command <a href='#snaptopoints'>snaptopoints x1,y1,x2,y2,...</a> to switch from free to discrete movement
1570
  @ in case of external images (commands copy / copyresized) the external image can be set draggable ; always xy. <br>The function javascript;read_canvas() will return the xy-coordinates of all images.
1571
  @%drag_x%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor lightblue%opacity 200,40%drag x%linewidth 2%circles blue,-5,0,3,0,0,2,5,0,4,0,4,3,0,-3,4
1572
  @%drag_y%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor lightblue%opacity 200,40%drag y%linewidth 2%circles blue,-5,0,3,0,0,2,5,0,4,0,4,3,0,-3,4
1573
  @%drag_xy%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor lightblue%opacity 200,40%drag xy%linewidth 2%circles blue,-5,0,3,0,0,2,5,0,4,0,4,3,0,-3,4
18552 bpr 1574
  */
1575
          temp = get_string(infile,1);
1576
          if(strstr(temp,"xy") != NULL ){
1577
            drag_type = 0;
1578
          } else {
1579
            if(strstr(temp,"x") != NULL ){
1580
              drag_type = 1;
1581
            }
1582
            else { drag_type = 2;}
1583
          }
1584
      /* assuming all drag&drop coordinates the same precision: so set only once */
1585
          if( print_drag_params_only_once == FALSE ){
1586
            fprintf(js_include_file,"dragdrop_precision = %d;use_dragdrop_reply = true;",precision);
1587
            print_drag_params_only_once = TRUE;
1588
          }
1589
          onclick = 2;
1590
      /* if(use_userdraw == TRUE ){canvas_error("\"drag & drop\" may not be combined with \"userdraw\" or \"pan and zoom\" \n");} */
1591
          use_dragstuff = 2;
1592
          js_function[INTERACTIVE] = 1;
1593
          break;
1594
        case ELLIPSE:
1595
  /*
1596
  @ ellipse xc,yc,width_x,height_y,color
1597
  @ ellipses with center xc/yc and width/height in x/y-range etc (this differs from flydraw syntax!)
1598
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
1599
  @ will shrink / expand on zoom out / zoom in
1600
  @%ellipse%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor orange%opacity 200,40%linewidth 3%drag xy%ellipse 0,0,6,4,green%zoom blue
1601
  */
1602
          for(i=0;i<5;i++){
1603
            switch(i){
1604
              case 0:double_data[0] = get_real(infile,0);break; /* x-values */
1605
              case 1:double_data[1] = get_real(infile,0);break; /* y-values */
1606
              case 2:double_data[2] = get_real(infile,0);break; /* rx -> px */
1607
              case 3:double_data[3] = get_real(infile,0);break; /* ry -> px */
1608
              case 4:stroke_color = get_color(infile,1);/* name or hex color */
1609
                if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,4);}
1610
                if(use_affine == TRUE ){ transform(2,4);}
1611
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
1612
                decimals = find_number_of_digits(precision);
18557 bpr 1613
                tmp_buffer=my_newmem(MAX_BUFFER);
1614
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,3,[%.*f],[%.*f],[%.*f],[%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[1],decimals,double_data[2],decimals,double_data[3],line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 1615
                add_to_buffer(tmp_buffer);
1616
                if(onclick != 0){object_cnt++;}/* object_cnt++; */
1617
                dragstuff[3] = 1;
1618
                if(use_dragstuff == 0 ){ use_dragstuff = 1; }
1619
                reset();
1620
              break;
1621
            }
1622
          }
1623
          break;
1624
        case ELLIPSES:
1625
  /*
1626
  @ ellipses color,xc1,yc1,width_x1,height_y1,xc2,yc2,width_x2,height_y2,xc3,yc3,width_x3,height_y3,...
1627
  @ ellipses with center and height in x/y-range etc (this differs from flydraw syntax!)
1628
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
1629
  @ will shrink / expand on zoom out / zoom in
1630
  @%ellipses%size 400,400%xrange -10,10%yrange -10,10%filled%fillcolor orange%opacity 200,40%linewidth 3%onclick%ellipses red,-3,0,2,4,0,0,4,2,3,0,6,2
1631
  */
8224 bpr 1632
 
18552 bpr 1633
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
1634
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
18623 bpr 1635
          if(fillcolor) {fill_color=fillcolor;} else {fill_color=stroke_color;}
18552 bpr 1636
          i=1;
1637
          while( ! done ){     /* get next item until EOL*/
1638
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
1639
            switch (i%4){
1640
              case 1:double_data[i-1] = get_real(infile,0);break; /* x */
1641
              case 2:double_data[i-1] = get_real(infile,0);break; /* y */
1642
              case 3:double_data[i-1] = get_real(infile,0);break; /* rx */
1643
              case 0:double_data[i-1] = get_real(infile,1);break; /* ry */
1644
              default: break;
1645
            }
1646
            i++;
1647
          }
1648
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,4);}
1649
          if(use_affine == TRUE ){ transform(i-1,4);}
1650
          decimals = find_number_of_digits(precision);
1651
          for(c = 0 ; c < i-1 ; c = c+4){
18623 bpr 1652
            check_string_length(string_length);
1653
            tmp_buffer=my_newmem(MAX_BUFFER);
1654
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,3,[%.*f],[%.*f],[%.*f],[%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+1],decimals,double_data[c+2],decimals,double_data[c+3],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 1655
            add_to_buffer(tmp_buffer);
1656
            if(onclick != 0){object_cnt++;} /* object_cnt++; */
1657
          }
1658
          reset();
1659
          dragstuff[3] = 1;
1660
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
1661
          break;
1662
        case FILLALL:
1663
  /*
1664
  @ fillall color,x1,y1,x2,y2...x_n,y_n
18615 bpr 1665
  @ fill all the region containing points (x1:y1),(x2:y2)...(x_n:y_n) with color 'color'
1666
  @ any color (object) in the <a href="#canvastype">canvastype</a> will act as border to the bucket fill
18552 bpr 1667
  @ use this command after all boundary objects are declared.
1668
  @ Use command 'userdraw clickfill,color' for user click driven flood fill.
1669
  @ use command <a href="#canvastype">canvastype </a> to fill another canvas (default should be fine: DRAG_CANVAS = 5)
1670
  @ note: the fill-family of commands are very (client) cpu intensive operations!<br>filling is done pixel by pixel e.g. image size of 400x400 uses 160000 pixels: each pixel contains 4 data (R,G,B,Opacity) = 640000 data.<br>on every data a few operations / comparisons are done...<br>So have pity on your students CPU..
18672 schaersvoo 1671
  @%fillall%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%vlines black,-5,0,-4,0,3,0&hlines black,-5,0,-5,4,-5,-2&%circles green,0,0,2,3,3,5,-5,-5,3%opacity 240,50%fillall blue,1,1,8,8,-8,-8
18552 bpr 1672
  */
1673
          decimals = find_number_of_digits(precision);
1674
          fill_color=get_color(infile,0); /* how nice: now the color comes first...*/
1675
          i=0;
1676
          if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */
1677
            js_function[DRAW_FILLTOBORDER] = 1;
1678
            add_js_filltoborder(canvas_type);
1679
          }
1680
          while( ! done ){     /* get next item until EOL*/
1681
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
1682
            if(i%2 == 0 ){
1683
              double_data[i] = get_real(infile,0); /* x */
1684
            }
1685
            else {
1686
              double_data[i] = get_real(infile,1); /* y */
18557 bpr 1687
              tmp_buffer=my_newmem(MAX_BUFFER);
18609 bpr 1688
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "setTimeout(function(){filltoborder(%.*f,%.*f,false,[%s,%d],%d,false,null);},1000);\n",decimals,double_data[i-1],decimals,double_data[i],fill_color,(int) (fill_opacity/0.0039215),FILL_CANVAS+fill_cnt));
18552 bpr 1689
              add_to_buffer(tmp_buffer);
1690
              fill_cnt++;
1691
            }
1692
            i++;
1693
          }
1694
          break;
1695
        case FILLED:
1696
  /*
1697
  @ filled
1698
  @ keyword (no arguments required)
1699
  @ the next ''fillable`` object (only the next !) will be filled
1700
  @ use command <a href="#fillcolor">fillcolor color</a> to set fillcolor
1701
  @ use <a href="#fillpattern">fillpattern</a> for non-solid color filling.
1702
  @ use command <code>opacity 0-255,0-255</code> to set stroke and fill-opacity
1703
  @ use command <a href='#fill'>fill x,y,color</a> or <a href="#floodfill">floodfill x,y,color</a> to fill the space around (x;y) with color <br>pixel operation implemented in javascript: use with care !
1704
  */
1705
          use_filled = 1;
1706
          break;
1707
        case FILLCOLOR:
1708
  /*
1709
  @ fillcolor colorname or #hex
1710
  @ set the color: mainly used for command 'userdraw obj,stroke_color'
18635 bpr 1711
  @ or in forms as polygon, rects and so on (add filled it the form is not already filled, so if you use rect, need to put filled, if you use frect, no need).
18552 bpr 1712
  @ see <a href="#fillpattern">fillpattern</a> for non-solid color filling.
1713
  */
18623 bpr 1714
          fillcolor = get_color(infile,1);
18635 bpr 1715
          fill_color = fillcolor;
18552 bpr 1716
          break;
1717
        case FILLPATTERN:
1718
  /*
1719
  @ fillpattern grid | hatch | diamond | dot | image_url
1720
  @ alternative: settile image_url
1721
  @ use a pattern as fillstyle
1722
  @ suitable for all fillable object including the <a href="#userdraw">userdraw objects' family</a>
18627 bpr 1723
  @ note: do not use the ''f`` for a fillable object : this is used exclusively for solid color filling.
18569 bpr 1724
  @ the fillcolor is set by the object command, for example:<br><code>size 370,370<br>xrange -5,5<br>yrange -5,5<br>opacity 165,150<br>fillpattern grid<br>circle -6,3,160,blue<br>fillpattern dot<br>circle -3,-3,160,red<br>fillpattern hatch<br>circle 0,3,160,green<br>fillpattern diamond<br>circle 3,-3,160,cyan<br>userdraw dotfill,blue<br>zoom red</code>
18552 bpr 1725
  @ the pattern dimensions are hardcoded (linewidth, radius,dx,dy are fixed)
1726
  @ the pattern color is set by command <a href='#fillcolor'>fillcolor</a> and <a href='#opacity'>opacity</a>
1727
  @ see <a href="#fillcolor">fillcolor</a> for solid color filling.
18569 bpr 1728
  @ when using an image-url, make sure it contains an ''/`` in the filename...''fillpattern &#36;module_dir/gifs/test.jpg`` will fill the next fillable object with this image.|<br>the argument to html5 canvas routine 'createPattern(img,argument)' is set to ''repeat`` e.g. if the image is smaller then the canvas, multiple copies will be used to fill the area ( e.g. ctx.fillStyle() = pattern)<br>for example:<br><code>size 150,150<br>xrange -5,5<br>yrange -5,5<br>drag xy<br>fillpattern gifs/en.gif<br>circle 0,0,100,red<br>fillpattern gifs/nl.gif<br>drag xy<br>circle -3,2,100,green<br>fillpattern gifs/cn.gif<br>drag xy<br>circle 3,2,100,green</code>
18552 bpr 1729
  @ fillpattern is also active for <a href="#userdraw">userdraw object,color</a>...<br>the userdraw family a has also ''clickfill type`` (e.g. an object gets filled between boundaries, when clicked) commands like:<br>'userdraw dotfill,color'<br>'userdraw hatchfill,color' etc
18569 bpr 1730
  @%fillpattern_1%size 400,400%xrange -5,5%yrange -5,5%opacity 165,150%fillpattern grid%circle -6,3,160,blue%fillpattern dot%circle -3,-3,160,red%fillpattern hatch%circle 0,3,160,green%fillpattern diamond%circle 3,-3,160,cyan%zoom red
18552 bpr 1731
  @%fillpattern_2%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%fillcolor green%fillpattern hatch%#fillpattern dot,diamond,grid,imageurl%userdraw circle,red
1732
  */
1733
          temp = get_string(infile,1);
1734
          use_filled = 0;
1735
          js_function[DRAW_FILL_PATTERN] = 1;
1736
          if( strstr(temp,"grid") != 0 ){ use_filled = 2;}
1737
          else{
1738
            if( strstr(temp,"hatch") != 0 ){ use_filled = 3;}
1739
            else{
1740
              if( strstr(temp,"diamond") != 0 ){ use_filled = 4;}
1741
              else{
1742
                if( strstr(temp,"dot") != 0 ){ use_filled = 5;}
1743
                else{
1744
                  if( strstr(temp,"/") != 0 ){ /* get_image_from_url() needs to be called after function definition...*/
1745
                    use_filled = 6;js_function[JS_LOAD_IMAGE] = 1;
18557 bpr 1746
                    tmp_buffer=my_newmem(MAX_BUFFER);
1747
                    check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "get_image_from_url(\"%s\");",temp));
18552 bpr 1748
                    add_to_buffer(tmp_buffer);
1749
                  }
1750
                }
1751
              }
1752
            }
1753
          }
1754
          if( use_filled == 0 ){canvas_error("fillpattern unknown or typo...choose grid,hatch,diamond of dot...");}
1755
          break;
1756
        case FILLTOBORDER:
1757
  /*
1758
  @ filltoborder x,y,bordercolor,color
1759
  @ fill the region of point (x:y) with color 'color'
18615 bpr 1760
  @ any other color than bordercolor will not act as border to the bucket fill
1761
  @ the filling is done in the connex component whih contains (x,y) of the set of points which are in a color different of bordercolor
18552 bpr 1762
  @ use this command after all boundary objects are declared.
18615 bpr 1763
  @ it can be useful to increase strokeopacity or linewidth
18552 bpr 1764
  @ use command <a href="#canvastype">canvastype </a> to fill another canvas (default should be fine: DRAG_CANVAS = 5)
1765
  @ note: filltoborder is a very (client) cpu intensive operation!<br>filling is done pixel by pixel e.g. image size of 400x400 uses 160000 pixels: each pixel contains 4 data (R,G,B,Opacity) = 640000 data.<br>on every data a few operations / comparisons are done...<br>So have pity on your students CPU..
1766
  @ maybe used together with command <a href="#userdraw">userdraw clickfill,color</a>
18615 bpr 1767
  @%filltoborder%size 400,400%xrange -10,10%yrange -10,10%canvastype 100%linewidth 2%precision 1000%jsplot blue,5*sin(x)%opacity 200,50%filltoborder 6,6,blue,green%filltoborder 6,-6,blue,red
18552 bpr 1768
  */
1769
          for(i=0 ;i < 4 ; i++){
1770
            switch(i){
1771
              case 0:double_data[0] = get_real(infile,0);break;
1772
              case 1:double_data[1] = get_real(infile,0);break;
1773
              case 2:bgcolor = get_color(infile,0);break;
1774
              case 3:fill_color = get_color(infile,1);
18569 bpr 1775
          if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */
1776
            js_function[DRAW_FILLTOBORDER] = 1;
1777
            add_js_filltoborder(canvas_type);
1778
          }
1779
          decimals = find_number_of_digits(precision);
18552 bpr 1780
         /* we need to set a timeout: the canvas is not yet draw in memory? when floodfill is called directly... */
18569 bpr 1781
          tmp_buffer=my_newmem(MAX_BUFFER);
18629 bpr 1782
          check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "setTimeout(function(){filltoborder(%.*f,%.*f,[%s,%d],[%s,%d],%d,false,null)},1000);\n",decimals,double_data[0],decimals,double_data[1],bgcolor,(int) (fill_opacity/0.0039215),fill_color,(int) (fill_opacity/0.0039215),FILL_CANVAS+fill_cnt));
18569 bpr 1783
          add_to_buffer(tmp_buffer);
1784
          fill_cnt++;
1785
          reset();
1786
          break;
18552 bpr 1787
              default:break;
1788
            }
1789
          }
1790
          break;
1791
        case FLOODFILL:
1792
  /*
1793
  @ floodfill x,y,color
1794
  @ alternative: fill
1795
  @ fill the region of point (x:y) with color 'color'
1796
  @ any other color or size of picture (borders of picture) will act as border to the bucket fill
1797
  @ use this command after all boundary objects are declared.
1798
  @ Use command <code>userdraw clickfill,color</code> for user click driven flood fill.
1799
  @ use command <a href="#canvastype">canvastype </a> to fill another canvas (default should be fine: DRAG_CANVAS = 5)
1800
  @ note: floodfill is a very (client) cpu intensive operation!<br>filling is done pixel by pixel e.g. image size of 400x400 uses 160000 pixels: each pixel contains 4 data (R,G,B,Opacity) = 640000 data.<br>on every data a few operations / comparisons are done...<br>So have pity on your students CPU..
1801
  @%floodfill%size 400,400%xrange -10,10%yrange -10,10%canvastype 100%linewidth 2%precision 1000%jsplot blue,5*sin(x)%opacity 200,50%floodfill 6,6,blue%floodfill 6,-6,red
1802
  */
1803
          for(i=0 ;i < 4 ; i++){
1804
            switch(i){
1805
              case 0:double_data[0] = get_real(infile,0);break;
1806
              case 1:double_data[1] = get_real(infile,0);break;
1807
              case 2:fill_color = get_color(infile,1);
1808
                if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */
1809
                  js_function[DRAW_FILLTOBORDER] = 1;
1810
                  add_js_filltoborder(canvas_type);
1811
                }
1812
                decimals = find_number_of_digits(precision);
1813
         /* we need to set a timeout: the canvas is not yet draw in memory? when floodfill is called directly... */
18557 bpr 1814
                tmp_buffer=my_newmem(MAX_BUFFER);
18609 bpr 1815
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "setTimeout(function(){filltoborder(%.*f,%.*f,false,[%s,%d],%d,false,null);},1000);\n",decimals,double_data[0],decimals,double_data[1],fill_color,(int) (fill_opacity/0.0039215),FILL_CANVAS+fill_cnt));
18552 bpr 1816
                add_to_buffer(tmp_buffer);
1817
                fill_cnt++;
1818
                break;
1819
            default:break;
1820
            }
1821
          }
1822
          reset();
1823
          break;
1824
        case FONTCOLOR:
1825
  /*
18556 bpr 1826
  @ fontcolor color
1827
  @ color: hexcolor or colorname
1828
  @ default: black
1829
  @ use command <a href="#fontfamily">fontfamily</a> to deviate from default font type
1830
  @%fontcolor%size 400,400%xrange -10,10%yrange -10,10%fontcolor red%#note: use command fontfamily to change size and shape%axis%axisnumbering%grid 2,2,grey,2,2,4,grey
18552 bpr 1831
  */
1832
          font_color = get_color(infile,1);
1833
          break;
1834
        case FONTFAMILY:
1835
  /*
18556 bpr 1836
  @ fontfamily font_description
1837
  @ set the font family; for browsers that support it
1838
  @ font_description: Arial, Courier, Helvetica etc
1839
  @ in case commands <code>string color,x,y,the string</code>, <code>stringup color,x,y,rotation,the string</code>, ''fontfamily`` can be something like:<code>fontfamily italic 34pt Arial</code>. Use correct syntax: ''font style``, ''font size pt``, ''fontfamily``
1840
  @%fontfamily%size 400,400%xrange -10,10%yrange -10,10  %fontfamily Bold 10pt Arial%string blue,-9,9,10 pt Arial%fontfamily Italic 20pt Arial%string blue,0,9,20 pt Arial%fontfamily Bold 10pt Helvetica%string blue,-9,5,10 pt Helvetica%fontfamily Italic 20pt Helvetica%string blue,0,5,20 pt Helvetica %fontfamily Bold 10pt Courier%string blue,-9,0,10 pt Courier%fontfamily Italic 20pt Courier%string blue,0,0,20 pt Courier%fontfamily Bold 10pt Fixed%string blue,-9,-5,10 pt Fixed%fontfamily Italic 20pt Fixed%string blue,0,-5,20 pt Fixed %fontfamily Bold 10pt Times%string blue,-9,-9,10 pt Times%fontfamily Italic 20pt Times%string blue,0,-9,20 pt Times
12110 schaersvoo 1841
 
18552 bpr 1842
  */
1843
          font_family = get_string(infile,1);
1844
          break;
1845
        case FONTSIZE:
1846
  /*
18556 bpr 1847
  @ fontsize font_size
1848
  @ default value 12
1849
  @ note: for some macros (like ''grid | legend | xaxistext | xlabel`` etc) sometimes command <a href="#fontfamily">fontfamily</a> can be used for some specific font-setting<br>this is however not always very straight forward... so just try and see what happens
18552 bpr 1850
  */
1851
          font_size = (int) (get_real(infile,1));
1852
          break;
1853
        case FUNCTION_LABEL:
1854
  /*
18556 bpr 1855
  @ functionlabel label_1:label_2:label_3...
1856
  @ alternative: functionlabels
1857
  @ default value ''f(x)=:g(x)=:h(x)=:i(x)=:j(x)=:k(x)=:m(x)=:n(x)=``
1858
  @ no mathml allowed (just ascii string)
1859
  @ use command <a href='#fontsize'>fontsize int</a> to adjust the size
1860
  @ use command <a href='#strokecolor'>strokecolor colorname</a> to adjust the labels (individually, if needed)
1861
  @ if needed, use before every command <a href='#userinput'>userinput function | inputfield | textarea</a>
1862
  @ no limit in amount of inputfields for userbased function plotting
1863
  @%function_label%size 400,400%xrange -5,5%yrange -5,5%precision 0%axis%axisnumbering%opacity 100,190%grid 1,1,grey,2,2,5,black%linewidth 3%linewidth 1%precision 1000%functionlabels F(x)=:H(x)=:Yield(x)=%strokecolor green%userinput function%strokecolor red%userinput function%strokecolor blue%userinput function
18552 bpr 1864
  */
1865
          temp = get_string_argument(infile,1);
1866
          function_label = list2js_array(temp,":");
1867
          break;
1868
        case GRID:/* xmajor,ymajor,gridcolor [,xminor,yminor,tick length (px), axis/tickscolor]*/
1869
  /*
18556 bpr 1870
  @ grid step_x,step_y,gridcolor
1871
  @ if keywords <a href="#axis">axis</a> or <a href="#axisnumbering">axisnumbering</a> are set, use: <code>grid step_x,step_y,major_color,minor_x,minor_y,tics height in px,axis_color</code> minor x step = step_x / minor_x
1872
  @ in that case, use command <a href="#fontcolor">fontcolor</a>, <a href="#fontsize">fontsize</a> and / or <a href="#fontfamily">fontfamily</a> to adjust font; defaults: black,12,Arial
1873
  @ if xmin > 0 and/or ymin > 0 and zooming / panning is not active: be aware that the x/y-axis numbering and x/y major/minor tic marks will not be visual as they are placed under the x-axis and left to the y-axis (in Quadrant II and IV)
1874
  @ can <b>not</b> be set <a href="#onclick">onclick</a> or <a href="#drag">drag xy</a>
1875
  @ use commands <a href="#xlabel">xlabel some_string</a> and/or <a href="#ylabel">ylabel some_string</a> to label axis; use command ''fontsize`` to adjust size: the font family is non-configurable 'italic your_fontsize px Arial' !
1876
  @ see commands <a href="#xaxis">xaxis or xaxistext</a>, <a href="#yaxis">yaxis or yaxistext</a> to set tailormade values on axis (the used font is set by command <a href="#fontfamily">fontfamily</a>; default '12px Arial')
1877
  @ see command <a href="#legend">legend</a> to set a legend for the graph; use command <a href="#fontsize">fontsize</a> to adjust size (the font family is non-configurable 'bold your_fontsize px Arial')
1878
  @%grid%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%zoom red
1879
  @%grid_axis%size 400,400%xrange -10,10%yrange -10,10%axis%grid 1,1,grey,2,2,6,black%zoom red
1880
  @%grid_axis_axisnumbering%size 400,400%xrange -10,10%yrange -10,10%fontfamily Italic 14px Courier%axis%axisnumbering%precision 0%grid 1,1,grey,2,2,6,black%zoom red
18552 bpr 1881
  */
1882
          if( js_function[DRAW_YLOGSCALE] == 1 ){canvas_error("only one grid type is allowed...");}
1883
          js_function[DRAW_GRID] = 1;
1884
          for(i=0;i<4;i++){
1885
            switch(i){
1886
              case 0:double_data[0] = get_real(infile,0);break;/* xmajor */
1887
              case 1:double_data[1] = get_real(infile,0);break;/* ymajor */
1888
              case 2:
1889
              if( use_axis == TRUE ){
1890
                stroke_color = get_color(infile,0);
1891
                done = FALSE;
1892
                int_data[0] = (int) (get_real(infile,0));/* xminor */
1893
                int_data[1] = (int) (get_real(infile,0));/* yminor */
1894
                int_data[2] = (int) (get_real(infile,0));/* tic_length */
1895
                fill_color = get_color(infile,1); /* used as axis_color*/
1896
              }
1897
              else {
1898
              int_data[0] = 1;
1899
              int_data[1] = 1;
1900
              stroke_color = get_color(infile,1);
1901
              fill_color = stroke_color;
1902
              }
1903
              if( double_data[0] <= 0 ||  double_data[1] <= 0 ||  int_data[0] <= 0 ||  int_data[1] <= 0 ){canvas_error("major or minor ticks must be positive !");}
1904
              /* set snap_x snap_y values in pixels */
1905
              fprintf(js_include_file,"snap_x = %f;snap_y = %f;",double_data[0] / int_data[0],double_data[1] / int_data[1]);
1906
              fprintf(js_include_file,"\n/* add grid */function redraw_grid(){draw_grid%d(%d,%d,%.2f,%.*f,%.*f,%d,%d,%d,%d,\"%s\",\"%s\",%d,\"%s\",%d,%d,%d,%d,%d,\"%s\",%.2f);return;};",canvas_root_id,GRID_CANVAS,precision,stroke_opacity,decimals,double_data[0],decimals,double_data[1],int_data[0],int_data[1],int_data[2],line_width,stroke_color,fill_color,font_size,font_family,use_axis,use_axis_numbering,use_dashed,dashtype[0],dashtype[1],font_color,fill_opacity);
18557 bpr 1907
              tmp_buffer=my_newmem(MAX_BUFFER);
1908
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "redraw_grid();\n"));
18552 bpr 1909
              add_to_buffer(tmp_buffer);
1910
              break;
1911
            }
1912
          }
1913
          reset();
1914
          break;
1915
        case GRIDFILL:
1916
  /*
1917
  @ gridfill x0,y0,dx,dy,color
1918
  @ x0,y0 in xrange / yrange
1919
  @ distances dx,dy in pixels
1920
  @ there is also a command <a href="#userdraw">userdraw gridfill,color</a>
1921
  @%gridfill%size 400,400%xrange -10,10%yrange -10,10%canvastype 100%linewidth 2%precision 1000%jsplot blue,5*sin(x)%opacity 200,50%gridfill 6,6,10,10,blue%gridfill 6,-6,6,6,red
11806 schaersvoo 1922
 
18552 bpr 1923
  */
1924
          js_function[DRAW_GRIDFILL] = 1;
1925
          decimals = find_number_of_digits(precision);
1926
          if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */
1927
            js_function[DRAW_FILLTOBORDER] = 1;
1928
            add_js_filltoborder(canvas_type);
1929
          }
1930
          for(i=0;i<5;i++){
1931
            switch(i){
1932
              case 0: double_data[0] = get_real(infile,0); break; /* x  */
1933
              case 1: double_data[1] = get_real(infile,0); break; /* y  */
1934
              case 2: int_data[0] = (int) (get_real(infile,0)); break; /* dx pixel */
1935
              case 3: int_data[1] = (int) (get_real(infile,0)); break; /* dy pixel*/
1936
              case 4: stroke_color = get_color(infile,1);
18557 bpr 1937
 
1938
              tmp_buffer=my_newmem(MAX_BUFFER);
1939
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_gridfill(%d,%.*f,%.*f,%d,%d,%d,\"%s\",%.2f,%d,%d);\n",STATIC_CANVAS+fill_cnt,decimals,double_data[0],decimals,double_data[1],int_data[0],int_data[1],line_width,stroke_color,stroke_opacity,xsize,ysize));
18552 bpr 1940
              add_to_buffer(tmp_buffer);
1941
              fill_cnt++;
1942
              reset();
1943
              break;
1944
              default:break;
1945
            }
1946
          }
1947
          break;
1948
        case GROUP:
1949
  /*
18556 bpr 1950
  @ group
1951
  @ keyword
1952
  @ work in 'progress'
1953
  @ all objects(*) after the command and until <a href="#kill">kill group</a> or <a href="#killslider">killslider</a> may be moved together with mouse moverments<br> (*) for now all real canvas objects and latex / xml ; but no images (work in progress)
1954
  @ may be combined with slider driven movements or drag & drop
1955
  @%group%%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 100%linewidth 4%rotationcenter 0,0%slider -2*pi,2*pi,300,40,angle active,rotate%snaptogrid%ftriangle 0,-4,-2,-2,4,--5,blue%fillcolor red%fcircle -4.4,4.4,40,blue%kill slider%slider -20,20,300,40,x active,x-slide%ftriangle -2,0,0,4,2,0,green%fcircle 4.4,4.5,40,red%kill slider%slider -20,20,300,40,y active,y-slide%fcircle 4,-4,40,green%linewidth 4%fcircle -4,-4,40,orange%kill slider%group%fcircle -4.4,4.5,10,blue%fcircle -5.4,4.5,10,blue%fcircle -6.4,4.5,10,blue%fcircle -4.4,8,16,green%fcircle -5.4,8,16,green%fcircle -6.4,8,16,green%mouse red,22%zoom red
18552 bpr 1956
  */
1957
          use_slider++;
1958
          add_slider(2);
1959
          no_reset = TRUE;
1960
          int c = 0;
1961
          for(i=last_slider;i<=use_slider;i++){ int_data[c] = i; c++; }
1962
          my_sliders = data2js_array(int_data,use_slider - last_slider+1);
1963
          if( precision == 0 ){precision = 100;}
1964
          onclick = 5;
1965
          use_dragstuff = 2;
1966
          drag_type = 0;
1967
          js_function[INTERACTIVE] = 1;
1968
          fprintf(js_include_file,"var slider%d;dragdrop_precision = %d;use_dragdrop_reply = true;",use_slider,precision);
18557 bpr 1969
          tmp_buffer=my_newmem(MAX_BUFFER);
1970
          check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "slider%d = new move_group(%d);\n",use_slider,use_slider));
18552 bpr 1971
          add_to_buffer(tmp_buffer);
1972
          break;
1973
        case HALFLINE:
1974
  /*
1975
  @ demiline x1,y1,x2,y2,color
1976
  @ alternative: halfline
1977
  @ draws a halfline starting in (x1:y1) and through (x2:y2) in color 'color' (colorname or hex)
1978
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
1979
  @%halfline%size 400,400%xrange -10,10%yrange -10,10%halfline -5,5,0,0,red%halfline -5,-5,0,0,blue
1980
  */
1981
          for(i=0; i<13;i++){double_data[i]=0;}
1982
          for(i=0;i<5;i++){
1983
            switch(i){
1984
              case 0: double_data[0]= get_real(infile,0);break; /* x-values */
1985
              case 1: double_data[1]= get_real(infile,0);break; /* y-values */
1986
              case 2: double_data[10]= get_real(infile,0);break; /* x-values */
1987
              case 3: double_data[11]= get_real(infile,0);break; /* y-values */
1988
              case 4: stroke_color=get_color(infile,1);/* name or hex color */
1989
                if(double_data[0] == double_data[10]){ /* vertical halfline */
1990
                  if(double_data[1] < double_data[11]){
1991
                    double_data[3] = ymax + 1000;
1992
                  }
1993
                  else {
1994
                    double_data[3] = ymin - 1000;
1995
                  }
1996
                  double_data[2] = double_data[0];
1997
                } else { /* horizontal halfline*/
1998
                  if( double_data[1] == double_data[11] ){
1999
                    if( double_data[0] < double_data[10] ){
2000
                      double_data[2] = xmax + 1000; /* halfline to the right */
2001
                    }
2002
                    else {
2003
                      double_data[2] = xmin - 1000; /* halfline to the left */
2004
                    }
2005
                    double_data[3] = double_data[1];
2006
                  }
2007
                else {
2008
          /* any other halfline */
2009
          /* slope */
2010
                  double_data[12] = (double_data[11] - double_data[1])/(double_data[10] - double_data[0]);
2011
                /* const */
2012
                  double_data[13] = double_data[1] - double_data[12]*double_data[0];
2013
                  if( double_data[0] < double_data[10] ){
2014
                    double_data[2] = double_data[2] + 1000;
2015
                  }
2016
                  else {
2017
                    double_data[2] = double_data[2] - 1000;
2018
                  }
2019
                  double_data[3] = double_data[12]*double_data[2] + double_data[13];
2020
                }
2021
              }
2022
              if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
2023
              if(use_rotate == TRUE ){rotate(4,angle,rotationcenter,2);}
2024
              if(use_affine == TRUE ){ transform(4,2);}
18557 bpr 2025
              tmp_buffer=my_newmem(MAX_BUFFER);
2026
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,18,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[1],decimals,double_data[3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 2027
              add_to_buffer(tmp_buffer);
2028
              if(onclick != 0){object_cnt++;}
2029
        /* object_cnt++; */
2030
              reset();
2031
              break;
2032
            }
2033
          }
2034
          dragstuff[18] = 1;
2035
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
2036
          break;
2037
        case HALFLINES:
2038
  /*
2039
  @ demilines color,x1,y1,x2,y2,....
2040
  @ alternative: halflines
2041
  @ draws halflines starting in (x1:y1) and through (x2:y2) in color 'color' (colorname or hex) etc
2042
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> indiviually
2043
  @%halflines%size 400,400%xrange -10,10%yrange -10,10%halflines red,-5,5,0,0,-5,-5,0,0
2044
  */
2045
          stroke_color=get_color(infile,0);
2046
          fill_color = stroke_color;
2047
          i=0;
2048
          while( ! done ){     /* get next item until EOL*/
2049
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
2050
            if(i%2 == 0 ){
2051
              double_data[i] = get_real(infile,0); /* x */
2052
            } else {
2053
              double_data[i] = get_real(infile,1); /* y */
2054
            }
2055
            i++;
2056
          }
2057
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
2058
          decimals = find_number_of_digits(precision);
2059
          for(c = 0 ; c < i-1 ; c = c+4){
2060
            if( double_data[c] == double_data[c+2] ){ /* vertical line*/
2061
              if(double_data[c+1] < double_data[c+3]){ /* upright halfline */
2062
                double_data[c+3] = ymax + 1000;
2063
              }
2064
              else {
2065
                double_data[c+3] = ymin - 1000;/* descending halfline */
2066
              }
2067
            }
2068
            else {
2069
              if( double_data[c+1] == double_data[c+3] ){ /* horizontal line */
2070
                if(double_data[c] < double_data[c+2] ){ /* halfline to the right */
2071
                  double_data[c+2] = xmax+100;
2072
                }
2073
                else {
2074
                  double_data[c+2] = xmin-1000; /* halfline to the right */
2075
                }
2076
              }
2077
              else {
2078
      /* m */
2079
                double m = (double_data[c+3] - double_data[c+1]) /(double_data[c+2] - double_data[c]);
2080
      /* q */
2081
                double q = double_data[c+1] - ((double_data[c+3] - double_data[c+1]) /(double_data[c+2] - double_data[c]))*double_data[c];
2082
                if(double_data[c] < double_data[c+2]){ /* to the right */
2083
                  double_data[c+2] = xmax+1000; /* 1000 is needed for dragging...otherwise it is just segment */
2084
                  double_data[c+3] = (m)*(double_data[c+2])+(q);
2085
                  }
2086
                  else { /* to the left */
2087
                    double_data[c+2] = xmin - 1000;
2088
                    double_data[c+3] = (m)*(double_data[c+2])+(q);
2089
                  }
2090
                }
2091
              }
2092
              if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
2093
              if(use_affine == TRUE ){ transform(i-1,2);}
18557 bpr 2094
              tmp_buffer=my_newmem(MAX_BUFFER);
2095
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,18,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 2096
              add_to_buffer(tmp_buffer);
2097
              if(onclick != 0){object_cnt++;}/* object_cnt++; */
2098
            }
2099
          reset();
2100
          dragstuff[18] = 1;
2101
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
2102
          break;
2103
        case HATCHFILL:
2104
  /*
2105
  @ hatchfill x0,y0,dx,dy,color
2106
  @ x0,y0 in xrange / yrange
2107
  @ distances dx,dy in pixels
2108
  @ there is also a command <a href="#userdraw">userdraw hatchfill,color</a>
2109
  @%hatchfill%size 400,400%xrange -10,10%yrange -10,10%canvastype 100%linewidth 2%precision 1000%jsplot blue,5*sin(x)%opacity 200,50%hatchfill 6,6,10,10,blue%hatchfill 6,-6,6,6,red
2110
  */
2111
          js_function[DRAW_HATCHFILL] = 1;
2112
          if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */
2113
            js_function[DRAW_FILLTOBORDER] = 1;
2114
            add_js_filltoborder(canvas_type);
2115
          }
2116
          decimals = find_number_of_digits(precision);
2117
          for(i=0;i<5;i++){
2118
            switch(i){
2119
              case 0: double_data[0] = get_real(infile,0); break; /* x */
2120
              case 1: double_data[1] = get_real(infile,0); break; /* y  */
2121
              case 2: int_data[0] = (int) (get_real(infile,0)); break; /* dx pixel */
2122
              case 3: int_data[1] = (int) (get_real(infile,0)); break; /* dy pixel*/
2123
              case 4: stroke_color = get_color(infile,1);
2124
                if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);}
2125
                if(use_affine == TRUE ){ transform(2,2);}
2126
                /* draw_hatchfill(ctx,x0,y0,dx,dy,linewidth,color,opacity,xsize,ysize) */
18557 bpr 2127
                tmp_buffer=my_newmem(MAX_BUFFER);
2128
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_hatchfill(%d,%.*f,%.*f,%d,%d,%d,\"%s\",%.2f,%d,%d);\n",STATIC_CANVAS+fill_cnt,decimals,double_data[0],decimals,double_data[1],int_data[0],int_data[1],line_width,stroke_color,stroke_opacity,xsize,ysize));
18552 bpr 2129
                add_to_buffer(tmp_buffer);
2130
                fill_cnt++;
2131
                reset();
2132
                break;
2133
              default:break;
2134
            }
2135
          }
2136
          break;
2137
        case HLINE:
2138
  /*
2139
  @ hline x,y,color
2140
  @ alternative: horizontalline
2141
  @ draw a horizontal line through point (x:y) in color 'color'
2142
  @ or use command <a href='#curve'>curve color,formula</a> to draw the line (uses more points to draw the line; is however better draggable)
2143
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
2144
  @%hline%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%hline 0,0,red%dhline 0,5,blue
2145
  */
2146
          for(i=0;i<3;i++) {
2147
            switch(i){
2148
              case 0: double_data[0] = get_real(infile,0);break; /* x-values */
2149
              case 1: double_data[1] = get_real(infile,0);break; /* y-values */
2150
              case 2: stroke_color = get_color(infile,1);/* name or hex color */
2151
                double_data[3] = double_data[1];
2152
                if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);}
2153
                if(use_affine == TRUE ){ transform(2,2);}
2154
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
2155
                decimals = find_number_of_digits(precision);
18557 bpr 2156
                tmp_buffer=my_newmem(MAX_BUFFER);
2157
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,100*xmin,decimals,100*xmax,decimals,double_data[1],decimals,double_data[3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 2158
                add_to_buffer(tmp_buffer);
2159
                if(onclick != 0){object_cnt++;}/* object_cnt++; */
2160
                dragstuff[4] = 1;
2161
                if(use_dragstuff == 0 ){ use_dragstuff = 1; }
2162
                reset();
2163
                break;
2164
            }
2165
          }
2166
          break;
2167
        case HLINES:
2168
  /*
2169
  @ hlines color,x1,y1,x2,y2,...
2170
  @ alternative: horizontallines
2171
  @ draw horizontal lines through points (x1:y1)...(xn:yn) in color 'color'
2172
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually
2173
  @%hlines%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%hlines red,0,0,0,5,0,-5
2174
  */
2175
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
2176
          fill_color = stroke_color;
2177
          i=0;
2178
          while( ! done ){     /* get next item until EOL*/
2179
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
2180
            if(i%2 == 0 ){
2181
                double_data[i] = get_real(infile,0); /* x */
2182
            }
2183
            else {
2184
              double_data[i] = get_real(infile,1); /* y */
2185
            }
2186
            i++;
2187
          }
2188
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
2189
          if(use_affine == TRUE ){ transform(i-1,2);}
2190
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
11806 schaersvoo 2191
 
18552 bpr 2192
          decimals = find_number_of_digits(precision);
2193
          for(c = 0 ; c < i-1 ; c = c+2){
18557 bpr 2194
            tmp_buffer=my_newmem(MAX_BUFFER);
18607 bpr 2195
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,100*xmin,decimals,100*xmax,decimals,double_data[c+1],decimals,double_data[c+1],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 2196
            add_to_buffer(tmp_buffer);
2197
            if(onclick != 0){object_cnt++;}/* object_cnt++; */
2198
          }
2199
          reset();
2200
          dragstuff[4] = 1;
2201
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
2202
          break;
2203
        case HTTP:
2204
  /*
18556 bpr 2205
  @ http x1,y1,x2,y2,http://some_adress.com
2206
  @ an active html-page will be displayed in an "iframe" rectangle left top (x1:y1), right bottom (x2:y2)
2207
  @ do not use interactivity (or mouse) if the mouse needs to be active in the iframe
2208
  @ can <b>not</b> be ''set onclick`` or ''drag xy``
2209
  @%http%size 400,400%xrange -10,10%yrange -10,10%http 0,10,10,0,http://wims.unice.fr%opacity 200,50%drag xy%fcircle 0,0,100,green
18552 bpr 2210
  */
2211
          js_function[DRAW_HTTP] = 1;
2212
          for(i=0;i<5;i++){
2213
            switch(i){
2214
              case 0: int_data[0]=x2px(get_real(infile,0));break; /* x in x/y-range coord system -> pixel width */
2215
              case 1: int_data[1]=y2px(get_real(infile,0));break; /* y in x/y-range coord system  -> pixel height */
2216
              case 2: int_data[2]=x2px(get_real(infile,0)) - int_data[0];break; /* width in x/y-range coord system -> pixel width */
2217
              case 3: int_data[3]=y2px(get_real(infile,0)) - int_data[1];break; /* height in x/y-range coord system  -> pixel height */
2218
              case 4: decimals = find_number_of_digits(precision);
2219
                temp = get_string(infile,1);
2220
                if(strstr(temp,"\"") != 0 ){ temp = str_replace(temp,"\"","'");}
18557 bpr 2221
                tmp_buffer = my_newmem(string_length+2);
2222
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_http(%d,%d,%d,%d,%d,\"%s\");\n",canvas_root_id,int_data[0],int_data[1],int_data[2],int_data[3],temp));
18552 bpr 2223
                add_to_buffer(tmp_buffer);
2224
               break;
2225
            }
2226
          }
2227
          reset();
2228
          break;
2229
        case HTML:
2230
  /*
18556 bpr 2231
  @ html x1,y1,html_string
2232
  @ all tags are allowed, html code using inputfields could be read using your own javascript code. Do not use ids like 'canvas_input0' etc.
2233
  @ can be set <a href='#onclick'>onclick</a>  and <a href='#drag'>drag&amp;drop</a>
2234
  @ command <a href='#affine'>affine</a> will produce CSS3 matrix transformations
2235
  @ command <a href='#rotate'>rotate</a> will rotate the object
2236
  @ use keyword <a href='#centered'>centered</a> to center the html object on (x1:y1)
2237
  @ note: using drag&amp;drop for all external P,SPAN,DIV,IMG,SVG-images onto a canvasdraw element, use ''onclick=javascript:place_image_on_canvas(this.id)``
2238
  @ note: sub &amp; sup are supported in command family <a href='#string'>string</a>, e.g. real internal canvas objects !
2239
  @%html-text%size 500,500%xrange -10,10%yrange -10,10%drag xy%centered%fillcolor lightblue%html 2,2,<h1 style='color:red'>DRAG ME</h1> %opacity 200,50%drag xy%fcircle 0,0,100,green
2240
  @%html-image-slider%size 500,500%xrange -10,10%yrange -10,10%fontsize 42%rotationcenter 0,0%centered%html 0,0,<img src="http://85.148.206.56/gifs/can1.gif">%slider 0,pi,400,40,angle active degree, %centered%html 0,0,<img src="http://85.148.206.56/gifs/can2.gif">
18552 bpr 2241
  */
2242
          js_function[DRAW_XML] = 1;
2243
          for(i=0;i<5;i++){
2244
            switch(i){
2245
              case 0: double_data[0] = get_real(infile,0);break;
2246
              case 1: double_data[1] = get_real(infile,0);break;
2247
              case 4: decimals = find_number_of_digits(precision);
2248
                if(use_affine == TRUE ){ transform(2,2);}/* needs double_data[] */
2249
                if( use_offset != 0 || drag_type != -1 ){int_data[2] = 1;}else{int_data[2] = 0;} /* only centered or not-centered */
2250
                int_data[0] = x2px(double_data[0]);/* needs px */
2251
                int_data[1] = y2px(double_data[1]);
18656 schaersvoo 2252
                if( use_slider != -1 && onclick == 0){ onclick = 5; }/* no drag&onclick but slideable */
18552 bpr 2253
                if( use_slider != -1 && drag_type != -1){ onclick = 5; }
2254
                temp = get_string(infile,1);
2255
                if( strstr(temp,"\"") != 0 ){ temp = str_replace(temp,"\"","\\\""); }
2256
                if( strstr(temp,"<img ")!= 0){URL="image";}else{URL="html";}
18557 bpr 2257
                tmp_buffer=my_newmem(MAX_BUFFER);
2258
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "var draw_xml%d = {id:%d,type:'%s',x:[%d],y:[%d],mathml:\"%s\",drag_type:%d,onclick:%d,object_cnt:%d,stroke_color:\"%s\",stroke_opacity:%.2f,fill_color:\"%s\",fill_opacity:%.2f,use_center:%d,use_snap:%d,angle:%f,fontfamily:\"%s\",transform:%s,use_affine:%d,offset:[0,0],use_slider:%s,rotation_center:%s,once:true};slidergroup[%d] = null;draw_xml(draw_xml%d);\n",drawxml_cnt,drawxml_cnt,URL,int_data[0],int_data[1],temp,drag_type,onclick,object_cnt,stroke_color,stroke_opacity,fill_color,fill_opacity,int_data[2],use_snap,angle,font_family,doubledata2js_array(affine_matrix,6,decimals),use_affine,my_sliders,rotation_center,object_cnt,drawxml_cnt));
18552 bpr 2259
                add_to_buffer(tmp_buffer);
2260
                if(onclick != 0 ){object_cnt++;}
2261
                drawxml_cnt++;/* keeps track on imported img,div,p,span,mathml,svg */
2262
                break;
2263
              default:break;
2264
            }
2265
          }
2266
          reset();
2267
          break;
2268
        case IMAGEFILL:
2269
  /*
2270
  @ imagefill x,y,scaling to xsize &times; ysize?,image_url
2271
  @ The next suitable <b>filled object</b> will be filled with "image_url" tiled
2272
  @ scaling to xsize &times; ysize ? ... 1 = yes 0 = no
2273
  @ After pattern filling, the fill-color should be reset !
2274
  @ wims getins / image from class directory: imagefill 80,80,my_image.gif
2275
  @ normal url: imagefill 80,80,0,&#36;module_dir/gifs/my_image.gif
2276
  @ normal url: imagefill 80,80,1,http://adres/a/b/c/my_image.jpg
2277
  @ if dx,dy is larger than the image, the whole image will be background to the next object.
2278
  @%imagefill_tile%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%circles blue,0,0,5,3,2,5%imagefill 1.5,1.5,0,gifs/en.gif%imagefill -5,5,0,gifs/logo/wimsedu.png
2279
  @%imagefill_scale%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%circles blue,0,0,5,3,2,5%imagefill 1.5,1.5,1,gifs/en.gif%imagefill -5,5,1,gifs/logo/wimsedu.png
2280
  */
2281
          js_function[DRAW_IMAGEFILL] = 1;
2282
          if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */
2283
            js_function[DRAW_FILLTOBORDER] = 1;
2284
            add_js_filltoborder(canvas_type);
2285
          }
2286
          for(i=0 ;i < 4 ; i++){
2287
            switch(i){
2288
              case 0:int_data[0] = (int) (get_real(infile,0));break;
2289
              case 1:int_data[1] = (int) (get_real(infile,0));break;
2290
              case 2:int_data[2] = (int) (get_real(infile,0));break; /* 0 | 1 */
2291
              case 3: URL = get_string_argument(infile,1);
18557 bpr 2292
                tmp_buffer=my_newmem(MAX_BUFFER);
2293
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_imagefill(%d,%d,%d,\"%s\",%d,%d,%d,%d);\n",STATIC_CANVAS+fill_cnt,int_data[0],int_data[1],URL,xsize,ysize,use_userdraw,int_data[2]));
18552 bpr 2294
                add_to_buffer(tmp_buffer);
2295
                fill_cnt++;
2296
              break;
2297
            }
2298
          }
2299
          reset();
2300
          break;
2301
        case IMAGEPALETTE:
2302
  /*
18556 bpr 2303
  @ imagepalette image1,image2,image3,...
2304
  @ if used before and together with command <a href='#multidraw'>multidraw images,..,..., etc</a> the image will be presented in a small table in the ''control panel``.
2305
  @%imagepalette%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%copy 0,0,-1,-1,-1,-1,gifs/images/skull_and_crossbones50.png%fontcolor green%fontfamily Bold 42pt Arial%imagepalette gifs/ca.gif,gifs/en.gif,gifs/nl.gif,gifs/fr.gif,gifs/cn.gif,gifs/de.gif,gifs/kh.gif,gifs/it.gif%multiuserinput 0,0,1%css color:blue;%multisnaptogrid 1,1,1%multilinewidth 0,4,0%# attention: use unicode text input without the slash %# \u222D ---> u222D at least will sometimes work%# otherwise cut&past unicode symbols into inputfield...%multilabel TEXT,REACTION ARROW,FLAGS,STOP DRAWING%multidraw text,arrow,images
18552 bpr 2306
   */
2307
          temp = get_string(infile,1);
2308
          temp = str_replace(temp,",","\",\"");
2309
          if( use_tooltip == 1 ){canvas_error("command 'imagepalette' is incompatible with command 'intooltip tip_text',as they use the same div-element ");}
2310
          fprintf(js_include_file,"\nvar current_id;var imagepalette = [\" %s \"];\n",temp);
2311
          break;
2312
        case INPUT:
2313
  /*
18556 bpr 2314
  @ input x,y,size,editable,value
2315
  @ to set inputfield "readonly", use editable = 0
2316
  @ if no preset 'value' is needed...use a 'space' as last item argument
2317
  @ only active inputfields (editable = 1) will be read with read_canvas();
2318
  @ if ''&#36;status=done`` (e.g. in answer.phtml) the inputfield will be cleared and set readonly<br>override this by keyword <a href="#status">status</a>
2319
  @ may be further controlled by <a href="#css">css</a>
2320
  @ if mathml inputfields are present and / or some userdraw is performed, these data will <b>not</b> be send as well (javascript:read_canvas();)
2321
  @ use keyword <a href='#xoffset'>xoffset | centered</a> if the inputfield should be centered on (x:y)<br> default is the left top corner is (x:y)
2322
  @ if the student must place an inputfield(s) somewhere on the canvas, use command <a href="#userdraw">userdraw input,color</a> or make use of a command like <a href="#userdraw">userdraw text,color</a>
2323
  @%input%size 400,400%xrange -10,10%yrange -10,10%linewidth 6%point 1,2,red%input 1,2,5,1, ?%point -5,5,red%input -5,5,5,1, ?%point 6,-5,red%input 6,-5,5,1, ?%point -5,-8,red%input -5,-8,5,1, ?
18552 bpr 2324
  */
2325
          js_function[DRAW_INPUTS] = 1;
2326
          for(i = 0 ; i<5;i++){
2327
            switch(i){
2328
              case 0: int_data[0]=x2px(get_real(infile,0));break;/* x in px */
2329
              case 1: int_data[1]=y2px(get_real(infile,0));break;/* y in px */
2330
              case 2: int_data[2]=abs( (int)(get_real(infile,0)));break; /* size */
2331
              case 3: if( get_real(infile,1) >0){int_data[3] = 1;}else{int_data[3] = 0;};break; /* readonly */
2332
              case 4: temp = get_string(infile,3);
18557 bpr 2333
                tmp_buffer=my_newmem(MAX_BUFFER);
2334
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_static_inputs(%d,%d,%d,%d,%d,%d,\"%s\",\"%s\",%d);\n",canvas_root_id,input_cnt,int_data[0],int_data[1],int_data[2],int_data[3],css_class,temp,use_offset));
18552 bpr 2335
                add_to_buffer(tmp_buffer);
2336
                input_cnt++;break;
2337
              default: break;
2338
            }
2339
          }
2340
          if(reply_format == 0 ){reply_format = 15;}
2341
          reset();
2342
          break;
2343
        case INTOOLTIP:
18556 bpr 2344
  /*
2345
  @ intooltip link_text
2346
  @ link_text is a single line (span-element)
2347
  @ link_text may also be an image URL ''http://some_server/images/my_image.png`` or ''&#36;module_dir/gifs/my_image.jpg``
2348
  @ link_text may contain HTML markup
2349
  @ the canvas will be displayed in a tooltip on ''link_text``
2350
  @ the canvas is default transparent: use command <a href="#bgcolor">bgcolor color</a> to adjust background-color, the link text will also be shown with this 'bgcolor'.
2351
  @ many ''userinput stuff`` will use the tooltip_placeholder_div element...only one is defined in the wims-page<br>and are therefore these commands are mutually exclusive.<br>keep this in mind...
2352
  @%intooltip%size 400,400%xrange -10,10%yrange -10,10%fontfamily Bold 42pt Courier%string black,0,0,Hello World%intooltip <span style="background-color:black;color:white;font-style:bold;font-size:48pt;">CLICK <br>HERE</span>
2353
  */
18552 bpr 2354
          if(use_input_xy != FALSE ){canvas_error("intooltip can not be combined with userinput_xy or other commands using the tooltip-div...see documentation");}
2355
          if( use_tooltip == 1 ){ canvas_error("command 'intooltip' cannot be combined with command 'popup'...");}
2356
          tooltip_text = get_string(infile,1);
2357
          if(strstr(tooltip_text,"\"") != 0 ){ tooltip_text = str_replace(tooltip_text,"\"","'"); }
2358
          use_tooltip = 1;
2359
          break;
2360
        case JSCURVE:
2361
  /*
18556 bpr 2362
  @ jscurve color,formula1(x),formula2(x),formula3(x),...
2363
  @ alternative: jsplot
2364
  @ your function will be plotted by the javascript engine of the client browser
2365
  @ if <a href='trange'>trange</a> is defined, the two functions will be plotted parametric<br><b>note</b>: use <i>x</i> as variable...and not <i>t</i>. Use keyword <a href='#animate'>animate</a> to animate a point on the curve
2366
  @ use only basic math in your curve: <code>sqrt,^,asin,acos,atan,log,pi,abs,sin,cos,tan,e</code>
2367
  @ use parenthesis and rawmath: use 2*x instead of 2x ; use 2^(sin(x))...etc etc (use error console to debug any errors...)
2368
  @ <b>attention</b>: last ''precision`` command in the canvasdraw script determines the calculation precision of the javascript curve plot !
2369
  @ no validity check is done by wims.
2370
  @ zooming & panning are implemented:<br>use command ''zoom color`` for mouse driven zooming<br>or use keyword 'setlimits' for inputfields setting xmin/xmax, ymin/ymax
2371
  @ zooming & panning is better than for curves produced by command <a href="#curve">curve color,formula</a> because for avery change in x/y-range the curve is recalculated in javascript
2372
  @ zooming & panning in case of userbased functionplot: reclick the OK button to re-plot curve onto the resized grid
2373
  @ use keyword <a href='animate'>animate</a> for animating a point on the curve
2374
  @ use command ''trace_jscurve formula(x)`` for tracing
2375
  @ use command ''jsmath formula(x)`` for calculating and displaying indiviual points on the curve
2376
  @ can <b>not</b> be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> (yet)
2377
  @ commands plotjump / plotstep are not active for ''jscurve``
2378
  @ every command jscurve will produce a new canvas (canvastype 111,112,113...) for this one curve.
18572 bpr 2379
  @ plotting multiple js-curves on the same canvas (for example if you want to use 'userdraw clickfill,color' on <a href="#canvastype">canvastype</a> number 111, use:<br> <code>jscurve red,fun1(x),fun2(x)...fun_n(x)</code>, you must specify individual multistrokecolors &amp; multistrokeopacity &amp; multilinewidth for these multiple js-curves to use different colors. Otherwise all curves will be the same color... Use commands like: <a href="#multistrokecolors">multistrokecolors</a>, <a href="#multilinewidth">multilinewidth</a>, <a href="#multidash">multidash</a>, <a href="#multistrokeopacity">multistroke</a>, <b>color</b> given for the command <code>jscurve color,formulas(x)</code> will not be used in that case... but the color argument must still be given in any case (otherwise syntax error...)
18556 bpr 2380
  @%jscurve%size 400,400%xrange -10,10%yrange -10,10%multistrokecolors red,green,blue,orange%multilinewidth 1,2,3%multistrokeopacity 0.5,0.8,1.0%jscurve red,sin(x),1/sin(x),sin(x^2)
18552 bpr 2381
  */
2382
          jsplot_cnt++;/* -1 --> 0 */
2383
          stroke_color = get_color(infile,0);
2384
          js_function[JS_MATH] = 1;
2385
          js_function[JS_PLOT] = 1;
2386
          if( tmin != 0 && tmax !=0){use_parametric = TRUE;}
2387
          temp = get_string(infile,1);
2388
          temp = str_replace(temp,",","\",\"");
18557 bpr 2389
          tmp_buffer=my_newmem(MAX_BUFFER);
2390
          check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "var js_plot%d = function(){jsplot(%d,[\"%s\"],[%d],[\"%s\"],[%.2f],[%d],%d,%d,[%f,%f],%d,%d,%d,0);};js_plot%d();",jsplot_cnt,JSPLOT_CANVAS+jsplot_cnt,temp,line_width,stroke_color,stroke_opacity,use_dashed,dashtype[0],dashtype[1],tmin,tmax,plot_steps,use_parametric,use_animate,jsplot_cnt));
18552 bpr 2391
          add_to_buffer(tmp_buffer);
2392
          fprintf(js_include_file,"if(typeof(all_jsplots) !== 'number'){var all_jsplots;};all_jsplots = %d;",jsplot_cnt);
11806 schaersvoo 2393
 
18552 bpr 2394
       /* we need to create multiple canvasses, so we may zoom and pan ?? */
2395
          break;
2396
        case JSMATH:
2397
  /*
18556 bpr 2398
  @ jsmath some_math_function
2399
  @ will calculate an y-value from a userinput x-value and draws a crosshair on these coordinates.
2400
  @ default labels ''x`` and ''y``; the commands ''xlabel some_x_axis_name`` and ''ylabel some_y_axis_name`` will set the label for the input fields
2401
  @ use command 'css some_css' for styling the display fields. Use command 'fontsize int' to size the labels ''x`` and ''y``
2402
  @ the client browser will convert your math function to javascript math.<br>use parenthesis and rawmath: use 2*x instead of 2x etc etc<br>no check is done on the validity of your function and/or syntax<br>use error console to debug any errors...
2403
  @ be aware that the formula's of the plotted function(s) can be found in the page javascript source
2404
  @%jsmath%size 400,400%xrange -10,10%yrange -10,10%jsplot blue,sin(x^2)%jsmath sin(x^2)
18552 bpr 2405
  */
2406
          js_function[DRAW_CROSSHAIRS] = 1;
2407
          js_function[JS_MATH] = 1;
2408
          add_calc_y(get_string(infile,1),font_size,css_class);
2409
          break;
2410
        case KILL:
2411
  /*
2412
  @ kill arguments
2413
  @ arguments may be: affine linear translation rotation slider offset  reset
2414
  @ for documentation see: killaffine,killlinear,killtranslation...
2415
  @ multiple arguments are allowed (although not checked for validity...)
2416
  */
2417
          temp = get_string(infile,1);
2418
          if(strstr(temp,"affine") != 0 ){use_affine = FALSE;affine_matrix[0] = 1.0;affine_matrix[1] = 0.0;affine_matrix[2] = 0.0;affine_matrix[3] = 1.0;affine_matrix[4] = 0.0;affine_matrix[5] = 0.0;}
2419
          if(strstr(temp,"linear") != 0 ){affine_matrix[0] = 1.0;affine_matrix[1] = 0.0;affine_matrix[2] = 0.0;affine_matrix[3] = 1.0;}
2420
          if(strstr(temp,"translation") != 0 || strstr(temp,"translate") != 0 ){affine_matrix[4] = 0.0;affine_matrix[5] = 0.0;}
2421
          if(strstr(temp,"rotation") != 0 || strstr(temp,"rotate") != 0 ){use_rotate = FALSE;angle = 0.0;rotation_center="null";}
2422
          if(strstr(temp,"slider") != 0 ){slider_type = "0";my_sliders = "[-1]";last_slider = use_slider+1;}
2423
          if(strstr(temp,"group") != 0 ){onclick = 0;drag_type = -1;slider_type = "0";my_sliders = "[-1]";last_slider = use_slider+1;use_slider = -1;reset();}
2424
          if(strstr(temp,"reset") != 0 ){if(no_reset == FALSE){no_reset = TRUE;}else{no_reset = FALSE;reset();}}
2425
          if(strstr(temp,"offset") != 0 ){use_offset = 0;}
2426
          break;
2427
        case KILLAFFINE:
2428
  /*
2429
  @ killaffine
2430
  @ keyword: resets the transformation matrix to 1,0,0,1,0,0
2431
  @ note: any active linear transformation will also be reset: tx=0, ty=0
2432
  */
2433
          use_affine = FALSE;
2434
          affine_matrix[0] = 1.0;
2435
          affine_matrix[1] = 0.0;
2436
          affine_matrix[2] = 0.0;
2437
          affine_matrix[3] = 1.0;
2438
          affine_matrix[4] = 0.0;
2439
          affine_matrix[5] = 0.0;
2440
          break;
2441
        case KILLLINEAR:
2442
  /*
2443
  @ killlinear
2444
  @ keyword: resets the transformation matrix to 1,0,0,1,tx,ty
2445
  @ note:any active transformation or rotation will not be killed (tx,ty remain active)
2446
  */
2447
          affine_matrix[0] = 1.0;
2448
          affine_matrix[1] = 0.0;
2449
          affine_matrix[2] = 0.0;
2450
          affine_matrix[3] = 1.0;
2451
          break;
2452
        case KILLROTATE:
2453
  /*
18556 bpr 2454
  @ killrotate
2455
  @ will set the rotation angle to 0.
18572 bpr 2456
  @ will also reset the command <a href="#rotationcenter">rotationcenter</a> to the first (x;y) of the next rotatable/slidable object(s) <br>eg a following rotate command will have the first object point as rotation center
18556 bpr 2457
  @ if not set, the rotation center will remain unchanged
2458
  @ note:any active transformation or linear will not be killed (e.g an active transformation matrix remains active)
2459
  @%killrotate%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%rotationcenter 0,0%# slider is active for all following objects until 'killslider'%slider -10,10,300,40,angle degree,Rotate%drag xy%# after dragging the object must be clicked to re-activate the slider%linewidth 4%arrow 0,0,6,0,9,blue%%# reset rotation center to the first (x,y) of the next object/arrow...%killrotate%drag xy%# after dragging the object must be clicked to re-activate the slider%arrow 0,0,6,1,9,red
18552 bpr 2460
  */
2461
          use_rotate = FALSE;
2462
          angle = 0.0;
2463
          rotation_center="null";
2464
          break;
2465
        case KILLSLIDER:
2466
  /*
18556 bpr 2467
  @ killslider
2468
  @ keyword (no arguments required)
2469
  @ ends grouping of object under a previously defined slider
18552 bpr 2470
  */
2471
          slider_type = "0";
2472
          my_sliders = "[-1]";
2473
          last_slider = use_slider+1;
2474
          break;
2475
        case KILLTRANSLATION:
2476
  /*
18556 bpr 2477
  @ killtranslation
2478
  @ alternative: killtranslate
2479
  @ note: a active linear or affine transformation will not be 100% reset...only tx=0,ty=0
2480
  @ resets the translation matrix a,b,c,d,tx,ty to a,b,c,d,0,0
18552 bpr 2481
  */
2482
          affine_matrix[4] = 0.0;
2483
          affine_matrix[5] = 0.0;
2484
          break;
2485
        case LATEX:
2486
  /*
18556 bpr 2487
  @ latex x,y,tex string
2488
  @ alternative: math
18572 bpr 2489
  @ note: <b>for a single greek letter</b> ,please be smart and use a command like <a href='#string'>string</a> along with <b>unicode</b> !! <br>possibly together with command <a href="#xyoffset">xoffset, yoffset or xyoffset</a><br> See <a target='new' href='https://en.wikipedia.org/wiki/Mathematical_operators_and_symbols_in_Unicode'>https://en.wikipedia.org/wiki/Mathematical_operators_and_symbols_in_Unicode</a><br> See <a target='new' href='https://en.wikipedia.org/wiki/Greek_script_in_Unicode'>https://en.wikipedia.org/wiki/Greek_script_in_Unicode</a>
18556 bpr 2490
  @ you may also use command <a href="#mathml">mathml</a> for xml strings generated with wims commmand ''mathmlmath`` (will not work on KaTeX enabled WIMS)
2491
  @ transformation commands <a href='#affine'>affine</a>, <a href='#translation'>translation</a> and <a href='#rotate'>rotate</a> are supported.(onclick and drag will work)
2492
  @ can be set onclick: <code>javascript:read_dragdrop();</code> will return click numbers of mathml-objects<br>if 4 clickable object are drawn, the reply could be 1,0,1,0 ... meaning clicked on the first and third object
2493
  @ can be set draggable:<code>javascript:read_dragdrop();</code> will return all coordinates in the same order as the canvas script: unmoved object will have their original coordinates...
2494
  @ can be moved/rotated with command <a href='#slider'>slider</a>
2495
  @ snaptogrid is supported
18627 bpr 2496
  @ when clicked, the color of the 'div background' of the 'mathobject' will be determined by the <a href="#fillcolor">fillcolor</a> and <a href="#opacity">opacity</a> settings
18556 bpr 2497
  @ userdraw may be combined with 'latex' ; the js-function 'read_canvas()' will contain the coordinates of the drawing.
2498
  @ userdraw may be combined; the read_canvas() will contain the drawing.
2499
  @ draggable or onclick 'external images' from command <a href='#copyresized'>copy or copyresized</a> and all objects from commands <a href='#html'>html</a> or <a href='#obabel'>obabel</a> can be combined with drag and/or onclick mathml
2500
  @ other drag objects (circles/rects etc) are supported, but read_dragdrop() will probably be difficult to interpret...
2501
  @ if inputfields are incorporated in mathml (with id's: id='mathml0',id='mathml1',...id='mathml_n')<br>the user_input values will be read by <code>javascript:read_mathml();</code>. <b>attention</b>: if after this mathml-input object other user-interactions are included, these will read mathml too using "read_canvas();"
2502
  @ If other inputfields (command input / command textarea) or userdraw are performed, the function read_canvas() will not read mathml. Use some generic function to read it....
2503
  @ use keyword <a href='#centered'>centered</a> to center the katex div object on (x1:y1) <br>this may not work as expected for MathJaX [TO BE TESTED]
2504
  @ note: if you want to include external TeX via drag&amp;drop onto a canvasdraw element, use \\mmlid{integer} in the tex-command:''!insmath \\mmlid{1}\\frac{1}{\pi}``<br> (if your wims_mathml does not support it...use <a href="http://85.148.206.56/wims/download/Mathml.tar.gz">this version...</a>)
2505
  @ note: the same is true for all external P,SPAN,DIV,IMG,SVG-images via drag&amp;drop onto a canvasdraw element, use ''onclick=javascript:place_image_on_canvas(this.id)``
2506
  @%latex_drag%size 400,400%xrange -10,10%yrange -10,10%grid 2,2,grey%strokecolor red%drag xy%centered%latex -6,5,\\frac{1}{2}+ \\frac{\\pi}{2}%strokecolor blue%drag xy%centered%latex -3,5,\\frac{1}{3}+ \\frac{\\pi}{3}%strokecolor green%drag xy%centered%latex 0,5,\\frac{1}{4}+ \\frac{\\pi}{4}%strokecolor orange%drag xy%fontfamily 26px Times%centered%latex 3,5,\\frac{1}{5}+ \\frac{\\pi}{6}
2507
  @%latex%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 3%vline 0,0,green%hline 0,0,green%fontfamily 16px Arial%fillcolor orange%strokecolor blue%linewidth 2%slider 0,4*pi,400,40,angle degree active, %centered%latex 0,0,\\frac{12345}{23456} \\times \\frac{12345}{23456}%translate 4,4%centered%rotate 180%drag xy%html 0,0,<table><tr><th>HTML TABLE</th></tr><tr><th><a href="https://wimsedu.info/">WIMS EDU </a> </th></tr><tr><td><img src="gifs/en.gif"></tr><tr><td><img src="gifs/nl.gif"></tr><tr><td><img src="gifs/fr.gif"></tr><tr><td><img src="gifs/cn.gif"></tr><tr><td><img src="gifs/it.gif"></tr></table>%userdraw arrow2,red
18552 bpr 2508
  */
2509
          js_function[DRAW_XML] = 1;
2510
          for(i=0;i<3;i++){
2511
            switch(i){
2512
              case 0: double_data[0]=get_real(infile,0);break; /* x in x/y-range coord system -> pixel width */
2513
              case 1: double_data[1]=get_real(infile,0);break; /* y in x/y-range coord system  -> pixel height */
2514
              case 2: decimals = find_number_of_digits(precision);
2515
                temp = get_string(infile,1);
2516
                if(use_affine == TRUE ){ transform(2,2);}/* slider will use css-rotate transformation */
2517
                if( use_offset != 0 || drag_type != -1 ){int_data[2] = 1;}else{int_data[2] = 0;} /* only centered or not-centered */
2518
                int_data[0] = x2px(double_data[0]);
2519
                int_data[1] = y2px(double_data[1]);
2520
                if( use_slider != -1 && onclick == 0 ){ onclick = 5;}
2521
                if( use_slider != -1 && drag_type != -1){ onclick = 5; }
15757 schaersvoo 2522
#ifdef KATEX_INSTALLED
18552 bpr 2523
                if( strstr(temp,"\\") != 0 ){ temp = str_replace(temp,"\\","\\\\"); }
2524
                if( strstr(temp,"\"") != 0 ){ temp = str_replace(temp,"\"","'"); }
18557 bpr 2525
                tmp_buffer=my_newmem(MAX_BUFFER);
2526
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "var draw_xml%d = {id:%d,type:'katex',x:[%d],y:[%d],mathml:\"%s\",drag_type:%d,onclick:%d,object_cnt:%d,stroke_color:\"%s\",stroke_opacity:%.2f,fill_color:\"%s\",fill_opacity:%.2f,use_center:%d,use_snap:%d,angle:%f,fontfamily:\"%s\",transform:%s,use_affine:%d,offset:[0,0],use_slider:%s,rotation_center:%s,once:true};draw_xml(draw_xml%d);\n",drawxml_cnt,drawxml_cnt,int_data[0],int_data[1],temp,drag_type,onclick,object_cnt,stroke_color,stroke_opacity,fill_color,fill_opacity,int_data[2],use_snap,angle,font_family,doubledata2js_array(affine_matrix,6,decimals),use_affine,my_sliders,rotation_center,drawxml_cnt));
15757 schaersvoo 2527
#else
18552 bpr 2528
                temp = getMML(temp);/* generate MathML for Firefox or MathJaX */
2529
                if( strstr(temp,"\"") != 0 ){ temp = str_replace(temp,"\"","'"); }
18557 bpr 2530
                tmp_buffer=my_newmem(MAX_BUFFER);
2531
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "var draw_xml%d = {id:%d,type:'mathml',x:[%d],y:[%d],mathml:\"%s\",drag_type:%d,onclick:%d,object_cnt:%d,stroke_color:\"%s\",stroke_opacity:%.2f,fill_color:\"%s\",fill_opacity:%.2f,use_center:%d,use_snap:%d,angle:%f,fontfamily:\"%s\",transform:%s,use_affine:%d,offset:[0,0],use_slider:%s,rotation_center:%s,once:true};draw_xml(draw_xml%d);\n",drawxml_cnt,drawxml_cnt,int_data[0],int_data[1],temp,drag_type,onclick,object_cnt,stroke_color,stroke_opacity,fill_color,fill_opacity,int_data[2],use_snap,angle,font_family,doubledata2js_array(affine_matrix,6,decimals),use_affine,my_sliders,rotation_center,drawxml_cnt));
15757 schaersvoo 2532
#endif
18552 bpr 2533
                add_to_buffer(tmp_buffer);
2534
                if(onclick != 0 ){object_cnt++;}
2535
                drawxml_cnt++;/* keeps track on imported img,div,p,span,mathml,svg */
2536
                break;
2537
              default:break;
2538
              }
2539
          }
2540
          reset();
2541
          break;
2542
        case LATTICE:
2543
  /*
18556 bpr 2544
  @ lattice x0,y0,xv1,yv1,xv2,yv2,n1,n2,color
2545
  @ can <b>not</b> be set ''onclick`` or ''drag xy``
2546
  @%lattice%size 400,400%xrange -10,10%yrange -10,10%fillcolor red%linewidth 2%lattice -10,-10,0,1,1,1,10,10,red%fillcolor blue%lattice 10,-10,0,1,-1,1,10,10,blue
18552 bpr 2547
  */
2548
          js_function[DRAW_LATTICE] = 1;
2549
          for( i = 0; i<9; i++){
2550
            switch(i){
2551
              case 0: int_data[0] = x2px(get_real(infile,0));break; /* x0-values  -> x-pixels*/
2552
              case 1: int_data[1] = y2px(get_real(infile,0));break; /* y0-values  -> y-pixels*/
2553
              case 2: int_data[2] = (int) (get_real(infile,0));break; /* x1-values  -> x-pixels*/
2554
              case 3: int_data[3] = (int) -1*(get_real(infile,0));break; /* y1-values  -> y-pixels*/
2555
              case 4: int_data[4] = (int) (get_real(infile,0));break; /* x2-values  -> x-pixels*/
2556
              case 5: int_data[5] = (int) -1*(get_real(infile,0));break; /* y2-values  -> y-pixels*/
2557
              case 6: int_data[6] = (int) (get_real(infile,0));break; /* n1-values */
2558
              case 7: int_data[7] = (int) (get_real(infile,0));break; /* n2-values */
2559
              case 8: stroke_color=get_color(infile,1);
2560
                decimals = find_number_of_digits(precision);
18557 bpr 2561
                tmp_buffer=my_newmem(MAX_BUFFER);
2562
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_lattice(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,\"%s\",%.2f,\"%s\",%.2f,%d,%.2f,%d); ",STATIC_CANVAS,line_width,int_data[0],int_data[1],int_data[2],int_data[3],int_data[4],int_data[5],int_data[6],int_data[7],fill_color,fill_opacity,stroke_color,stroke_opacity,use_rotate,angle,use_filled));
18552 bpr 2563
                add_to_buffer(tmp_buffer);break;
2564
              default:break;
2565
            }
2566
          }
2567
          reset();
2568
          break;
2569
        case LINEAR:
2570
  /*
18556 bpr 2571
  @ linear a,b,c,d
2572
  @ defines a transformation matrix for subsequent objects
2573
  @ use keyword <a href='#killlinear'>killlinear</a> to end the transformation...the next objects will be drawn in the original x/y-range
2574
  @ a: Scales the drawings horizontally
2575
  @ b: Skews the drawings horizontally
2576
  @ c: Skews the drawings vertically
2577
  @ d: Scales the drawings vertically
2578
  @ the data precision may be set by preceding command ''precision int``
2579
  @ note: any active translation (tx,ty) is not changed
2580
  @%linear%size 400,400%xrange -10,10%yrange -10,10%opacity 255,255%fcircle 5,5,40,blue%linear 0.2,0,0,0.2%fcircle 5,5,40,green
18552 bpr 2581
  */
2582
          for(i = 0 ; i<4;i++){
2583
            switch(i){
2584
              case 0: affine_matrix[0] = get_real(infile,0);break;
2585
              case 1: affine_matrix[1] = get_real(infile,0);break;
2586
              case 2: affine_matrix[2] = get_real(infile,0);break;
2587
              case 3: affine_matrix[3] = get_real(infile,1);
2588
                affine_matrix[4] = 0;affine_matrix[5] = 0;
2589
                use_affine = TRUE;
2590
                break;
2591
              default: break;
2592
            }
2593
          }
2594
          reset();
2595
         break;
2596
        case LINE:
2597
  /*
2598
  @ line x1,y1,x2,y2,color
2599
  @ draw a line through points (x1:y1)--(x2:y2) in color ''color``
2600
  @ or use command ''curve color,formula`` to draw the line (uses more points to draw the line; is however better draggable)
2601
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
2602
  @%line%size 400,400%xrange -10,10%yrange -10,10%line 0,1,2,-1,green
2603
  */
2604
          for(i=0;i<5;i++){
2605
            switch(i){
2606
              case 0: double_data[10]= get_real(infile,0);break; /* x-values */
2607
              case 1: double_data[11]= get_real(infile,0);break; /* y-values */
2608
              case 2: double_data[12]= get_real(infile,0);break; /* x-values */
2609
              case 3: double_data[13]= get_real(infile,0);break; /* y-values */
2610
              case 4: stroke_color=get_color(infile,1);/* name or hex color */
2611
                if( double_data[10] == double_data[12] ){ /* vertical line*/
2612
                  double_data[1] = xmin;
2613
                  double_data[3] = ymax;
2614
                  double_data[0] = double_data[10];
2615
                  double_data[2] = double_data[10];
2616
                }
2617
                else{
2618
                  if( double_data[11] == double_data[13] ){ /* horizontal line */
2619
                    double_data[1] = double_data[11];
2620
                    double_data[3] = double_data[11];
2621
                    double_data[0] = ymin;
2622
                    double_data[2] = xmax;
2623
                }
2624
                else {
2625
      /* m */
2626
                  double_data[5] = (double_data[13] - double_data[11]) /(double_data[12] - double_data[10]);
2627
      /* q */
2628
                  double_data[6] = double_data[11] - ((double_data[13] - double_data[11]) /(double_data[12] - double_data[10]))*double_data[10];
2629
      /*xmin,m*xmin+q,xmax,m*xmax+q*/
2630
                  double_data[1] = (double_data[5])*(xmin)+(double_data[6]);
2631
                  double_data[3] = (double_data[5])*(xmax)+(double_data[6]);
2632
                  double_data[0] = xmin;
2633
                  double_data[2] = xmax;
2634
                }
2635
              }
2636
              if(use_rotate == TRUE ){rotate(4,angle,rotationcenter,2);}
2637
              if(use_affine == TRUE ){ transform(4,2);}
2638
              if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
2639
              decimals = find_number_of_digits(precision);
18557 bpr 2640
              tmp_buffer=my_newmem(MAX_BUFFER);
2641
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[1],decimals,double_data[3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 2642
              add_to_buffer(tmp_buffer);
2643
              if(onclick != 0){object_cnt++;}
2644
        /* object_cnt++;*/
2645
              reset();
2646
              break;
2647
            }
2648
          }
2649
          dragstuff[4] = 1;
2650
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
2651
          break;
2652
        case LINES:
2653
  /*
2654
  @ lines color,x1,y1,x2,y2...x_n-1,y_n-1,x_n,y_n
2655
  @ draw multiple lines through points (x1:y1)--(x2:y2) ...(x_n-1:y_n-1)--(x_n:y_n) in color 'color'
2656
  @ or use multiple commands ''curve color,formula`` or ''jscurve color,formule`` to draw the line <br>(uses more points to draw the line; is however better draggable)
2657
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
2658
  @%lines%size 400,400%xrange -10,10%yrange -10,10%lines green,0,1,1,3,0,0,1,3,0,0,-2,1
2659
  */
2660
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
2661
          fill_color = stroke_color;
2662
          i=0;
2663
          while( ! done ){     /* get next item until EOL*/
2664
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
2665
            if(i%2 == 0 ){
2666
              double_data[i] = get_real(infile,0); /* x */
2667
            }
2668
            else {
2669
              double_data[i] = get_real(infile,1); /* y */
2670
            }
2671
            i++;
2672
          }
2673
          decimals = find_number_of_digits(precision);
2674
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
2675
          for(c = 0 ; c < i-1 ; c = c+4){
2676
            if(double_data[c] == double_data[c+2] ){ /* vertical line*/
2677
              double_data[c+1] = xmin;
2678
              double_data[c+3] = ymax;
2679
              double_data[c+2] = double_data[c];
2680
            }
2681
            else {
2682
              if( double_data[c+1] == double_data[c+3] ){ /* horizontal line */
2683
                double_data[c+3] = double_data[c+1];
2684
                double_data[c] = ymin;
2685
                double_data[c+2] = xmax;
2686
              }
2687
              else {
2688
      /* m */
2689
                double m = (double_data[c+3] - double_data[c+1]) /(double_data[c+2] - double_data[c]);
2690
      /* q */
2691
                double q = double_data[c+1] - ((double_data[c+3] - double_data[c+1]) /(double_data[c+2] - double_data[c]))*double_data[c];
2692
      /*xmin,m*xmin+q,xmax,m*xmax+q*/
2693
                double_data[c+1] = (m)*(xmin)+(q);
2694
                double_data[c+3] = (m)*(xmax)+(q);
2695
                double_data[c] = xmin;
2696
                double_data[c+2] = xmax;
2697
              }
2698
            }
2699
            if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
2700
            if(use_affine == TRUE ){ transform(i-1,2);}
18557 bpr 2701
            tmp_buffer=my_newmem(MAX_BUFFER);
2702
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 2703
            add_to_buffer(tmp_buffer);
2704
            if(onclick != 0){object_cnt++;}
2705
    /* object_cnt++; */
2706
          }
2707
          dragstuff[4] = 1;
2708
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
2709
          reset();
2710
          break;
2711
        case LINEWIDTH:
2712
  /*
2713
  @ linewidth int
2714
  @ default 1
2715
  @%linewidth%size 400,400%xrange -10,10%yrange -10,10%linewidth 1%line -5,-5,-5,5,red%linewidth 2%line -4,-5,-4,5,green%linewidth 3%line -3,-5,-3,5,blue%linewidth 4%line -2,-5,-2,5,orange%linewidth 1%line -1,-5,-1,5,brown%linewidth 5%line 1,-5,1,5,cyan%linewidth 6%line 3,-5,3,5,purple%linewidth 7%line 5,-5,5,5,black
2716
  */
2717
          line_width = (int) (get_real(infile,1));
2718
          break;
18669 bpr 2719
        case LEVELSTEP:
2720
          level_step = (int) (get_real(infile,1));
2721
          if (level_step < 1) level_step=1;
2722
          if (level_step > 16) level_step=16;
2723
          break;
18552 bpr 2724
        case LEVELCURVE:
2725
  /*
2726
  @ levelcurve color,expression in x/y,l1,l2,...
2727
  @ draws very primitive level curves for expression, with levels l1,l2,l3,...,l_n
2728
  @ the quality is <b>not to be compared</b> with the Flydraw levelcurve. <br>(choose flydraw if you want quality...)
2729
  @ every individual level curve may be set 'onclick / drag xy' <br>e.g. every single level curve (l1,l2,l3...l_n) has a unique identifier
2730
  @ note: the arrays for holding the javascript data are limited in size
2731
  @ note: reduce image size if javascript data arrays get overloaded<br>(command 'plotsteps int' will not control the data size of the plot...)
2732
  @%levelcurve%size 400,400%xrange -10,10%yrange -10,10%levelcurve red,x*y,1,2,3,4
2733
  */
2734
          fill_color = get_color(infile,0);
2735
          char *fun1 = get_string_argument(infile,0);
2736
          if( strlen(fun1) == 0 ){canvas_error("function is NOT OK !");}
2737
          i = 0;
2738
          done = FALSE;
2739
          while( !done ){
2740
            double_data[i] = get_real(infile,1);
2741
            i++;
2742
          }
2743
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
2744
          for(c = 0 ; c < i; c++){
18557 bpr 2745
            tmp_buffer=my_newmem(MAX_BUFFER);
18669 bpr 2746
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,16,%s,[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,eval_levelcurve(xsize,ysize,fun1,xmin,xmax,ymin,ymax,level_step,precision,double_data[c]),line_width,line_width,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 2747
            add_to_buffer(tmp_buffer);
2748
            if(onclick != 0){object_cnt++;}
2749
           /* object_cnt++; */
2750
          }
2751
          dragstuff[16] = 1;
2752
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
2753
          reset();
2754
          break;
2755
        case LEGEND:
2756
  /*
2757
  @ legend string1:string2:string3....string_n
2758
  @ will be used to create a legend for a graph
2759
  @ also see command <a href='#piechart'>piechart</a>
2760
  @ will use the same colors per default as used in the graphs; use command <a href='#legendcolors'>legendcolors</a> to override the default
2761
  @ use command <a href="#fontsize">fontsize</a> to adjust. (command ''fontfamily`` is not active for command ''legend``)
2762
  @%legend%size 400,400%xrange -10,10%yrange -10,10%bgcolor white%fontsize 16%legend legend 1:legend 2:legend 3:legend 4:this is legend 5:legend 6:another legend abc%legendcolors red:green:blue%grid 1,1,white%# note: command "grid" is mandatory%# just set grid invisible if not wanted
2763
  */
2764
          temp = get_string(infile,1);
2765
          if( strstr( temp,":") != 0 ){ temp = str_replace(temp,":","\",\""); }
2766
          legend_cnt++; /* attention: starts with -1: it will be used in piechart etc */
2767
          fprintf(js_include_file,"var legend%d = [\"%s\"];",legend_cnt,temp);
2768
          break;
2769
        case LEGENDCOLORS:
2770
  /*
2771
  @ legendcolors color1:color2:color3:...:color_n
2772
  @ will be used to color a legend: use this command after the legend command ! e.g. <code>legend test1:test2:test3<br>legendcolors blue:red:orange</code>.
2773
  @ make sure the number of colors match the number of legend items
18627 bpr 2774
  @ command ''legend`` in case of ''piechart`` and ''barchart`` will use these colors per default (no need to specify ''legendcolors``)
18552 bpr 2775
  @%legendcolors%size 400,400%xrange -10,10%yrange -10,10%fontsize 18%legend legend 1:legend 2:legend 3%legendcolors red:green:blue%grid 1,1,grey
2776
  */
2777
          if(legend_cnt == -1){canvas_error("use command \"legend\" before command \"legendcolors\" ! ");}
2778
          temp = get_string(infile,1);
2779
          if( strstr( temp,":") != 0 ){ temp = str_replace(temp,":","\",\""); }
2780
          fprintf(js_include_file,"var legendcolors%d = [\"%s\"];",legend_cnt,temp);
2781
          break;
2782
        case LINEGRAPH: /* scheme: var linegraph_0 = [ 'stroke_color','line_width','use_dashed', 'dashtype0','dashtype1','x1','y1',...,'x_n','y_n'];*/
2783
  /*
2784
  @ linegraph x1:y1:x2:y2...x_n:y_n
2785
  @ will plot your data in a graph
2786
  @ may <b>only</b> to be used together with command <a href='#grid'>grid</a>
2787
  @ can be used together with freestyle x-axis/y-axis texts: see commands <a href='#xaxis'>xaxis</a>,<a href='#xaxisup'>xaxisup</a> and <a href='#yaxis'>yaxis</a>
2788
  @ use command <a href='#legend'>legend</a> to provide an optional legend in right-top-corner
2789
  @ also see command <a href='#piechart'>piechart</a>
2790
  @ multiple linegraphs may be used in a single plot
2791
  @ note: your arguments are not checked by canvasdraw: use your javascript console in case of trouble...
2792
  @ <ul><li>use command <a href='#strokecolor'>strokecolor</a> before a command ''linegraph`` to set the color of this graph</li><li>use command <a href='#linewidth'>linewidth</a> before command ''linegraph`` to set linewidth of this graph</li><li>use keyword <a href='#dashed'>dashed</a> before command ''linegraph`` to set dashing of the graph</li><li>if dashing is set, use command <a href='#dashtype'>dashtype</a> before command ''linegraph`` to set the type of dashing of the (individual) graph</li></ul>
2793
  @%linegraph%size 400,400%xrange -10,10%yrange -10,10%strokecolor red%linegraph -10:1:-5:-1:3:3:10:-5%strokecolor blue%linegraph -10:-1:-5:1:3:-3:10:5%dashed%strokecolor green%linegraph -10:2:-5:-2:3:4:10:2%grid 1,1,grey
2794
  */
2795
          temp = get_string(infile,1);
2796
          if( strstr( temp,":") != 0 ){ temp = str_replace(temp,":","\",\""); }
2797
          fprintf(js_include_file,"var linegraph_%d = [\"%s\",\"%d\",\"%d\",\"%d\",\"%d\",\"%s\"];",linegraph_cnt,stroke_color,line_width,use_dashed,dashtype[0],dashtype[1],temp);
2798
          linegraph_cnt++;
2799
          reset();
2800
          break;
2801
        case MATHML:
2802
  /*
2803
  @ mathml x1,y1,mathml_string
2804
  @ this command is special for GECKO browsers, and it makes use of Native Mathml
2805
  @ For general use with all browsers, use command <a href='#latex'>latex</a>
2806
  @ can be set <a href='onclick'>onclick</a>  and <a href='drag'>drag&amp;drop</a> <br>Note: dragging is fairly primitive dragging of the div-element, and is not done using the <em>dragstuff library</em>
2807
  @ command <a href='#affine'>affine</a> will produce CSS3 matrix transformations
2808
  @ command <a href='#rotate'>rotate</a> will rotate the object
2809
  @ the mathml object is centered at (x1:y1)
2810
  @ the ''mathml_string`` can be produced using WIMS commands like ''texmath`` followed by ''mathmlmath``... or write correct TeX and use only ''mathmlmath``
2811
  @ mathml will be displayed in a rectangle left top (x1:y1)
2812
  @ can be set onclick <code>javascript:read_dragdrop();</code> will return click numbers of mathml-objects; if 4 clickable object are drawn, the reply could be 1,0,1,0 ... meaning clicked on the first and third object
2813
  @ can be set draggable: <code>javascript:read_dragdrop()</code> will return all coordinates in same order as the canvas script: unmoved objects will have their original coordinates...
2814
  @ snaptogrid is supported...snaptopoints will work, but use with care... due to the primitive dragging. Technically: the dragstuff library is not used... the mathml is embedded in a new div element and not in the html5-canvas.
2815
  @ when clicked, the mathml object will be drawn in red color; the div background color will be determined by the <a href="#fillcolor">fillcolor</a> and <a href="#opacity">opacity</a> settings.
2816
  @ userdraw may be combined with 'mathml' ; the read_canvas() will contain the drawing.
2817
  @ draggable or onclick 'external images' from command <a href='#copyresized'>copy or copyresized</a> can be combined with drag and/or onclick mathml
2818
  @ other drag objects (circles/rects etc) are supported, but read_dragdrop() will probably be difficult to interpret...
2819
  @ if inputfields are incorporated in mathml (with id's: id='mathml0',id='mathml1',...id='mathml_n')<br>the user_input values will be read by javascript:read_mathml();<br><b>attention</b>: if after this mathml-input object other user-interactions are included, these will read mathml too using "read_canvas();"
2820
  @ If other inputfields (command input / command textarea) or userdraw is performed, the function read_canvas() will not read mathml. Use some generic function to read it....
2821
  @ use keyword <a href='#centered'>centered</a> to center the mathml/xml object on (x1:y1)
18654 schaersvoo 2822
  @%mathml_onclick%size 400,400%xrange -10,10%yrange -10,10%opacity 255,70%onclick%strokecolor red%fillcolor green%mathml -5,5,<span style="font-size:1em;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mstyle id="wims_mathml366290"><mrow><mo stretchy="true">[</mo><mtable rowspacing="0.5ex" columnalign=" left " columnlines=" none " rowlines=" none " ><mtr><mtd><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mstyle displaystyle="true"><mfrac><mn>1</mn><mn>2</mn></mfrac></mstyle><mo>&sdot;</mo><msup><mi>x</mi> <mn>2</mn></msup></mtd></mtr> <mtr><mtd><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><msqrt><mstyle displaystyle="true"><mfrac><mn>1</mn><mrow><msup><mi>x</mi> <mn>2</mn></msup></mrow></mfrac></mstyle></msqrt></mtd></mtr></mtable><mo stretchy="true">]</mo></mrow></mstyle></math></span>%onclick%strokecolor blue%mathml 5,5,<span style="font-size:1em;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mstyle id="wims_mathml580175" ><mrow><mo stretchy="true">[</mo><mtable rowspacing="0.5ex" columnalign=" left " columnlines=" none " rowlines="none"><mtr><mtd><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mstyle displaystyle="true"><mfrac><mn>1</mn><mrow><mi>sin</mi><mrow><mo stretchy="true">(</mo><msup><mi>x</mi> <mn>2</mn></msup><mo stretchy="true">)</mo></mrow></mrow></mfrac></mstyle></mtd></mtr> <mtr><mtd><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><msqrt><mrow><mi>sin</mi><mrow><mo stretchy="true">(</mo><msup><mi>x</mi> <mn>2</mn></msup><mo stretchy="true">)</mo></mrow></mrow></msqrt></mtd></mtr></mtable><mo stretchy="true">]</mo></mrow></mstyle></math></span>
18552 bpr 2823
  @%mathml_drag%size 400,400%xrange -10,10%yrange -10,10%drag xy%strokecolor red%mathml -5,5,<span style="font-size:1em;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mstyle id="wims_mathml366290"><mrow><mo stretchy="true">[</mo><mtable rowspacing="0.5ex" columnalign=" left " columnlines=" none " rowlines=" none "><mtr><mtd><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mstyle displaystyle="true"><mfrac><mn>1</mn><mn>2</mn></mfrac></mstyle><mo>&sdot;</mo><msup><mi>x</mi> <mn>2</mn></msup></mtd></mtr> <mtr><mtd><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><msqrt><mstyle displaystyle="true"><mfrac><mn>1</mn><mrow><msup><mi>x</mi> <mn>2</mn></msup></mrow></mfrac></mstyle></msqrt></mtd></mtr></mtable><mo stretchy="true">]</mo></mrow></mstyle></math></span>%drag xy%strokecolor blue%mathml 5,5,<span style="font-size:1em;"><math xmlns="http://www.w3.org/1998/Math/MathML" display="inline"><mstyle id="wims_mathml580175" ><mrow><mo stretchy="true">[</mo><mtable rowspacing="0.5ex" columnalign=" left " columnlines=" none " rowlines=" none "><mtr><mtd><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mstyle displaystyle="true"><mfrac><mn>1</mn><mrow><mi>sin</mi><mrow><mo stretchy="true">(</mo><msup><mi>x</mi> <mn>2</mn></msup><mo stretchy="true">)</mo></mrow></mrow></mfrac></mstyle></mtd></mtr> <mtr><mtd><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><msqrt><mrow><mi>sin</mi><mrow><mo stretchy="true">(</mo><msup><mi>x</mi> <mn>2</mn></msup><mo stretchy="true">)</mo></mrow></mrow></msqrt></mtd></mtr></mtable><mo stretchy="true">]</mo></mrow></mstyle></math></span>%#click left top corner...then drag...
2824
  */
2825
          js_function[DRAW_XML] = 1;
2826
          for(i=0;i<3;i++){
2827
            switch(i){
2828
              case 0: double_data[0]=get_real(infile,0);break; /* x in x/y-range coord system -> pixel width */
2829
              case 1: double_data[1]=get_real(infile,0);break; /* y in x/y-range coord system  -> pixel height */
2830
              case 2: decimals = find_number_of_digits(precision);
2831
                if(use_affine == TRUE ){ transform(2,2);}/* needs double_data[] */
2832
                if( use_offset != 0 || drag_type != -1 ){int_data[2] = 1;}else{int_data[2] = 0;} /* only centered or not-centered */
2833
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
2834
                int_data[0] = x2px(double_data[0]);/* needs px */
2835
                int_data[1] = y2px(double_data[1]);
2836
                if( use_slider != -1 && onclick == 0 ){ onclick = 3;}/* no drag&onclick but slideable */
2837
                if( use_slider != -1 && drag_type != -1){ onclick = 5; }
2838
                temp = get_string(infile,1);
2839
                if( strstr(temp,"\"") != 0 ){ temp = str_replace(temp,"\"","'"); }
18557 bpr 2840
                tmp_buffer=my_newmem(MAX_BUFFER);
2841
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "var draw_xml%d = {id:%d,type:'mathml',x:[%d],y:[%d],mathml:\"%s\",drag_type:%d,onclick:%d,object_cnt:%d,stroke_color:\"%s\",stroke_opacity:%.2f,fill_color:\"%s\",fill_opacity:%.2f,use_center:%d,use_snap:%d,angle:%f,fontfamily:\"%s\",transform:%s,use_affine:%d,offset:[0,0],use_slider:%d,rotation_center:%s,once:true};draw_xml(draw_xml%d);slidergroup[%d] = null;\n",drawxml_cnt,drawxml_cnt,int_data[0],int_data[1],temp,drag_type,onclick,object_cnt,stroke_color,stroke_opacity,fill_color,fill_opacity,int_data[2],use_snap,angle,font_family,doubledata2js_array(affine_matrix,6,decimals),use_affine,use_slider,rotation_center,drawxml_cnt,object_cnt));
18552 bpr 2842
                add_to_buffer(tmp_buffer);
2843
                if(onclick != 0 ){object_cnt++;}
2844
                drawxml_cnt++;/* keeps track on imported img,div,p,span,mathml,svg */
2845
          /*
2846
            in case inputs are present, trigger adding the read_mathml()
2847
            if no other reply_format is defined
2848
            note: all other reply types will include a reading of elements with id='mathml'+p)
2849
          */
2850
                if(strstr(temp,"mathml0") != NULL){ if(reply_format == 0 ){reply_format = 16;}} /* no other reply type is defined */
2851
                break;
2852
              default:break;
2853
            }
2854
          }
2855
          reset();
2856
          break;
2857
        case MOUSE:
2858
  /*
18556 bpr 2859
  @ mouse color,fontsize
2860
  @ will display the cursor (x:y) coordinates in ''color`` and ''fontsize`` using default fontfamily Arial
2861
  @ note: use command ''mouse`` at the end of your script code (the same is true for command ''zoom``)
2862
  @%mouse%size 400,400%xrange -10,10%yrange -10,10%mouse red,22
18552 bpr 2863
  */
2864
          stroke_color = get_color(infile,0);
2865
          font_size = (int) (get_real(infile,1));
2866
          tmp_buffer = my_newmem(26);
2867
          snprintf(tmp_buffer,26,"use_mouse_coordinates();\n");add_to_buffer(tmp_buffer);
2868
          add_js_mouse(MOUSE_CANVAS,precision,stroke_color,font_size,stroke_opacity,2);
2869
          js_function[INTERACTIVE] = 1;
2870
          break;
2871
        case MOUSE_DEGREE:
2872
  /*
18556 bpr 2873
  @ mouse_degree color,fontsize
2874
  @ will display the angle in degrees between x-axis, (0:0) and the cursor (x:y) in 'color' and 'font size'<br> using a fontfamily Arial
2875
  @ The angle is positive in QI and QIII and the angle value is negative in QII and QIV
2876
  @ note: use command 'mouse' at the end of your script code (the same is true for command 'zoom')
2877
  @%mouse_degree%size 400,400%xrange -10,10%yrange -10,10%userdraw arc,blue%precision 100000%mouse_degree red,22
18552 bpr 2878
  */
2879
          stroke_color = get_color(infile,0);
2880
          font_size = (int) (get_real(infile,1));
2881
          tmp_buffer = my_newmem(26);
2882
          snprintf(tmp_buffer,26,"use_mouse_coordinates();\n");add_to_buffer(tmp_buffer);
2883
          add_js_mouse(MOUSE_CANVAS,precision,stroke_color,font_size,stroke_opacity,3);
2884
          js_function[JS_FIND_ANGLE] = 1;
2885
          js_function[INTERACTIVE] = 1;
2886
          break;
2887
        case MOUSE_DISPLAY:
2888
  /*
18556 bpr 2889
  @ display TYPE,color,fontsize
2890
  @ TYPE may be x | y | xy | degree | radian | radius
2891
  @ will display the mouse cursor coordinates as x-only,y-only,(x:y), the radius of a circle (this only in case 'userdraw circle(s),color') or the angle in degrees or radians for commands <code>userdraw arc,color</code> or protractor, ruler (if set dynamic).
2892
  @ use commands ''xunit`` and / or ''yunit`` to add the units to the mouse values. The ''degree | radian`` will always have the appropriate symbol).
2893
  @ just like commands ''mouse``, ''mousex``, ''mousey``, ''mouse_degree``... only other name
2894
  @%display_x%size 400,400%xrange -10,10%yrange -10,10%xunit \\u212B%display x,red,22
2895
  @%display_y%size 400,400%xrange -10,10%yrange -10,10%yunit seconds%display y,red,22
2896
  @%display_xy%size 400,400%xrange -10,10%yrange -10,10%xunit centimetre%yunit seconds%display xy,red,22%userdraw segments,blue
2897
  @%display_deg%size 400,400%xrange -10,10%yrange -10,10%display degree,red,22%fillcolor orange%opacity 200,50%userdraw arc,blue
2898
  @%display_rad%size 400,400%xrange -10,10%yrange -10,10%display radian,red,22%fillcolor orange%opacity 200,50%userdraw arc,blue
2899
  @%display_radius%size 400,400%xrange -10,10%yrange -10,10%xunit cm%xunit \\u212b%display radius,red,22%userdraw circle,blue
18552 bpr 2900
  */
2901
          temp = get_string_argument(infile,0);
2902
          if( strstr(temp,"xy") != NULL ){
2903
            int_data[0] = 2;
2904
          } else {
2905
            if( strstr(temp,"y") != NULL ){
2906
              int_data[0] = 1;
2907
            }else{
2908
              if( strstr(temp,"x") != NULL ){
2909
                int_data[0] = 0;
2910
              }else{
2911
                if(strstr(temp,"degree") != NULL){
2912
                int_data[0] = 3;
2913
                js_function[JS_FIND_ANGLE] = 1;
2914
                }else{
2915
                  if(strstr(temp,"radian") != NULL){
2916
                    int_data[0] = 4;
2917
                    js_function[JS_FIND_ANGLE] = 1;
2918
                  }else{
2919
                    if(strstr(temp,"radius") != NULL){
2920
                      int_data[0] = 5;
2921
                    }else{
2922
                      int_data[0] = 2;
2923
                    }
2924
                  }
2925
                }
2926
              }
2927
            }
2928
          }
2929
          stroke_color = get_color(infile,0);
2930
          font_size = (int) (get_real(infile,1));
2931
          tmp_buffer = my_newmem(26);
2932
          snprintf(tmp_buffer,26,"use_mouse_coordinates();\n");add_to_buffer(tmp_buffer);
2933
          add_js_mouse(MOUSE_CANVAS,precision,stroke_color,font_size,stroke_opacity,int_data[0]);
2934
          js_function[INTERACTIVE] = 1;
2935
          break;
2936
        case MOUSE_PRECISION:
2937
  /*
18556 bpr 2938
  @ precision int
2939
  @ 1 = no decimals ; 10 = 1 decimal ; 100 = 2 decimals etc
2940
  @ may be used / changed before every object
2941
  @ In case of user interaction (like ''userdraw`` or ''multidraw``), this value will be used to determine the amount of decimals in the reply / answer
2942
  @%precision%size 400,400%xrange -10,10%yrange -10,10%precision 1%userdraw segment,red
18552 bpr 2943
  */
2944
          precision = (int) (get_real(infile,1));
2945
          if(precision < 1 ){precision = 1;};
2946
          break;
2947
        case MOUSEX:
2948
  /*
18556 bpr 2949
  @ mousex color,fontsize
2950
  @ will display the cursor x-coordinate in ''color`` and ''font size`` using the fontfamily Arial.
2951
  @ note: use command ''mouse`` at the end of your script code (the same is true for command ''zoom``).
18552 bpr 2952
  */
2953
          stroke_color = get_color(infile,0);
2954
          font_size = (int) (get_real(infile,1));
2955
          tmp_buffer = my_newmem(26);
2956
          snprintf(tmp_buffer,26,"use_mouse_coordinates();\n");add_to_buffer(tmp_buffer);
2957
          add_js_mouse(MOUSE_CANVAS,precision,stroke_color,font_size,stroke_opacity,0);
2958
          js_function[INTERACTIVE] = 1;
2959
          break;
2960
        case MOUSEY:
2961
  /*
18556 bpr 2962
  @ mousey color,fontsize
2963
  @ will display the cursor y-coordinate in ''color`` and ''font size`` using default fontfamily Arial.
2964
  @ note: use command ''mouse`` at the end of your script code (the same is true for command ''zoom``).
8386 schaersvoo 2965
 
18552 bpr 2966
  */
2967
          stroke_color = get_color(infile,0);
2968
          font_size = (int) (get_real(infile,1));
2969
          tmp_buffer = my_newmem(26);
2970
          snprintf(tmp_buffer,26,"use_mouse_coordinates();\n");add_to_buffer(tmp_buffer);
2971
          add_js_mouse(MOUSE_CANVAS,precision,stroke_color,font_size,stroke_opacity,1);
2972
          js_function[INTERACTIVE] = 1;
2973
          break;
2974
        case MULTIDASH:
2975
  /*
18556 bpr 2976
  @ multidash 0,1,1
2977
  @ meaning draw objects no. 2 (circle) and 3 (segments), in the list of command like <code>multifill points,circle,segments</code>, are dashed
2978
  @ use before command <a href='#multidraw'>multidraw</a>
2979
  @ if not set all objects will be set ''not dashed``... unless a generic keyword ''dashed`` was given before command ''multidraw``
2980
  @ the dash-type is not -yet- adjustable <br>(e.g. command <code>dashtype line_px,space_px</code> will give no control over multidraw objects)
2981
  @ wims will <b>not</b> check if the number of 0 or 1's matches the amount of draw primitives...
2982
  @ always use the same sequence as is used for ''multidraw``
18552 bpr 2983
  */
2984
          if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");}
2985
          temp = get_string(infile,1);
2986
          temp = str_replace(temp,",","\",\"");
2987
          fprintf(js_include_file,"var multidash = [\"%s\"];",temp);
2988
          reset();/* if command 'dashed' was given...reset to not-dashed */
2989
          break;
2990
        case MULTIDRAW:
2991
  /*
18556 bpr 2992
  @ multidraw obj_type_1,obj_type_2...obj_type_11
2993
  @ for simple single object user drawings you could also use command <a href="#userdraw">userdraw</a>
18572 bpr 2994
  @ implemented obj_types:<ul><li>point | points</li><li>circle | circles</li><li>line | lines</li><li>segment | segments</li><li>arrow | arrows (use command 'arrowhead int' for size (default value 8 pixels))</li><li>curvedarrow | curvedarrows</li><li>rect | rects</li><li>closedpoly<br><b>only one</b> closedpolygon may be drawn.The number of ''corner points`` is not preset (e.g. not limited, freestyle), the polygon is closed when clicking on the first point again..(+/- 10px)</li><li>triangle | triangles</li><li>parallelogram | parallelograms</li><li>poly[3-9] | polys[3-9] draw 3...9 point polygone(s): polys3 is of course triangles</li><li>images</li><li>crosshair | crosshairs</li><li>function <br>for more function user input fields, use it multiple times<br>for 4 inputfields use : multidraw function,function,function,function</li></ul>
18556 bpr 2995
  @ additionally objects may be user labelled, using obj_type ''text``...<br>in this case allways a text input field and if <a href='#multiuserinput'> multiuserinput=1 </a> also (x:y) inputfields will be added to the page.<br>use commands ''fontfamily`` and ''fontcolor`` to adjust (command ''multistrokeopacity`` may be set to adjust text opacity)<br>note: text is always centered on the mouse-click or user-input coordinates !<br>note: no keyboard listeners are used
2996
  @ it makes no sense using something like ''multidraw point,points`` ... <br>something like "multidraw polys4,polys7" will only result in drawing a ''4 point polygone`` and not a ''7 point polygone``: this is a design flaw and not a feature...
2997
  @ note: mouselisteners are only active if "&#36;status != done " (eg only drawing in an active/non-finished exercise) <br> to overrule use command/keyword "status" (no arguments required)
2998
  @ buttons for changing the obj_type (and in case of ''multiuserinput``, some inputfields and buttons) <br>will be present in the reserved div ''tooltip_div`` and can be styled using command 'css some_css'
2999
  @ the button label will be default the ''object primitive name`` (like ''point``, ''circles``).<br>If you want a different label (e.g. an other language), use command ''multilabel``<br>for example in dutch: <br><code>multilabel cirkel,lijnstuk,punten,STOP<br>multidraw circle,segment,points</code><br>(see command <a href='#multilabel'>multilabel</a> for more details)
3000
  @ a right mouse button click will remove the last drawn object of the selected drawing type. All other type of objects are not removed
3001
  @ multidraw is incompatible with command ''tooltip`` (the reserved div_area is used for the multidraw control buttons)
3002
  @ all ''multidraw`` drawings will scale on zooming.<br>this in contrast to the command <a href="#userdraw">userdraw</a>.
3003
  @ wims will <b>not</b> check the amount or validity of your command arguments ! <br>( use javascript console to debug any typo's )
18572 bpr 3004
  @ a local function <code>read_canvas%d</code> will read all userbased drawings.<br>The output is always a 16 lines string with fixed sequence.<br>line 1 = points_x+";"+points_y+"\\n"<br>line 2 = circles_x+";"+circles_y+";"+multi_radius+"\\n"<br>line 3 = segments_x+";"+segments_y+"\\n"<br>line 4 = arrows_x+";"+arrows_y+"\\n"<br>line 5 = lines_x+";"+lines_y+"\\n"<br>line 6 = triangles_x+";"+triangles_y+"\\n"<br>line 7 = polys[3-9]_x+";"+polys[3-9]_y+"\\n"<br>line 8 = rects_x +";"+rects_y+"\\n"<br>line 9 = closedpoly_x+";"+closedpoly_y+"\\n"<br>line 10 = parallelogram_x+";"+parallelogram_y"\\n"<br>line 11 = text_x+";"+text_y+";"+text"\\n"<br>line 12 = image_x+";"+image_y+";"+image_id<br>line 13 = curvedarrows_x +";"+ curvedarrows_y +"\\n"<br>line 14 = curvedarrows2_x +";"+ curvedarrows2_y +"\\n"<br>line 15 = crosshairs_x +";"+ crosshairs_y +"\\n"<br>line 16 = userdraw_x +";"+userdraw_y + "\\n" note: this is for single ''userdraw object,color`` and ''replyformat 29``<br>line 17 = userdraw_x +";"+userdraw_y +";"+userdraw_radius + "\\n" note: this is for single ''userdraw object,color`` and ''replyformat 29``<br>The x/y-data are in x/y-coordinate system and display precision may be set by a previous command ''precision 0 | 10 | 100 | 1000...``<br>In case of circles the radius is -for the time being- rounded to pixels<br><b>use the wims "direct exec" tool to see the format of the reply</b>
18556 bpr 3005
  @ It is best to prepare / format the student reply in clientside javascript.<br>However in ''wims`` language you could use something like this<br>for example you are interested in the polys5 drawings of a pupil (the pupil may draw multiple poly5 objects...)<br>note: the reply for 2 poly5's is: x11,x12,x13,x14,x15,x21,x22,x23,x24,x25 ; y11,y12,y13,y14,y15,y21,y22,y23,y24,y25<br>rep = !line 7 of reply <br>rep = !translate ';' to '\\n' in &#36;rep <br>pts = 5 # 5 points for polygon <br>x_rep = !line 1 of &#36;rep <br>y_rep = !line 2 of &#36;rep <br>tot = !itemcnt &#36;x_rep <br>num_poly = &#36;[&#36;tot/&#36;pts] <br>idx = 0 <br>!for p=1 to &#36;num_poly <br>&nbsp;!for s=1 to &#36;pts <br>&nbsp;&nbsp;!increase idx <br>&nbsp;&nbsp;X = !item &#36;idx of &#36;x_rep <br>&nbsp;&nbsp;Y = !item &#36;idx of &#36;y_rep <br>&nbsp;&nbsp;# do some checking <br>&nbsp;!next s <br>!next p <br>
3006
  @ <b>attention</b>: for command argument ''closedpoly``, only one polygone can be drawn. The last point (e.g. the point clicked near the first point) of the array is removed.
3007
  @ technical: all 10 ''draw primitives`` + ''text`` will have their own -transparent- PNG bitmap canvas. <br>So for example there can be a points_canvas entirely separated from a line_canvas.<br>This to avoid the need for a complete redraw when something is drawn to the canvas...(eg only the object_type_canvas is redrawn), this in contrast too many very slow do-it-all HTML5 canvas javascript libraries.<br>The mouselisteners are attached to the canvas-div element.
3008
  @ a special object type is ''images``.<br>if used together with <a href='#imagepalette'>imagepalette</a> a image table will be integrated in the 'control section' of multidraw (set <code>multiuserinput 1</code> for ''images``) if not used with <a href='#imagepalette'>imagepalette</a>, provide the images or div's (&lt;img&gt; tag with bitmap or SVG or anything in a div element) somewhere on the html exercise page, with an onclick handler like:<br><code>&lt;img src='gifs/images/dog.svg' onclick='javascript:place_image_on_canvas(this.id);' id="ext_image_1" /&gt;<br>&lt;img src='gifs/fish.png' onclick='javascript:place_image_on_canvas(this.id);' id="another" /&gt;</code><br>etc ... when activating the multidraw ''image`` button, the images can be selected<br> (left mouse button/onclick) and placed on the canvas...left mouse click.<br>using div's will enable you -amongst other content- to add math typesetting from the exercise page onto the canvas.
18572 bpr 3009
  @ When you are not content with the default ''multidraw control panel``, you can create your own interface, using a few javascript functions to call the drawprimitives, delete things and ''stop drawing`` in case you also want to drag&drop stuff...</br>To activate this feature, use <a href='#multilabel'>multilabel NOCONTROLS</a><br>The object types are internally represented by the following numbers (making typos will render your exercise null and void)<br>point = 0<br>points =1<br>circle = 2<br>circles = 3<br>line = 4<br>lines = 5<br>segment = 6<br>segments = 7<br>arrow = 8<br>arrows = 9<br>triangle = 10<br>triangles = 11<br>closedspoly = 12<br>text = 13<br>rect = 14<br>rects = 15<br>poly[3-9] = 16<br>polys[3-9] = 17<br>parallelogram = 18<br>parallelograms = 19<br>images  = 20<br>curvedarrow = 21<br>curvedarrows = 22<br>curvedarrow2 = 23<br>curvedarrows2 = 24<br>crosshair = 25<br>crosshairs = 26 <br>controls for example:<br><code>&lt;input type='button' onclick='javascript:userdraw_primitive=null' value='STOP DRAWING' /&gt;<br>&lt;input type='button' onclick='javascript:userdraw_primitive=24;multidraw_object_cnt = 0;' value='start drawing curvedarrows2' /&gt; <br>&lt;input type='button' onclick='javascript:var fun=eval("clear_draw_area"+canvas_scripts[0]);fun(24,0);' value='REMOVE LAST CURVEDARROW ' /&gt; </code><br> If using multiple canvas scripts in a single page, loop through the canvas_scripts[n] <br>note: if using NOCONTROLS and just a single draw primitive (for example, just: 'multidraw circles'), the object may be drawn directly. (analogue to 'userdraw circles,color')<br>And since a right mouse button click will always remove the last drawn object of the current object type, there is no need for a special "remove button"
18556 bpr 3010
  @%multidraw_function%size 400,400%xrange -10,10%yrange -10,10%fontfamily Italic 22px Helvetica%axis%axisnumbering%precision 0%grid 2,2,grey,1,1,5,black%multicolors red,green,blue%fontcolor orange%multilinewidth 1,2,3%multidraw text,function,function,function,line
3011
  @%multidraw%size 400,400%xrange -10,10%yrange -10,10%multidash 1,0%multilinewidth 1,2%multistrokecolors red,blue%multisnaptogrid 1,1%multilabel LINES,CIRCLES,STOP DRAWING%multidraw lines,circles
3012
  @%multidraw_images%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%drag xy%# use special function to read the drag coordinates%copy 0,0,-1,-1,-1,-1,gifs/images/skull_and_crossbones50.png%fontcolor green%fontfamily Bold 42pt Arial%imagepalette gifs/ca.gif,gifs/en.gif,gifs/nl.gif,gifs/fr.gif,gifs/cn.gif,gifs/de.gif,gifs/kh.gif,gifs/it.gif%multiuserinput 0,0,1%css color:blue;%multisnaptogrid 1,1,1%multilinewidth 0,4,0%# attention: use unicode text input without the slash %# \u222D ---> u222D at least will sometimes work%# otherwise cut&past unicode symbols into inputfield...%multilabel TEXT,REACTION ARROW,FLAGS,STOP DRAWING%multidraw text,arrow,images
3013
  @%multidraw_demo%size 800,800%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%css color:blue;%fontfamily Italic 42pt Arial%precision 1%opacity 200,50%snaptogrid%linewidth 3%filled%multistrokecolors red,green,blue,orange,yellow,purple,black,cyan,red,green,blue,orange,green,purple,black,cyan%multifillcolors red,green,blue,orange,yellow,purple,black,cyan,red,green,blue,orange,brown,purple%imagepalette gifs/ca.gif,gifs/en.gif,gifs/nl.gif,gifs/fr.gif,gifs/cn.gif,gifs/de.gif,gifs/kh.gif,gifs/it.gif%multidraw closedpoly,segments,rect,parallelogram,triangles,poly5,points,lines,arrows,circles,text,curvedarrows,curvedarrows2,images
3014
  @%multidraw_NOCONTROLS%size 400,400%xrange -10,10%yrange -10,10%grid 2,2,grey%linewidth 3%strokecolor green%fillcolor blue%filled%opacity 255,60%multilabel NOCONTROLS%multidraw circles%# RIGHT MOUSE CLICK REMOVES LAST OBJECT
18552 bpr 3015
  */
3016
          js_function[INTERACTIVE] = 1;
3017
          if(js_function[JS_ZOOM] == 1){use_zoom = 1;} /* use noisy zoom_code, when command zoom is given before command 'multidraw' */
3018
          if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");}
3019
          if( use_userdraw == 1 ){canvas_error("Only one userdraw primitive may be used in command 'userdraw' use command 'multidraw' for this...");}
3020
          use_userdraw = 2;
3021
          temp = get_string(infile,1);
3022
          fprintf(js_include_file,"\
3023
            var MMP = %d;\
3024
            if( typeof(multisnaptogrid) == 'undefined' && multisnaptogrid == null){var multisnaptogrid = new Array(MMP);for(var i=0;i<MMP;i++){multisnaptogrid[i] = %d;};};\
3025
            if( typeof(multistrokecolors) === 'undefined' && multistrokecolors == null){ var multistrokecolors = new Array(MMP);for(var i=0;i<MMP;i++){multistrokecolors[i] = '%s';};};\
3026
            if( typeof(multifillcolors) === 'undefined' && multifillcolors == null ){var multifillcolors = new Array(MMP);for(var i=0;i<MMP;i++){multifillcolors[i] = '%s';};};\
3027
            if( typeof(multistrokeopacity) === 'undefined' && multistrokeopacity == null){var multistrokeopacity = new Array(MMP);for(var i=0;i<MMP;i++){multistrokeopacity[i] = %.2f;};};\
3028
            if( typeof(multifillopacity) === 'undefined' &&  multifillopacity == null){var multifillopacity = new Array(MMP);for(var i=0;i<MMP;i++){multifillopacity[i] = %.2f;};};\
3029
            if( typeof(multilinewidth) === 'undefined' && multilinewidth == null){var multilinewidth = new Array(MMP);for(var i=0;i<MMP;i++){multilinewidth[i] = %d;};};\
3030
            if( typeof(multifill) === 'undefined' && multifill == null){var multifill = new Array(MMP);for(var i=0;i<MMP;i++){multifill[i] = %d;};};\
3031
            if( typeof(multidash) === 'undefined' && multidash == null){var multidash = new Array(MMP);for(var i=0;i<MMP;i++){multidash[i] = %d;};};\
3032
            if( typeof(multilabel) === 'undefined' && multilabel == null){var multilabel = [\"%s\",\"stop drawing\"];};\
3033
            if( typeof(multiuserinput) === 'undefined' && multiuserinput == null){var multiuserinput = new Array(MMP);for(var i=0;i<MMP;i++){multiuserinput[i] = '0';};};\
3034
            var arrow_head = %d;var multifont_color = '%s';var multifont_family = '%s';var forbidden_zone = [xsize+2,ysize+2];",
3035
            MAX_MULTI_PRIMITIVES,
3036
            use_snap,
3037
            stroke_color,
3038
            fill_color,
3039
            stroke_opacity,
3040
            fill_opacity,
3041
            line_width,
3042
            use_filled,
3043
            use_dashed,
3044
            str_replace(temp,",","\",\""),
3045
            arrow_head,font_color,font_family);
3046
          add_js_multidraw(temp,css_class,use_offset,int_data[MAX_MULTI_PRIMITIVES+1],crosshair_size,use_zoom);
3047
            /* no_controls == int_data[MAX_MULTI_PRIMITIVES+1] */
3048
          reply_precision = precision;
3049
          if(strstr(temp,"text") != NULL){
3050
            js_function[JS_SAFE_EVAL] = 1;
3051
            js_function[DRAW_SUBSUP] = 1;
3052
          }
3053
          if(strstr(temp,"function") != NULL){
3054
            int pp, funs = count_substring(temp, "function");
3055
            js_function[JS_SAFE_EVAL] = 1;
3056
            js_function[JS_RAWMATH] = 1;
3057
            js_function[DRAW_JSFUNCTION] = 1;
3058
            js_function[JS_MATH] = 1;
3059
            js_function[JS_PLOT] = 1;
3060
            for(pp = 0 ; pp< funs ;pp++){
3061
              add_input_jsfunction(css_class,function_label,input_cnt,stroke_color,stroke_opacity,line_width,use_dashed,dashtype[0],dashtype[1],font_size);
3062
              input_cnt++;
3063
              jsplot_cnt++;
3064
            }
3065
            fprintf(js_include_file,"if(typeof(all_jsplots) !== 'number'){var all_jsplots;};all_jsplots = %d;function redraw_userdraw(){redraw_jsplot();return;};",jsplot_cnt);
3066
          }
3067
      /* the canvasses range from 1000 ... 1008 */
3068
          if( reply_format == 0){reply_format = 29;}
3069
          reset();/* if command 'filled' / 'dashed' was given...reset all */
3070
          break;
3071
        case MULTILABEL:
3072
  /*
18556 bpr 3073
  @ multilabel button_label_1,button_label_2,...,button_label_8,'stop drawing text'
3074
  @ use before command <a href='#multidraw'>multidraw</a>
3075
  @ if not set all labels (e.g. the value of input type 'button') will be set by the english names for the draw_primitives (like 'point','circle'...)
3076
  @ the ''stop drawing`` button text <b>must</b> be the last item on the ''multilabel`` -list <br>for example:<br><code>multilabel punten,lijnen,Stop met Tekenen<br>multidraw points,lines</code>
3077
  @ all buttons can be ''styled`` by using command <code>css</code><br><b>note:</b>If you want to add some CSS style to the buttons...<br>the id's of the ''draw buttons`` are their english command argument<br>(e.g. id="canvasdraw_points" for the draw points button).<br>the id of the ''stop drawing`` button is "canvasdraw_stop_drawing".<br>the id of the "OK" button is ''canvasdraw_ok_button``
3078
  @ wims will not check the amount or validity of your input
3079
  @ always use the same sequence as is used for ''multidraw``
3080
  @ if you don't want the controls, and want to write your own interface, set <code>multilabel NOCONTROLS</code>
18552 bpr 3081
  */
3082
          if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");}
3083
          temp = get_string(infile,1);
3084
          if( strcasestr(temp,"NOCONTROLS") ){
3085
            int_data[MAX_MULTI_PRIMITIVES+1] = 1; /*int_data[25] = 1 --> 'no_controls = 1' in canvasmacro.c */
3086
            fprintf(js_include_file,"var multilabel = null;");
3087
          }
3088
          else {
3089
            int_data[MAX_MULTI_PRIMITIVES+1] = 0; /* so DO use control buttons etc */
3090
            temp = str_replace(temp,",","\",\"");
3091
            fprintf(js_include_file,"var multilabel = [\"%s\"];",temp);
3092
          }
3093
          break;
3094
        case MULTILINEWIDTH:
3095
  /*
18556 bpr 3096
  @ multilinewidth linewidth_1,linewidth_2,...,linewidth_8
3097
  @ use before command <a href='#multidraw'>multidraw</a>
3098
  @ if not set all line widths will be set by a previous command ''linewidth int``
3099
  @ use these up to 7 different line widths for the draw primitives used by command <code>multidraw obj_type_1,obj_type_2...obj_type_7</code>
3100
  @ wims will <b>not</b> check if the number of 0 or 1's matches the amount of draw primitives...
3101
  @ always use the same sequence as is used for ''multidraw``
18552 bpr 3102
  */
3103
          if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");}
3104
          temp = get_string(infile,1);
3105
          temp = str_replace(temp,",","\",\"");
3106
          fprintf(js_include_file,"var multilinewidth = [\"%s\"];",temp);
3107
          break;
3108
        case MULTIFILL:
3109
  /*
18556 bpr 3110
  @ multifill 0,0,1,0,1,0,0
3111
  @ meaning draw objects no. 3 and 5, in the list of command ''multifill``, are filled (if the object is fillable...and not a line,segment,arrow or point...)
3112
  @ using a fillpattern: multifill 0,1,2,5,3,4<br>meaning: first object is not filled...second object is solid color filled...2=grid | 3=hatch | 4=diamond | 5=dot
3113
  @ use before command <a href='#multidraw'>multidraw</a>
3114
  @ if not set all objects -except point|points- will be set ''not filled``... unless a command <code>filled</code> was given before command <code>multifill</code>
3115
  @ only suitable for draw_primitives like ''circle | circles``, ''triangle | triangles``, ''rect | rects``, ''poly[3-9] | polys[3-9]`` and ''polygon``
3116
  @ wims will <b>not</b> check if the number of 0 or 1's matches the amount of draw primitives...
3117
  @ always use the same sequence as is used for ''multidraw``
18552 bpr 3118
  */
3119
          if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");}
3120
          i=0;
3121
          while( ! done ){     /* get next item until EOL*/
3122
            if(i > MAX_MULTI_PRIMITIVES){canvas_error("too many multidraw primitives...read the documentation...");}
3123
            int_data[i] = (int)(get_real(infile,1)); /* 0,1,2,3,4,5 */
3124
            if(int_data[i] < 0 || int_data[i] > 5 ){canvas_error("the only possible multifill arguments are: 0,1,2,3,4,5 ");}
3125
            if(int_data[i] > 1 ){use_filled = 2;js_function[DRAW_FILL_PATTERN] = 1;}/* switch to trigger pattern filling */
3126
            i++;
3127
          }
3128
          fprintf(js_include_file,"var multifill = %s ;",data2js_array(int_data,i-1));
3129
          break;
3130
        case MULTIFILLCOLORS:
3131
  /*
18556 bpr 3132
  @ multifillcolors color_name_1,color_name_2,...,color_name_8
3133
  @ use before command <a href='#multidraw'>multidraw</a>
3134
  @ if not set all fillcolors (for circle | triangle | poly[3-9] | closedpoly ) will be ''stroke_color``, ''fill_opacity``
3135
  @ use these up to 6 colors for the draw primitives used by command <code>multidraw obj_type_1,obj_type_2...obj_type_n</code>
18627 bpr 3136
  @ wims will <b>not</b> check if the number of colors matches the amount of draw primitives...
18556 bpr 3137
  @ always use the same sequence as is used for ''multidraw``
18627 bpr 3138
  @ can also be used with command <a href='#userdraw'>userdraw clickfill,color</a> when more than one fillcolor is wanted.<br>in that case use for example <a href='#replyformat'>replyformat 10</a> ... reply=x1:y1:color1,x2:y2:color2...<br>the colors will restart at the first color, when there are more fill-clicks than multi-fill-colors<br>if more control over the used colors is wanted, see command <a href='#colorpalette'>colorpalette color1,color2...</a>
18552 bpr 3139
  */
3140
          if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");}
3141
          fprintf(js_include_file,"var multifillcolors = [");
3142
          while( ! done ){
3143
            temp = get_color(infile,1);
3144
            fprintf(js_include_file,"\"%s\",",temp);
3145
          }
3146
          fprintf(js_include_file,"\"0,0,0\"];");/* add black to avoid trouble with dangling comma... */
3147
          break;
3148
        case MULTIFILLOPACITY:
3149
  /*
18556 bpr 3150
  @ multifillopacity fill_opacity_1,fill_opacity_2,...,fill_opacity_8
3151
  @ float values 0 - 1 or integer values 0 - 255
3152
  @ use before command <a href='#multidraw'>multidraw</a>
3153
  @ if not set all fill opacity_ will be set by previous command <code>opacity int,int</code> and keyword ''filled``
3154
  @ use these up to 7 different stroke opacities for the draw primitives used by command <code>multidraw obj_type_1,obj_type_2...obj_type_y</code>
3155
  @ wims will not check the amount or validity of your input
3156
  @ always use the same sequence as is used for ''multidraw``
18552 bpr 3157
  */
3158
          if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");}
3159
          temp = get_string(infile,1);
3160
          temp = str_replace(temp,",","\",\"");
3161
          fprintf(js_include_file,"var multifillopacity = [\"%s\"];",temp);
3162
          break;
3163
        case MULTISNAPTOGRID:
3164
  /*
18556 bpr 3165
  @ multisnaptogrid 0,1,1
3166
  @ alternative: multisnap
3167
  @ meaning draw objects no. 2 (circle) and 3 (segments), in the list of command like <code>multifill points,circle,segments</code>, will snap to the xy-grid (default 1 in x/y-coordinate system: see command <a href='#snaptogrid'>snaptogrid</a>)
3168
  @ freehand drawing...specify precision for reply: all objects snap to grid <code>multisnaptogrid 1,1,1,...</code>
3169
  @ only the xy-values snap_to_grid: all objects snap to grid <code>multisnaptogrid 1,1,1,...</code>
3170
  @ only the x-values snap_to_grid: all objects snap to x-grid <code>multisnaptogrid 2,2,2,...</code>
3171
  @ only the y-values snap_to_grid: all objects snap to y-grid <code>multisnaptogrid 3,3,3,...</code>
3172
  @ if <a href='#snaptopoints'>snaptopoints</a> is defined: all objects snap to points <code>multisnaptogrid 4,4,4,...</code> <br><b>make sure to define the points to snap on...</b> use command <a href='#snaptopoints'>snaptopoints</a>
3173
  @ <code>multisnaptogrid 0,1,2,3,4<br>multidraw text,arrow,line,circle,image</code><br>''text`` is free hand, ''arrow`` is snap to grid, ''line`` is snap to x-grid, ''circle`` is snap to y-grid, ''image`` is snap to points defined by command <a href='#snaptopoints'>snaptopoints</a>
3174
  @ use before command <a href='#multidraw'>multidraw</a>
3175
  @ attention: if not set all objects will be set ''no snap``... unless a generic command ''snaptogrid`` was given before command ''multidraw``
3176
  @ commands <a href='#xsnaptogrid'>xsnaptogrid</a>, <a href='#ysnaptogrid'>ysnaptogrid</a>, <a href='#snaptofunction'>snaptofunction</a> are <b>not</b> supported amd only functional for command <a href='#userdraw'>userdraw</a>
3177
  @ always use the same sequence as is used for ''multidraw``
3178
  @ wims will <b>not</b> check if the number of 0 or 1's matches the amount of draw primitives...
18552 bpr 3179
  */
3180
          if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");}
3181
          temp = get_string(infile,1);
3182
          fprintf(js_include_file,"var multisnaptogrid = [%s];",temp);
3183
          reset();/* if command 'dashed' was given...reset to not-dashed */
3184
          break;
3185
        case MULTISTROKECOLORS:
3186
  /*
18556 bpr 3187
  @ multistrokecolors color_name_1,color_name_2,...,color_name_8
3188
  @ use before command <a href='#multidraw'>multidraw</a>
3189
  @ if not set all colors will be ''stroke_color``, ''stroke_opacity``
3190
  @ use these up to 6 colors for the draw primitives used by command <code>multidraw obj_type_1,obj_type_2...obj_type_7</code>
18627 bpr 3191
  @ wims will <b>not</b> check if the number of colors matches the amount of draw primitives...
18556 bpr 3192
  @ always use the same sequence as is used for ''multidraw``
18552 bpr 3193
  */
3194
          if( use_tooltip == 1 ){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");}
3195
          fprintf(js_include_file,"var multistrokecolors = [");
3196
          while( ! done ){
3197
            temp = get_color(infile,1);
3198
            fprintf(js_include_file,"\"%s\",",temp);
3199
          }
3200
          fprintf(js_include_file,"\"0,0,0\"];");/* add black to avoid trouble with dangling comma... */
3201
          break;
3202
        case MULTISTROKEOPACITY:
3203
  /*
18556 bpr 3204
  @ multistrokeopacity stroke_opacity_1,stroke_opacity_2,...,stroke_opacity_7
3205
  @ float values 0 - 1 or integer values 0 - 255
3206
  @ use before command <a href='#multidraw'>multidraw</a>
3207
  @ if not set all stroke opacity_ will be set by previous command <code>opacity int,int</code>
3208
  @ use these up to 7 different stroke opacities for the draw primitives used by command <code>multidraw obj_type_1,obj_type_2...obj_type_7</code>
3209
  @ wims will not check the amount or validity of your input
3210
  @ always use the same sequence as is used for ''multidraw``
18552 bpr 3211
  */
3212
          if( use_tooltip == 1){canvas_error("command 'multidraw' is incompatible with command 'intooltip tip_text'");}
3213
          temp = get_string(infile,1);
3214
          temp = str_replace(temp,",","\",\"");
3215
          fprintf(js_include_file,"var multistrokeopacity = [\"%s\"];",temp);
3216
          break;
3217
        case MULTIUSERINPUT:
3218
  /*
3219
  @ multiuserinput 0,1,1,0
3220
  @ alternative: multiinput
18572 bpr 3221
  @ meaning, when the command ''multidraw`` is used <code>multidraw circles,points,lines,triangles</code><br>objects ''points`` and ''lines`` may additionally be ''drawn`` by direct input (inputfields)<br>all other objects must be drawn with a mouse
18552 bpr 3222
  @ in case of circle | circles a third inputfield for Radius (R) is added. The radius must be in the x/y coordinate system (x-range) and <b>not</b> in pixels...students don't think in pixels.<br>note: R-values will not snap-to-grid
3223
  @ in case of line(s) | segment(s) | arrow(s) the user should write <b>x1:y1</b> in the first inputfield and <b>x2:y2</b> in the second.<br>These ''hints`` are pre-filled into the input field.<br>Other coordinate delimiters are '';`` and '',`` e.g. <b>x1;y1</b> or <b>x1,y1</b>.<br>An error message (alert box) will popup when things are not correctly...
3224
  @ in case of a triangle | poly3, three inputfields are provided.
3225
  @ in case of ''text`` and ''multiuserinput=1, 3`` inputfields will be shown: ''x,y,text``
3226
  @ in case of ''text`` and ''multiuserinput=0, 1`` inputfield will be shown: text ... a mouse click will place the text on the canvas.
3227
  @ may be styled using command <a href="#css">css</a>
3228
  @ an additional button ''stop drawing`` may be used to combine userbased drawings with ''drag&and;drop`` or ''onclick`` elements
3229
  @ when exercise if finished (status=done) the buttons will not be shown.<br>To override this default behaviour use command / keyword ''status``
3230
  @ use before command <a href='#multidraw'>multidraw</a>
3231
  @ always use the same sequence as is used for ''multidraw``
3232
  */
3233
      /* simple rawmath and input check */
3234
          js_function[JS_SAFE_EVAL] = 1;
3235
          temp = get_string(infile,1);
3236
          temp = str_replace(temp,",","\",\"");
3237
          fprintf(js_include_file,"var multiuserinput = [\"%s\"];",temp);
3238
          break;
3239
        case NORESET:
3240
  /*
3241
  @ noreset
3242
  @ alternative: killreset
3243
  @ keyword
3244
  @ may come in handy if canvas script code is generated using loops
3245
  @ if used the following properties will remain to be valid<br><ul><li>filled</li><li>dash settings</li><li>onclick or drag settings</li><li>centering or offset</li></ul>
3246
  @ if used again, these properies will be reset to the default values and normal behaviour is continued (e.g. the above properties will be reset after 'use' on a canvas object)
3247
  @ etc etc
3248
  @ commands <a href='#slider'>slider</a>, <a href='#linear'>linear</a>, <a href='#rotate'>rotate</a>, <a href='#translate'>translate</a>, <a href='#affine'>affine</a> are always active until the 'kill' commands are given: <br><a href='#killlinear'>killlinear</a>, <a href='#killrotate'>killrotate</a>, <a href='#killtranslate'>killtranslate</a> and <a href='#killaffine'>killaffine</a>
3249
  @ commands like 'opacity', 'linewidth', 'fontsize', 'fontfamily' are only changed when redefined again
3250
  @%noreset%size 400,400%xrange -10,10%yrange -10,10%noreset%drag xy%linewidth 4%filled%rect -4,4,-2,2,blue%triangle -3,-3,0,0,1,-5,green%circle 0,0,50,orange%noreset%rect 2,4,4,2,blue
3251
  @%noreset_oefgraduation%size 800,100%xrange 0,11%yrange -1,1%hline 0,0,black%parallel 0,0,0,0.5,1,0,11,blue%noreset%onclick%centered%text black,1,0.6,large,20%text black,2,0.6,large,30%text black,3,0.6,large,40%text black,4,0.6,large,50%text black,5,0.6,large,60%text black,6,0.6,large,70%text black,7,0.6,large,80%text black,8,0.6,large,90%text black,9,0.6,large,100%text black,10,0.6,large,110
3252
  */
3253
          if(no_reset == FALSE){no_reset = TRUE;}else{no_reset = FALSE;reset();}
3254
          break;
3255
        case NOXAXIS:
3256
  /*
3257
  @ noxaxis
3258
  @ keyword
3259
  @ if set, the automatic x-axis numbering will be ignored
3260
  @ use command <a href="#axis">axis</a> to have a visual x/y-axis lines (see command <a href="#grid">grid</a>)
3261
  @ to be used before command grid (see <a href="#grid">command grid</a>)
3262
  */
3263
          fprintf(js_include_file,"x_strings = {};x_strings_up = [];\n");
3264
          use_axis_numbering = -1;
3265
          break;
3266
        case NOYAXIS:
3267
  /*
3268
  @ noyaxis
3269
  @ keyword
3270
  @ if set, the automatic y-axis numbering will be ignored
3271
  @ use command <a href="#axis">axis</a> to have a visual x/y-axis lines (see command <a href="#grid">grid</a>)
3272
  @ to be used before command grid (see <a href="#grid">command grid</a>)
3273
  */
3274
          fprintf(js_include_file,"y_strings = {};\n");
3275
          break;
3276
        case NUMBERLINE:
3277
  /*
3278
  @ numberline x0,x1,xmajor,xminor,y0,y1
3279
  @ numberline is using xrange/yrange system for all dimensions
3280
  @ multiple numberlines are allowed ; combinations with command <a href='#grid'>grid</a> is allowed; multiple commands <a href='#xaxis'>xaxis numbering</a> are allowed
3281
  @ x0 is start x-value in xrange
3282
  @ x1 is end x-value in xrange
3283
  @ xmajor is step for major division
3284
  @ xminor is divisor of xmajor; using small (30% of major tick) tick marks: this behaviour is ''hardcoded``
3285
  @ is xminor is an even divisor, an extra tickmark (60% of major tick) is added to the numberline: this behaviour is ''hardcoded``
3286
  @ y0 is bottom of numberline; y1 endpoint of major tics
3287
  @ use command <a href="#linewidth">linewidth</a> to control appearance
3288
  @ use <a href="#strokecolor">strokecolor</a> and <a href="#opacity">opacity</a> to controle measure line
3289
  @ for all ticks linewidth and color / opacity are identical.
3290
  @ if command <a href="#xaxis">xaxis</a> or <a href="#xaxisup">xaxisup</a> is not defined, the labeling will be on major ticks: x0...x1
3291
  @ use <a href="#fontfamily">fontfamily</a> and <a href="#fontcolor">fontcolor</a> to control fonts settings
3292
  @ may be used together with <a href="#userdraw">userdraw</a>, <a href="#multidraw">multidraw</a> and <a href="#drag">user drag</a> command family for the extra object drawn onto the numberline
3293
  @ <a href="#snaptogrid">snaptogrid, snaptopoints etc</a> and <a href="#zoom">zooming and panning</a> is supported
3294
  @ onclick and dragging of the numberline are not -yet- supported
3295
  @ note: in case of multiple numberlines, make sure the numberline without special x-axis numbering (e.g. ranging from xmin to xmax) comes first !
3296
  @%numberline%size 400,400%xrange -10,10%yrange -10,10%precision 1%strokecolor black%numberline -8,8,1,6,-4,-3.5%strokecolor red%xaxis -4:AA:-2:BB:2:CC:4:DD%numberline -8,8,1,2,4,4.5%strokecolor green%xaxisup -4:AAA:-2:BBB:2:CCC:4:DDD%numberline -8,8,1,3,2,2.5%strokecolor blue%xaxis -4:AAAA:-2:BBBB:2:CCCC:4:DDDD%numberline -8,8,1,4,0,0.5%strokecolor brown%xaxis -4:AAAAA:-2:BBBBB:2:CCCCC:4:DDDDD%numberline -8,8,1,5,-2,-1.5%zoom red
3297
  */
3298
          js_function[DRAW_NUMBERLINE] = 1;
3299
          for(i=0;i<6;i++){
3300
            switch(i){
3301
              case 0: double_data[0] = get_real(infile,0);break;/* xmin */
3302
              case 1: double_data[1] = get_real(infile,0);break;/* xmax */
3303
              case 2: double_data[2] = get_real(infile,0);break;/* xmajor */
3304
              case 3: double_data[3] = get_real(infile,0);break;/* xminor */
3305
              case 4: double_data[4] = get_real(infile,0);break;/* ymin */
3306
              case 5: double_data[5] = get_real(infile,1);/* ymax */
3307
            /*
3308
            var draw_numberline%d = function(canvas_type,xmin,xmax,xmajor,xminor,ymin,ymax,linewidth,strokecolor,strokeopacity,fontfamily,fontcolor);
3309
            */
3310
                fprintf(js_include_file,"snap_x = %f;snap_y = %f;",double_data[2] / double_data[3],double_data[5] - double_data[4] );
18557 bpr 3311
                tmp_buffer=my_newmem(MAX_BUFFER);
3312
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "\ndraw_numberline(%d,%d,%f,%f,%f,%f,%f,%f,%d,\"%s\",%f,\"%s\",\"%s\",%d);  ",NUMBERLINE_CANVAS+numberline_cnt,use_axis_numbering,double_data[0],double_data[1],double_data[2],double_data[3],double_data[4],double_data[5],line_width,stroke_color,stroke_opacity,font_family,font_color,precision));
18552 bpr 3313
                add_to_buffer(tmp_buffer);
3314
                numberline_cnt++;
3315
                break;
3316
              default:break;
3317
            }
3318
          }
3319
          reset();
3320
          break;
3321
        case OBABEL:
3322
  /*
3323
  @ obabel x,y,type input,molecule smiles-code or file location, extra arguments,extra arguments,...
3324
  @ will call the ''obabel`` program, if installed.
3325
  @ output will be an svg file
3326
  @ see documentation of obabel for special keys
3327
  @ command <a href='#affine'>affine</a> will produce CSS3 matrix transformations
3328
  @ command <a href='#rotate'>rotate</a> will rotate the object
3329
  @ can be set onclick: <code>javascript:read_dragdrop();</code> will return click numbers of mathml-objects<br>if 4 clickable object are drawn, the reply could be 1,0,1,0 ... meaning clicked on the first and third object
3330
  @ can be set draggable: <code>javascript:read_dragdrop();</code> will return all coordinates in the same order as the canvas script: unmoved object will have their original coordinates...
3331
  @ snaptogrid is supported...snaptopoints will work, but use with care...due to the primitive dragging<br>technically: the dragstuff library is not used...the mathml is embedded in a new div element and not in the html5-canvas
3332
  @ external files may be loaded if they are present on the server or in the modules <br>for example:<br> obabel 0,0,mol,&#36;module_dir/caffeine.mol,-P100,-xb none
3333
  @%obabel_smi%size 400,400%xrange -10,10%yrange -10,10%fillcolor green%drag xy%centered%obabel 0,0,smi,-:c1cFccc1cc,-xb none,-xB blue,-xi,-xt,-xa,-xX,-xP180,-h
3334
  */
3335
          js_function[DRAW_XML] = 1;
3336
          for(i=0;i<4;i++){
3337
            switch(i){
3338
              case 0: double_data[0]=get_real(infile,0);break; /* x in x/y-range coord system -> pixel width */
3339
              case 1: double_data[1]=get_real(infile,0);break; /* y in x/y-range coord system  -> pixel height */
3340
              case 2: URL = get_string_argument(infile,0);break;
3341
              case 3:
3342
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
3343
                temp = getSVGMOL(URL,get_string(infile,1));
3344
                decimals = find_number_of_digits(precision);
3345
                if(use_affine == TRUE ){ transform(2,2);}
3346
                if( use_offset != 0 || drag_type != -1 ){int_data[2] = 1;}else{int_data[2] = 0;} /* only centered or not-centered */
3347
                int_data[0] = x2px(double_data[0]);
3348
                int_data[1] = y2px(double_data[1]);
3349
                if( use_slider != -1 && onclick == 0 ){ onclick = 3;}/* no drag&onclick but slideable */
3350
                if( use_slider != -1 && drag_type > 0 ){ onclick = 5;}/* slider+drag*/
3351
                if( strstr(temp,"\"") != 0 ){ temp = str_replace(temp,"\"","'"); }
18557 bpr 3352
                tmp_buffer=my_newmem(MAX_BUFFER);
3353
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "var draw_xml%d = {id:%d,type:'svg',x:[%d],y:[%d],mathml:\"%s\",drag_type:%d,onclick:%d,object_cnt:%d,stroke_color:\"%s\",stroke_opacity:%.2f,fill_color:\"%s\",fill_opacity:%.2f,use_center:%d,use_snap:%d,angle:%f,fontfamily:\"%s\",transform:%s,use_affine:%d,offset:[0,0],use_slider:%s,rotation_center:%s,once:true};slidergroup[%d] = null;draw_xml(draw_xml%d);\n",drawxml_cnt,drawxml_cnt,int_data[0],int_data[1],temp,drag_type,onclick,object_cnt,stroke_color,stroke_opacity,fill_color,fill_opacity,int_data[2],use_snap,angle,font_family,doubledata2js_array(affine_matrix,6,decimals),use_affine,my_sliders,rotation_center,object_cnt,drawxml_cnt));
18552 bpr 3354
                add_to_buffer(tmp_buffer);
3355
                if(onclick != 0 ){object_cnt++;}
3356
                drawxml_cnt++;/* keeps track on imported img,div,p,span,mathml,svg */
3357
                break;
3358
              default:break;
3359
            }
3360
          }
3361
          reset();
3362
          break;
3363
        case OPACITY:
3364
  /*
3365
  @ opacity [0-255],[0-255]
3366
  @ opacity [0.0 - 1.0],[0.0 - 1.0]
3367
  @ alternative: transparent
3368
  @ first item is stroke opacity, second is fill opacity
3369
  @%opacity%size 400,400%xrange -10,10%yrange -10,10%opacity 255,0%fcircle -10,0,100,blue%opacity 250,50%fcircle -5,0,100,blue%opacity 200,100%fcircle 0,0,100,blue%opacity 150,150%fcircle 5,0,100,blue%opacity 100,200%fcircle 10,0,100,blue
3370
  */
3371
          for(i = 0 ; i<2;i++){
3372
            switch(i){
3373
              case 0: double_data[0]= get_real(infile,0);break;
3374
              case 1: double_data[1]= get_real(infile,1);break;
3375
              default: break;
3376
            }
3377
           }
3378
          if( double_data[0] > 255 ||  double_data[1] > 255  || double_data[0] < 0 || double_data[1] < 0 ){ canvas_error("opacity [0 - 255], [0 - 255] ");}/* typo or non-RGB ? */
18608 bpr 3379
          if( double_data[0] > 1 ){ stroke_opacity = (double) (0.0039215*double_data[0]); }else{ stroke_opacity = double_data[0];} /* 0.0 - 1.0 */
3380
          if( double_data[1] > 1 ){ fill_opacity = (double) (0.0039215*double_data[1]); }else{ fill_opacity = double_data[1];} /* 0.0 - 1.0 */
18552 bpr 3381
          break;
18608 bpr 3382
        case STROKEOPACITY:
3383
  /*
3384
  @ strokeopacity [0-255]
3385
  @ strokeopacity [0.0 - 1.0]
3386
  @%strokeopacity%size 400,400%xrange -10,10%yrange -10,10%fillopacity 120%strokeopacity 255%circle -10,0,100,blue%strokeopacity 100%circle -5,0,100,blue%strokeopacity 50%circle 0,0,100,blue
3387
  */
3388
          double_data[0]= get_real(infile,1);
3389
          if( double_data[0] > 255 || double_data[0] < 0 ){ canvas_error("opacity [0 - 255] ");}/* typo or non-RGB ? */
3390
          if( double_data[0] > 1 ){ stroke_opacity = (double) (0.0039215*double_data[0]); }else{ stroke_opacity = double_data[0];} /* 0.0 - 1.0 */
3391
          break;
3392
        case FILLOPACITY:
3393
  /*
3394
  @ fillopacity [0-255]
3395
  @ fillopacity [0.0 - 1.0]
3396
  @%fillopacity%size 400,400%xrange -10,10%yrange -10,10%strokeopacity 100%%fillopacity 0%fcircle -10,0,100,blue%fillopacity 50%fcircle -5,0,100,blue%fillopacity 100%fcircle 0,0,100,blue%fillopacity 150%fcircle 5,0,100,blue%fillopacity 200%fcircle 10,0,100,blue
3397
  */
3398
          double_data[0]= get_real(infile,1);
3399
          if( double_data[0] > 255 || double_data[0] < 0 ){ canvas_error("fillopacity [0 - 255] ");}/* typo or non-RGB ? */
3400
          if( double_data[0] > 1 ){ fill_opacity = (double) (0.0039215*double_data[0]); }else{ fill_opacity = double_data[0];} /* 0.0 - 1.0 */
3401
          break;
18552 bpr 3402
        case ONCLICK:
3403
  /*
18556 bpr 3404
  @ onclick
3405
  @ keyword (no arguments required)
3406
  @ if the next object is clicked, its ''object onclick_or_drag sequence number`` in fly script is returned by <code>javascript:read_canvas();</code>
3407
  @ onclick seqeuence numbering starts at ''0``, e.g. if there are 6 objects set onclick, the first onclick object will have id-number ''0``, the last id-number ''5``
3408
  @ line based objects will show an increase in line width<br>font based objects will show the text in ''bold`` when clicked.
3409
  @ the click zone (accuracy) is determined by 2&times; the line width of the object
3410
  @ onclick and <a href="#drag">drag x|y|xy</a> may be combined in a single flyscript (although a single object can <b>not</b> be onclick and draggable at the same time...)
3411
  @ note: not all objects may be set onclick
3412
  @%onclick%size 400,400%xrange -10,10%yrange -10,10%opacity 255,60%linewidth 3%onclick%fcircles blue,-3,3,1,1,2,2,3,1,1%onclick%ftriangles red,-4,-4,-4,0,-3,-2,0,0,4,0,2,-4%onclick%frects green,-4,4,-2,2,1,-1,3,-4
18552 bpr 3413
  */
3414
          fprintf(js_include_file,"use_dragdrop_reply = true;");
3415
          onclick = 1;
3416
          use_dragstuff=2;
3417
          js_function[INTERACTIVE] = 1;
3418
          break;
3419
        case PARALLEL:
3420
  /*
18556 bpr 3421
  @ parallel x1,y1,x2,y2,dx,dy,n,[colorname or #hexcolor]
3422
  @ affine transformations should be identical to flydraw
3423
  @ in case of <a href='#rotate'>rotation</a>  or <a href='#affine'>affine transformation </a>, command parallel will produce <em>n</em> individual segments, and these may be set ''onclick`` or ''drag xy`` individually.
3424
  @ in case of <em>no rotation or transformations</em> the lines can not be set ''onclick`` or ''drag xy``.
3425
  @ note: a large number of parallel lines (large <em>n</em>) may result in a canvasdraw error (...simplify your script...it produces too many lines...)
3426
  @%parallel_click%size 400,400%xrange -10,10%yrange -10,10%parallel -5,5,-4,-5,0.25,0,40,red%rotate 45%onclick%parallel -5,5,-4,-5,0.25,0,40,blue
3427
  @%parallel%size 400,400%xrange -10,10%yrange -10,10%parallel -5,5,-4,-5,0.25,0,40,red
18552 bpr 3428
  */
3429
          decimals = find_number_of_digits(precision);
3430
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
3431
          if( use_rotate == TRUE || use_affine == TRUE ){
3432
            for( i = 0;i < 8; i++ ){
3433
              switch(i){
3434
                case 0: double_data[0] = get_real(infile,0);break; /* x1-values */
3435
                case 1: double_data[1] = get_real(infile,0);break; /* y1-values */
3436
                case 2: double_data[2] = get_real(infile,0);break; /* x2-values */
3437
                case 3: double_data[3] = get_real(infile,0);break; /* y2-values */
3438
                case 4: double_data[4] = get_real(infile,0);break; /* xv  */
3439
                case 5: double_data[5] = get_real(infile,0);break; /* yv  */
3440
                case 6: int_data[0] = (int) (get_real(infile,0));break; /* n  */
3441
                case 7: stroke_color=get_color(infile,1);break;/* name or hex color */
3442
                default: break;
3443
              }
3444
            }
3445
            double_data[6] = double_data[0]; /* x1 */
3446
            double_data[7] = double_data[1]; /* y1 */
3447
            double_data[8] = double_data[2]; /* x2 */
3448
            double_data[9] = double_data[3]; /* y2 */
3449
            for(i = 0 ; i < int_data[0] ; i++){
3450
              double_data[0] = double_data[6] + i*double_data[4];
3451
              double_data[1] = double_data[7] + i*double_data[5];
3452
              double_data[2] = double_data[8] + i*double_data[4];
3453
              double_data[3] = double_data[9] + i*double_data[5];
3454
              if(use_rotate == TRUE ){ rotate(4,angle,rotationcenter,2);}
3455
              if(use_affine == TRUE ){ transform(4,2);}
18557 bpr 3456
              tmp_buffer=my_newmem(MAX_BUFFER);
3457
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[1],decimals,double_data[3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 3458
              add_to_buffer(tmp_buffer);
3459
              if(onclick != 0){object_cnt++;}
3460
            }
3461
            dragstuff[4] = 1;
3462
          }
3463
          else  /* use the old parallel version: calculations in javascript */
3464
          {
3465
            for( i = 0;i < 8; i++ ){
3466
              switch(i){
3467
                case 0: double_data[0] = get_real(infile,0);break; /* x1-values */
3468
                case 1: double_data[1] = get_real(infile,0);break; /* y1-values */
3469
                case 2: double_data[2] = get_real(infile,0);break; /* x2-values */
3470
                case 3: double_data[3] = get_real(infile,0);break; /* y2-values */
3471
                case 4: double_data[4] = xmin + get_real(infile,0);break; /* xv  */
3472
                case 5: double_data[5] = ymax + get_real(infile,0);break; /* yv  */
3473
                case 6: int_data[0] = (int) (get_real(infile,0));break; /* n  */
3474
                case 7: stroke_color=get_color(infile,1);/* name or hex color */
18557 bpr 3475
                  tmp_buffer=my_newmem(MAX_BUFFER);
3476
                  check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,11,[%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f],[%d,%d,%d],[%d,%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[4],decimals,double_data[1],decimals,double_data[3],decimals,double_data[5],int_data[0],int_data[0],int_data[0],int_data[0],int_data[0],int_data[0],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 3477
                  add_to_buffer(tmp_buffer);
3478
                  if(onclick != 0){object_cnt++;}
3479
                  break;
3480
                default: break;
3481
              }
3482
              dragstuff[11] = 1;
3483
            }
3484
          }
3485
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
3486
          reset();
3487
          break;
3488
        case PLOTSTEPS:
3489
      /*
18556 bpr 3490
  @ plotsteps a_number
18669 bpr 3491
  @ default 250
3492
  @ only used for commands <a href="#curve">curve / plot</a>
18556 bpr 3493
  @ use with care !
18552 bpr 3494
      */
3495
          plot_steps = (int) (get_real(infile,1));
3496
          break;
3497
        case POINT:
3498
  /*
3499
  @ point x,y,color
3500
  @ draw a single point at (x;y) in color 'color'
3501
  @ use command <code>linewidth int</code> to adjust size
3502
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
3503
  @ will not resize on zooming (command <code>circle x,y,r,color</code> will resize on zooming)
3504
  @ attention: in case of command <a href="#rotate">rotate angle</a> a point has rotation center (0:0) in x/y-range
3505
  @%point%size 400,400%xrange -10,10%yrange -10,10%opacity 255,255%linewidth 1%onclick%point 0,0,red%linewidth 2%onclick%point 1,1,blue%linewidth 3%onclick%point 3,3,green%linewidth 4%point 4,4,orange
3506
  */
3507
          for(i=0;i<3;i++){
3508
            switch(i){
3509
              case 0: double_data[0] = get_real(infile,0);break; /* x */
3510
              case 1: double_data[1] = get_real(infile,0);break; /* y */
3511
              case 2: stroke_color = get_color(infile,1);/* name or hex color */
3512
                if(use_rotate == TRUE ){rotate(2,angle,rotationcenter,2);}
3513
                if(use_affine == TRUE ){ transform(2,2);}
3514
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
3515
                decimals = find_number_of_digits(precision);
18557 bpr 3516
                tmp_buffer=my_newmem(MAX_BUFFER);
3517
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,2,[%.*f],[%.*f],[%.2f],[%d],%.2f,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[1],1.5*line_width,line_width,1.5*line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,1,0,0,0,use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 3518
                add_to_buffer(tmp_buffer);
3519
                /* object_cnt++; */
3520
                if(onclick != 0){object_cnt++;}
3521
                break;
3522
              default: break;
3523
            }
3524
          }
3525
          dragstuff[2] = 1;
3526
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
3527
          reset();
3528
          break;
3529
        case POINTS:
3530
  /*
3531
  @ points color,x1,y1,x2,y2,...,x_n,y_n
3532
  @ draw multiple points at given coordinates in color 'color'
3533
  @ use command <code>linewidth int</code> to adjust size
3534
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually (!)
3535
  @ attention: in case of command <a href="#rotate">rotate angle</a> the points have rotation center (0:0) in x/y-range
3536
  @%points_1%size 400,400%xrange -10,10%yrange -10,10%opacity 255,255%snaptogrid%linewidth 1%drag xy%points red,0,0,1,1,2,2,3,3%drag x%points blue,0,1,1,2,2,3,3,4
3537
  @%points_2%size 400,400%xrange -10,10%yrange -10,10%opacity 255,255%linewidth 1%onclick%points red,0,0,1,1,2,2,3,3%onclick%points blue,0,1,1,2,2,3,3,4
3538
  */
3539
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
3540
          fill_color = stroke_color;
3541
          i=0;
3542
          while( ! done ){     /* get next item until EOL*/
3543
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
3544
            if(i%2 == 0 ){
3545
              double_data[i] = get_real(infile,0); /* x */
3546
            }
3547
            else {
3548
              double_data[i] = get_real(infile,1); /* y */
3549
            }
3550
            i++;
3551
          }
3552
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
3553
          if(use_affine == TRUE ){ transform(i-1,2);}
3554
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
3555
          decimals = find_number_of_digits(precision);
3556
          for(c = 0 ; c < i-1 ; c = c+2){
18557 bpr 3557
            tmp_buffer=my_newmem(MAX_BUFFER);
3558
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,2,[%.*f],[%.*f],[%.2f],[%d],%.2f,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+1],1.5*line_width,line_width,1.5*line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,1,0,0,0,use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 3559
            add_to_buffer(tmp_buffer);
3560
            /* object_cnt++; */
3561
            if(onclick != 0){object_cnt++;}
3562
          }
3563
          dragstuff[2] = 1;
3564
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
3565
          reset();
3566
          break;
3567
        case POLY:
3568
  /*
3569
  @ poly color,x1,y1,x2,y2...x_n,y_n
3570
  @ polygon color,x1,y1,x2,y2...x_n,y_n
3571
  @ draw closed polygon
3572
  @ use command ''fpoly`` to fill it or use keyword <a href='#filled'>filled</a>
3573
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
3574
  @%polygon_1%size 400,400%xrange -10,10%yrange -10,10%opacity 255,25%fillcolor orange%filled%linewidth 2%drag xy%snaptogrid%poly blue,0,0,1,3,3,1,2,4,-1,3
3575
  @%polygon_2%size 400,400%xrange -10,10%yrange -10,10%opacity 255,25%fillcolor orange%filled%linewidth 1%onclick%poly green,0,0,1,3,3,1,2,4,-1,3
3576
  */
3577
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
3578
          i=0;
3579
          c=0;
3580
          while( ! done ){     /* get next item until EOL*/
3581
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
3582
            for( c = 0 ; c < 2; c++){
3583
              if(c == 0 ){
3584
                double_data[i] = get_real(infile,0);
3585
                i++;
3586
              }
3587
              else {
3588
                double_data[i] = get_real(infile,1);
3589
                i++;
3590
              }
3591
            }
3592
          }
3593
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
3594
          if(use_affine == TRUE ){ transform(i-1,2);}
3595
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
8386 schaersvoo 3596
 
18552 bpr 3597
      /* draw path:  closed & optional filled */
3598
          decimals = find_number_of_digits(precision);
18557 bpr 3599
          tmp_buffer=my_newmem(MAX_BUFFER);
3600
          check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,5,%s,[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,double_xy2js_array(double_data,i,decimals),line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 3601
          add_to_buffer(tmp_buffer);
3602
          if(onclick != 0){object_cnt++;}
3603
          reset();
3604
          dragstuff[5] = 1;
3605
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
3606
          break;
3607
        case POLYLINE:
3608
  /*
3609
  @ polyline color,x1,y1,x2,y2...x_n,y_n
3610
  @ brokenline color,x1,y1,x2,y2...x_n,y_n
3611
  @ path color,x1,y1,x2,y2...x_n,y_n
3612
  @ remark: there is <b>no</b> command polylines | brokenlines | paths ... just use multiple commands <code>polyline, x1,y1,x2,y2...x_n,y_n</code>
3613
  @ remark: there are commands <code>userdraw path(s),color</code> and <code>userdraw polyline,color</code>... these are two entirely different things ! the path(s) userdraw commands may be used for freehand drawing(s)<br>the polyline userdraw command is analogue to this polyline|brokenline command
3614
  @ the command interconnects the points in the given order with a line (canvasdraw will not close the drawing: use command <a href="#poly">polygon</a> for this)
3615
  @ use command <a href='#segments'>segments</a> for a series of segments. These may be clicked/dragged individually
3616
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
3617
  @%polyline_1%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%drag xy%snaptogrid%polyline blue,0,0,1,3,3,1,2,4,-1,3
3618
  @%polyline_2%size 400,400%xrange -10,10%yrange -10,10%linewidth 1%onclick%polyline green,0,0,1,3,3,1,2,4,-1,3
3619
  */
11806 schaersvoo 3620
 
18552 bpr 3621
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
3622
          i=0;
3623
          c=0;
3624
          while( ! done ){     /* get next item until EOL*/
3625
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
3626
            for( c = 0 ; c < 2; c++){
3627
              if(c == 0 ){
3628
                double_data[i] = get_real(infile,0);
3629
                i++;
3630
              }
3631
              else {
3632
                double_data[i] = get_real(infile,1);
3633
                i++;
3634
              }
3635
            }
3636
          }
11806 schaersvoo 3637
 
18552 bpr 3638
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
3639
          if(use_affine == TRUE ){ transform(i-1,2);}
3640
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
11806 schaersvoo 3641
 
18552 bpr 3642
      /* draw path: not closed & not filled */
3643
          decimals = find_number_of_digits(precision);
18557 bpr 3644
          tmp_buffer=my_newmem(MAX_BUFFER);
3645
          check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,%s,[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,double_xy2js_array(double_data,i,decimals),line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 3646
          add_to_buffer(tmp_buffer);
3647
          if(onclick != 0){object_cnt++;}
3648
          /* object_cnt++;*/
3649
          reset();
3650
          dragstuff[4] = 1;
3651
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
3652
          break;
3653
        case POPUP:
3654
      /*
18556 bpr 3655
  @ popup
3656
  @ keyword (no arguments)
3657
  @ if fly-script starts with keyword ''popup``, the canvas image will be exclusively in a popup window (xsize px &times; ysize px)
3658
  @ if keyword ''popup`` is used after command <code>size xsize,ysize</code> the canvas will also be displayed in a popup window with size ''xsize &times; ysize``
3659
  @ the popup window will be embedded into the page as a normal image, when ''status=done``; override with keyword <a href="#status">nostatus</a>
3660
  @ to access the read_canvas and read_dragdrop functions in a popup window, use:<br> <code> function read_all(){<br> if( typeof popup !== 'undefined' ){<br> var fun1 = popup['read_dragdrop'+canvas_scripts[0]];<br>var fun2 = popup['read_canvas'+canvas_scripts[0]];<br> popup.close();<br> return "dragdrop="+fun1()+"\\ncanvas="+fun2();<br> };</code>
3661
  @ to set a canvasdraw produced <a href="#clock">clock</a> or multiple clocks...use something like: <code>popup.set_clock(clock_id,type,diff);</code> as js-function for a button (or something else) in your document page.<br>where in <b>clock_id</b> starts with 0 for the first clock<br><b>type</b> is 1 for Hours,2 for Minutes and 3 for Seconds<br><b>diff</b> is the increment (positive or negative) per click
3662
  @%popup%popup%size 400,400%xrange -2*pi,2*pi%yrange -5,5%precision 0%axis%axisnumbering%opacity 100,190%grid 1,1,grey,2,2,5,black%linewidth 4%fillcolor blue%trange -pi,pi%animate%linewidth 1%precision 1000%jsplot red,4*cos(2*x),2*sin(3*x-pi/6)%strokecolor green%functionlabel H(x)=%userinput function
18552 bpr 3663
      */
3664
          use_tooltip = 2;
3665
          break;
3666
        case PROTRACTOR:
3667
  /*
18556 bpr 3668
  @ protractor x,y,x_width,type,mode,use_a_scale
3669
  @ x,y are the initial location
3670
  @ x_width: give the width in x-coordinate system (e.g. not in pixels !)
3671
  @ type = 1: a triangle range 0 - 180<br>type = 2: a circle shape 0 - 360
3672
  @ mode: use -1 to set the protractor interactive (mouse movement of protractor)<br>use mode = '0&deg; - 360&deg;' to set the protractor with a static angle of some value
3673
  @ if the value of the user_rotation angle is to be shown...use command <a href='#display'>display degree,color,fontsize</a><a href='#display'>display radian,color,fontsize</a>
3674
  @ use_scale = 1: the protractor will have some scale values printed; use_scale=0 to disable
3675
  @ the rotating direction of the mouse around the protractor determines the clockwise/ counter clockwise rotation of the protractor...
3676
  @ commands ''stroke_color | fill_color | linewidth | opacity | font_family`` will determine the looks of the protractor.
3677
  @ default replyformat: reply[0] = x;reply[1] = y;reply[2] = angle_in_radians<br>use command ''precision`` to set the reply precision.
3678
  @ if combined with a ruler, use replyformat = 32
3679
  @ command <code>snap_to_grid</code> may be used to assist the pupil at placing the protractor
3680
  @ when using command ''zoom``, pay <b>attention</b> to the size and symmetry of your canvas<br>...to avoid a partial image, locate the start position near the center of the visual canvas<br>technical: the actual ''protractor`` is just a static generated image in a new canvas-memory<br>This image is only generated once, and a copy of its bitmap is translated & rotated onto the visible canvas.<br>That is the reason for the ''high-speed dragging and rotating``.<br>I've limited its size to xsize &times; ysize e.g. the same size as the visual canvas...
3681
  @ only one protractor allowed (for the time being)
3682
  @ usage: first left click on the protractor will activate dragging;<br>a second left click will activate rotating (just move mouse around)<br>a third click will freeze this position and the x/y-coordinate and angle in radians will be stored in reply(3)<br>a next click will restart this sequence...
3683
  @%protractor%size 400,400%xrange -5,10%yrange -5,10%hline 0,0,black%vline 0,0,black%fillcolor orange%opacity 255,40%protractor 2,-2,6,0,-1,1,1%mouse red,22
18552 bpr 3684
  */
3685
          for( i = 0;i < 6; i++ ){
3686
            switch(i){
3687
              case 0: double_data[0] = get_real(infile,0);break; /* x-center */
3688
              case 1: double_data[1] = get_real(infile,0);break; /* y-center */
3689
              case 2: double_data[2] = get_real(infile,0);break; /* x-width */
3690
              case 3: int_data[0] = (int)(get_real(infile,0));break; /* type: 1==triangle 2 == circle */
3691
              case 4: int_data[1] = (int)(get_real(infile,0));break; /* passive mode == 0; active mode == -1 */
3692
              case 5: int_data[2] = (int)(get_real(infile,1)); /* use scale */
3693
                decimals = find_number_of_digits(precision);
3694
                if( int_data[1] < 0 ){ js_function[JS_FIND_ANGLE] = 1;}
18557 bpr 3695
                add_js_protractor(int_data[0],double_data[0], double_data[1], double_data[2],font_family,stroke_color,stroke_opacity,fill_color,fill_opacity,line_width,int_data[2],int_data[1],use_snap);
3696
                tmp_buffer=my_newmem(MAX_BUFFER);
3697
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, ";protractor%d(); ",canvas_root_id));
18552 bpr 3698
                add_to_buffer(tmp_buffer);
3699
                reply_precision = precision;
3700
        /* no reply from protractor if non-interactive */
3701
                if( reply_format == 0 && int_data[1] == -1 ){reply_format = 30;}
3702
                js_function[INTERACTIVE] = 1;
3703
                break;
3704
              default: break;
3705
            }
3706
          }
3707
          break;
3708
        case PIXELS:
3709
  /*
3710
  @ pixels color,x1,y1,x2,y2,x3,y3...
3711
  @ draw rectangular "points" with diameter 1 pixel
3712
  @ pixels can <b>not</b> be dragged or clicked
3713
  @ "pixelsize = 1" may be changed by command <code>pixelsize int</code>
3714
  @%pixels%size 400,400%opacity 255,255%pixelsize 5%pixels red,1,1,2,2,3,3,4,4,5,5,10,10,20,20,30,30,40,40,50,50,60,60,70,70,80,80,90,90,100,100,120,120,140,140,160,160,180,180,200,200,240,240,280,280,320,320,360,360,400,400%#NOTE pixelsize=5...otherwise you will not see them clearly...
3715
  */
3716
          js_function[DRAW_PIXELS] = 1;
3717
          stroke_color=get_color(infile,0);
3718
          i=0;
3719
          c=0;
3720
          while( ! done ){     /* get next item until EOL*/
3721
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
3722
            for( c = 0 ; c < 2; c++){
3723
              if(c == 0 ){
3724
                double_data[i] = get_real(infile,0);
3725
                i++;
3726
              }
3727
              else {
3728
                double_data[i] = get_real(infile,1);
3729
              }
3730
            }
3731
        }
3732
        if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
3733
        if(use_affine == TRUE ){ transform(i-1,2);}
3734
        decimals = find_number_of_digits(precision);
3735
        /*  *double_xy2js_array(double xy[],int len,int decimals) */
18557 bpr 3736
        tmp_buffer=my_newmem(MAX_BUFFER);
3737
        check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_setpixel(%s,\"%s\",%.2f,%d);\n",double_xy2js_array(double_data,i,decimals),stroke_color,stroke_opacity,pixelsize));
18552 bpr 3738
        add_to_buffer(tmp_buffer);
3739
        reset();
3740
        break;
3741
        case PIXELSIZE:
3742
  /*
3743
  @ pixelsize int
3744
  @ in case you want to deviate from default pixelsize = 1(...)
3745
  @ pixelsize 100 is of course a filled rectangle 100px &times; 100px
3746
  */
3747
          pixelsize = (int) get_real(infile,1);
3748
          break;
15111 schaersvoo 3749
 
18552 bpr 3750
        case PIECHART:
3751
  /*
3752
  @ piechart xc,yc,radius,'data+colorlist'
3753
  @ (xc: yc) center of circle diagram in xrange/yrange
3754
  @ radius in pixels
18627 bpr 3755
  @ data+color list: a colon separated list of raw data and corresponding colors<br>canvasdraw will not check validity of colornames...<br>in case of trouble look into javascript debugging of your browser
18552 bpr 3756
  @ example data+colorlist: 32:red:65:green:23:black:43:orange:43:yellow:14:white
3757
  @ the number of colors must match the number of data.
3758
  @ if defined <a href='#fillpattern'>fillpattern some_pattern</a> then the pie pieces will be filled with the respective color and a fill pattern...<br>the pattern is cycled from the 4 pattern primitives: grid,hatch,diamond,dot,grid,hatch,diamond,dot,...
18627 bpr 3759
  @ use command <a href='#opacity'>opacity</a> to adjust fill_opacity of colors
3760
  @ use command <a href='#legend'>legend</a> to automatically create a legend using the same colors as pie segments; unicode allowed in legend; expect javascript trouble if the amount of ''pie-slices``, ''pie-colors``, ''pie-legend-titles`` do not match, a javascript console is your best friend...<br>use command ''fontfamily`` to set the font of the legend.
18552 bpr 3761
  @ use command <a href='centered'>centered</a> to place <a href='#legend'>legend</a> text inside the piechart. The text is using the same color as the pie segment: use (fill) opacity to enhance visibility.
3762
  @%piechart_1%size 300,200%xrange -10,10%yrange -10,10%legend cars:motorcycles:bicycles:trikes%opacity 255,120%piechart -5,0,75,22:red:8:blue:63:green:7:purple%
3763
  @%piechart_2%size 200,200%xrange -10,10%yrange -10,10%fontfamily 16px Arial%centered%legend cars:motorcycles:bicycles:trikes%opacity 255,60%piechart 0,0,100,22:red:8:blue:63:green:7:purple
3764
  */
3765
          js_function[DRAW_PIECHART] = 1;
3766
          for(i=0;i<5;i++){
3767
            switch(i){
3768
              case 0: int_data[0] = x2px(get_real(infile,0)); break; /* x */
3769
              case 1: int_data[1] = y2px(get_real(infile,0)); break; /* y  */
3770
              case 2: int_data[2] = (int)(get_real(infile,1));break;/* radius*/
3771
              case 3: temp = get_string(infile,1);
3772
                if( strstr( temp, ":" ) != 0 ){ temp = str_replace(temp,":","\",\"");}
18557 bpr 3773
                tmp_buffer=my_newmem(MAX_BUFFER);
3774
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_piechart(%d,%d,%d,%d,[\"%s\"],%.2f,%d,\"%s\",%d,%d);\n",PIECHART,int_data[0],int_data[1],int_data[2],temp,fill_opacity,legend_cnt,font_family,use_filled,use_offset));
18552 bpr 3775
                add_to_buffer(tmp_buffer);
3776
                break;
3777
              default:break;
3778
            }
3779
          }
3780
          reset();
3781
          break;
3782
        case RANGE:
3783
  /*
3784
  @ range xmin,xmax,ymin,ymax
3785
  @ if not given: 0,xsize,0,ysize (eg in pixels)
3786
  */
3787
          for(i = 0 ; i<4; i++){
3788
            switch(i){
3789
              case 0: xmin = get_real(infile,0);break;
3790
              case 1: xmax = get_real(infile,1);break;
3791
              case 2: ymin = get_real(infile,0);break;
3792
              case 3: ymax = get_real(infile,1);break;
3793
              default: break;
3794
            }
3795
          }
3796
          if(xmin >= xmax){canvas_error(" xrange is not OK: xmin &lt; xmax !");}
3797
          if(ymin >= ymax){canvas_error(" yrange is not OK: ymin &lt; ymax !");}
3798
          fprintf(js_include_file,"var xmin = %f;var xmax = %f;var ymin = %f;var ymax = %f;",xmin,xmax,ymin,ymax);
3799
          found_size_command = found_size_command+2;
3800
          break;
3801
        case RAYS:
3802
  /*
18556 bpr 3803
  @ rays color,xc,yc,x1,y1,x2,y2,x3,y3...x_n,y_n
3804
  @ draw rays in color 'color' and center (xc:yc)
3805
  @ may be set draggable or onclick (every individual ray)
3806
  @%rays_onclick%size 400,400%xrange -10,10%yrange -10,10%onclick%rays blue,0,0,3,9,-3,5,-4,0,4,-9,7,9,-8,1,-1,-9
3807
  @%rays_drag_xy%size 400,400%xrange -10,10%yrange -10,10%drag xy%rays blue,0,0,3,9,-3,5,-4,0,4,-9,7,9,-8,1,-1,-9
18552 bpr 3808
  */
3809
          stroke_color=get_color(infile,0);
3810
          fill_color = stroke_color;
3811
          double_data[0] = get_real(infile,0);/* xc */
3812
          double_data[1] = get_real(infile,0);/* yc */
3813
          i=2;
3814
          while( ! done ){     /* get next item until EOL*/
3815
            if(i > MAX_INT - 1){canvas_error("in command rays too many points / rays in argument: repeat command multiple times to fit");}
3816
            if(i%2 == 0 ){
3817
              double_data[i] = get_real(infile,0); /* x */
3818
            }
3819
            else {
3820
              double_data[i] = get_real(infile,1); /* y */
3821
            }
3822
            fprintf(js_include_file,"/* double_data[%d] = %f */\n",i,double_data[i]);
3823
            i++;
3824
          }
3825
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
3826
          if(use_affine == TRUE ){ transform(i-1,2);}
3827
          if( i%2 != 0 ){canvas_error("in command rays: unpaired x or y value");}
3828
          decimals = find_number_of_digits(precision);
3829
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
3830
          for(c=2; c<i;c = c+2){
18557 bpr 3831
            tmp_buffer=my_newmem(MAX_BUFFER);
3832
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[c],decimals,double_data[1],decimals,double_data[c+1],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 3833
            add_to_buffer(tmp_buffer);
3834
    /* object_cnt++; */
3835
            if(onclick != 0){object_cnt++;}
3836
          }
3837
          reset();
3838
          dragstuff[4] = 1;
3839
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
3840
          break;
3841
        case RECT:
3842
  /*
3843
  @ rect x1,y1,x2,y2,color
3844
  @ use command <code>frect x1,y1,x2,y2,color</code> for a filled rectangle
3845
  @ use command/keyword <a href='#filled'>filled</a> before command <code>rect x1,y1,x2,y2,color</code>
3846
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
18572 bpr 3847
  @ note: internally a rect is defined with 4 points. So when performing some affine transformation, other than translation, it will result in some morphing of the rectangle !<br>this is a deviation of flydraw's rect&amp;affine
18552 bpr 3848
  @%rect%size 400,400%xrange -10,10%yrange -10,10%rect 0,0,4,-4,green%rect 0,5,4,1,red
3849
  */
3850
          for(i=0;i<5;i++){
3851
            switch(i){
3852
              case 0:double_data[0] = get_real(infile,0);break; /* x-values */
3853
              case 1:double_data[1] = get_real(infile,0);break; /* y-values */
3854
              case 2:double_data[4] = get_real(infile,0);break; /* x-values */
3855
              case 3:double_data[5] = get_real(infile,0);break; /* y-values */
3856
              case 4:stroke_color = get_color(infile,1);/* name or hex color */
3857
                decimals = find_number_of_digits(precision);
3858
                double_data[2] = double_data[4];
3859
                double_data[3] = double_data[1];
3860
                double_data[6] = double_data[0];
3861
                double_data[7] = double_data[5];
3862
          /* using closed PATH (type=5) instead of ctx.rect (type=1)!!!
3863
              0,1   2,3
3864
          6,7      4,5
3865
          x = [0,2,4,6]
3866
          y = [1,3,5,7]
3867
          */
18623 bpr 3868
                if(fillcolor) {fill_color=fillcolor;} else {fill_color=stroke_color;}
18552 bpr 3869
                if(use_rotate == TRUE ){rotate(8,angle,rotationcenter,2);}
3870
                if(use_affine == TRUE ){ transform(8,2);}
3871
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
18557 bpr 3872
                tmp_buffer=my_newmem(MAX_BUFFER);
18623 bpr 3873
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,5,[%.*f,%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f,%.*f],[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[4],decimals,double_data[6],decimals,double_data[1],decimals,double_data[3],decimals,double_data[5],decimals,double_data[7],line_width,line_width,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 3874
                add_to_buffer(tmp_buffer);
3875
                if(onclick != 0){object_cnt++;}
18555 bpr 3876
                /* object_cnt++; */
18552 bpr 3877
                reset();
3878
                break;
3879
              }
3880
            }
3881
          dragstuff[5] = 1;
3882
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
3883
          break;
3884
        case RECTS:
3885
  /*
3886
  @ rects color,x1,y1,x2,y2,.....
3887
  @ use command <code>frect color,x1,y1,x2,y2,.....</code> for a filled rectangle
3888
  @ use command/keyword <a href='#filled'>filled</a> before command <code>rects color,x1,y1,x2,y2,....</code>
18623 bpr 3889
  @ use command <code>fillcolor color</code> before ''frects`` to set the fill color.
18552 bpr 3890
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually
3891
  @%rects%size 400,400%xrange -10,10%yrange -10,10%rects red,0,0,4,-4,0,5,4,1
3892
  */
3893
      /* using closed PATH (type=5) in stead of ctx.rect (type=1)!!!
3894
      0,1   2,3 .....8,9  10,11.....
3895
  6,7      4,5 .....14,15  12,13.....
3896
  x = [0,2,4,6,8,10,12,14...]
3897
  y = [1,3,5,7,9,11,13,15...]
3898
      */
3899
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
18623 bpr 3900
          if(fillcolor) {fill_color=fillcolor;} else {fill_color=stroke_color;}
18552 bpr 3901
          i=0;
3902
          while( ! done ){     /* get next item until EOL*/
3903
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
3904
            if(i%2 == 0 ){
3905
              double_data[i] = get_real(infile,0); /* x */
3906
            }
3907
            else {
3908
              double_data[i] = get_real(infile,1); /* y */
3909
            }
3910
            i++;
3911
          }
3912
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
3913
          if(use_affine == TRUE ){ transform(i-1,2);}
3914
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
11806 schaersvoo 3915
 
18552 bpr 3916
          decimals = find_number_of_digits(precision);
3917
          for(c = 0 ; c < i-1 ; c = c+4){
18557 bpr 3918
            tmp_buffer=my_newmem(MAX_BUFFER);
18623 bpr 3919
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,5,[%.*f,%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f,%.*f],[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+2],decimals,double_data[c],decimals,double_data[c+1],decimals,double_data[c+1],decimals,double_data[c+3],decimals,double_data[c+3],line_width,line_width,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 3920
            add_to_buffer(tmp_buffer);
3921
            if(onclick != 0){object_cnt++;}
3922
    /* object_cnt++; */
3923
          }
3924
          dragstuff[5] = 1;
3925
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
3926
          if(use_rotate == TRUE ){
3927
            rotate(i-1,angle,rotationcenter,2);
3928
          }
3929
          reset();
3930
          break;
3931
        case REPLYFORMAT:
3932
  /*
3933
  @ replyformat number
3934
  @ use number=-1 to deactivate the js-functions read_canvas() and read_dragdrop()
3935
  @ default values should be fine !
3936
  @ use command <code>precision [0,1,10,100,1000,10000...]</code> before command ''replyformat`` to set the desired number of decimals in the student reply / drawing
3937
  @ the last value for ''precision int`` will be used to calculate the reply coordinates, if needed (read_canvas();)
3938
  @ choose<ul><li>replyformat 1: <code>x1,x2,x3,x4....x_n<br>y1,y2,y3,y4....y_n</code> x/y in pixels</li><li>replyformat 2: <code> x1,x2,x3,x4....x_n<br> y1,y2,y3,y4....y_n</code> x/y in xrange / yrange coordinate system</li><li>replyformat 3: <code> x1,x2,x3,x4....x_n<br> y1,y2,y3,y4....y_n<br> r1,r2,r3,r4....r_n</code> x/y in pixels, r in pixels</li><li>replyformat 4: <code> x1,x2,x3,x4....x_n<br> y1,y2,y3,y4....y_n<br> r1,r2,r3,r4....r_n</code> x/y in xrange / yrange coordinate system, r in pixels</li><li>replyformat 5: <code> Ax1,Ax2,Ax3,Ax4....Ax_n<br> Ay1,Ay2,Ay3,Ay4....Ay_n<br> Bx1,Bx2,Bx3,Bx4....Bx_n<br> By1,By2,By3,By4....By_n<br> Cx1,Cx2,Cx3,Cx4....Cx_n<br>  Cy1,Cy2,Cy3,Cy4....Cy_n<br>  ....<br>  Zx1,Zx2,Zx3,Zx4....Zx_n<br> Zy1,Zy2,Zy3,Zy4....Zy_n</code> x/y in pixels</li><li>replyformat 6: <code> Ax1,Ax2,Ax3,Ax4....Ax_n<br> Ay1,Ay2,Ay3,Ay4....Ay_n<br> Bx1,Bx2,Bx3,Bx4....Bx_n<br> By1,By2,By3,By4....By_n<br> Cx1,Cx2,Cx3,Cx4....Cx_n<br> Cy1,Cy2,Cy3,Cy4....Cy_n<br> ....<br> Zx1,Zx2,Zx3,Zx4....Zx_n<br> Zy1,Zy2,Zy3,Zy4....Zy_n</code> x/y in xrange / yrange coordinate system</li><li>replyformat 7: <code> x1:y1,x2:y2,x3:y3,x4:y4...x_n:y_n</code> x/y in pixels</li><li>replyformat 8: <code> x1:y1,x2:y2,x3:y3,x4:y4...x_n:y_n</code> x/y in xrange / yrange coordinate system</li><li>replyformat 9: <code> x1:y1:r1,x2:y2:r2,x3:y3:r3,x4:y4:r3...x_n:y_n:r_n</code> x/y in pixels</li><li>replyformat 10: <code> x1:y1:r1,x2:y2:r2,x3:y3:r3,x4:y4:r3...x_n:y_n:r_n</code> x/y in xrange / yrange coordinate system</li><li>replyformat 11: <code> Ax1,Ay1,Ax2,Ay2<br>Bx1,By1,Bx2,By2<br> Cx1,Cy1,Cx2,Cy2<br> Dx1,Dy1,Dx2,Dy2<br> ......<br> Zx1,Zy1,Zx2,Zy2</code> x/y in xrange / yrange coordinate system</li><li>replyformat 12: <code> Ax1,Ay1,Ax2,Ay2<br> Bx1,By1,Bx2,By2<br>Cx1,Cy1,Cx2,Cy2<br> Dx1,Dy1,Dx2,Dy2<br> ......<br> Zx1,Zy1,Zx2,Zy2</code> x/y in pixels</li><li>replyformat 13: <code> Ax1:Ay1:Ax2:Ay2,Bx1:By1:Bx2:By2,Cx1:Cy1:Cx2:Cy2,Dx1:Dy1:Dx2:Dy2, ... ,Zx1:Zy1:Zx2:Zy2</code> x/y in xrange / yrange coordinate system</li><li>replyformat 14: <code> Ax1:Ay1:Ax2:Ay2,Bx1:By1:Bx2:By2....Zx1:Zy1:Zx2:Zy2</code> x/y in pixels</li><li>replyformat 15: reply from inputfields,textareas <code>reply1,reply2,reply3,...,reply_n</code></li><li>replyformat 16: mathml input fields</li><li>replyformat 17: read ''userdraw text,color`` only <code>x1,y1,text1 \\n x2,y2,text2...\\n...x_n,y_n,text_n </code> x/y-values are in xrange/yrange</li><li>replyformat 18: read_canvas() will read all interactive clocks in <code>H1:M1:S1,H2:M2:S2...Hn:Mn:Sn</code></li><li>replyformat 19: read_canvas() will return the object number of marked / clicked object (clock), analogue to (shape library) onclick command</li><li>replyformat 20: read_canvas() will reply "object_number:x:y" of external images: object_number of the first draggable external image in the fly-script starts with 0, e.g. expect something like 0:-5:4,1:6:2,2:-2:-5, the first image position is (-5:4), the second image position is (6:2) and the third image position is (-2:-5)   <li>replyformat 21: <code> (x1:y1) (x2:y2) ... (x_n:y_n)</code> verbatim coordinate return</li><li>replyformat 22: returns an array .... <code>reply[0]=x1 reply[1]=y1 reply[2]=x2 reply[3]=y2 ... reply[n-1]=x_n reply[n]=y_n</code> x/y in xrange / yrange coordinate system</li><li>replyformat 23: can only be used for drawtype ''polyline``. A typical click sequence in drawtype polyline is x1,y1,x2,y2,x2,y2,x3,y3,x3,y3.....,x(n-1),y(n-1),x(n-1),y(n-1),xn,yn --replyformat 23 gives <code>x1,y1,x2,y2,x3,y3,.....x(n-1),y(n-1),xn,yn</code>; multiple occurences will be filtered out. The reply will be in x-y-range (xreply \\n yreply)</li><li>replyformat 24: read all inputfield values: even those set ''readonly``</li><li>replyformat 25: <code> angle1,angle2;...;angle_n</code> will return the radius (one or many) of the user drawn circle segment in degrees</li><li>replyformat 26: <code> rad1,rad2,...rad_n</code> will return the radius (one or many) of the user drawn circle segment in radians</li><li>replyformat 27: return (only) userdraw inputfields <code>x1,y1,text1<br> x2,y2,text2...<br>...x_n,y_n,textn</code></li><li>replyformat 28: <code> x1,y1,r1,x2,y2,r2...x_n,y_n,r_n</code> x / y / r in xrange / yrange coordinate system: may be used to reinput into command <code>circles color,x1,y1,r1,x2,y2,r2...x_n,y_n,r_n</code> will not return anything else (e.g. no inputfields, text etc)</li><li>replyformat 34: a special for OEF and dragging external images -included via commands <a href='#copy'>copy</a> or <a href='#copyresized'>copyresized</a> there will be an extra function <code>read_canvas_images()</code> for reading the coordinates of the images.<br>for now this is a unique function, e.g. there is no ''canvas id`` linked to it. (TO DO !!! 18/5/2019)</li></ul>
3939
  @ special replyformat = 100 ; will access to the raw javascript object data...use: read_dragdrop([property,property,...])<br>for example  properies like 'clicked','text', 'angle' , 'x'
3940
  */
3941
          reply_format = (int) get_real(infile,1);
3942
          reply_precision = precision;
3943
          break;
3944
        case ROUNDRECT:
3945
  /*
3946
  @ roundrect x1,y1,x2,y2,radius in px,color
3947
  @ use command <code>froundrect x1,y1,x2,y2,radius,color</code> for a filled rectangle
3948
  @ use command/keyword <a href='#filled'>filled</a> before command <code>roundrect x1,y1,x2,y2,radius,color</code>
3949
  @ fillcolor will be identical to ''color``
3950
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
3951
  @%roundrect%size 400,400%xrange -10,10%yrange -10,10%roundrect 0,0,4,-4,20,green%roundrect 0,5,4,1,10,red
3952
  */
3953
          for(i=0;i<6;i++){
3954
            switch(i){
3955
              case 0:double_data[0] = get_real(infile,0);break; /* x-values */
3956
              case 1:double_data[1] = get_real(infile,0);break; /* y-values */
3957
              case 2:double_data[2] = get_real(infile,0);break; /* x-values */
3958
              case 3:double_data[3] = get_real(infile,0);break; /* y-values */
3959
              case 4:int_data[0] = (int) (get_real(infile,0));break; /* radius value in pixels */
3960
              case 5:stroke_color = get_color(infile,1);/* name or hex color */
3961
                if(use_rotate == TRUE ){rotate(4,angle,rotationcenter,2);}
3962
                if(use_affine == TRUE ){ transform(2,4);}
3963
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
3964
      /* ensure no inverted roundrect is produced... */
3965
                if( double_data[0] > double_data[2] ){double_data[4] = double_data[0];double_data[0] = double_data[2];double_data[2] = double_data[4];}
3966
                if( double_data[3] > double_data[1] ){double_data[4] = double_data[1];double_data[1] = double_data[3];double_data[3] = double_data[4];}
3967
                decimals = find_number_of_digits(precision);
18557 bpr 3968
                tmp_buffer=my_newmem(MAX_BUFFER);
3969
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,6,[%.*f,%.*f],[%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[1],decimals,double_data[3],int_data[0],int_data[0],int_data[0],int_data[0],line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 3970
                add_to_buffer(tmp_buffer);
3971
                if(onclick != 0){object_cnt++;}
3972
      /* object_cnt++;*/
3973
                reset();
3974
                break;
3975
            }
3976
          }
3977
          dragstuff[6] = 1;
3978
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
3979
          break;
3980
        case ROUNDRECTS:
3981
  /*
3982
  @ roundrects color,radius in px,x1,y1,x2,y2,x3,y3,x4,y4,....
3983
  @ for filled roundrects use command/keyword <a href='#filled'>filled</a> before command
3984
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually
3985
  @%roundrects%size 400,400%xrange -10,10%yrange -10,10%roundrects blue,5,0,0,4,-4,5,4,1,2
3986
  */
11806 schaersvoo 3987
 
18552 bpr 3988
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
3989
          int_data[0] = (int) (get_real(infile,0)); /* radius value in pixels */
18623 bpr 3990
          if(fillcolor) {fill_color=fillcolor;} else {fill_color=stroke_color;}
18552 bpr 3991
          i=0;
3992
          while( ! done ){     /* get next item until EOL*/
3993
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
3994
            if(i%2 == 0 ){
3995
              double_data[i] = get_real(infile,0); /* x */
3996
            }
3997
            else {
3998
              double_data[i] = get_real(infile,1); /* y */
3999
            }
4000
            i++;
4001
          }
4002
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
4003
          if(use_affine == TRUE ){ transform(i-1,2);}
4004
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
4005
          decimals = find_number_of_digits(precision);
4006
          for(c = 0 ; c < i-1 ; c = c+4){
4007
    /* ensure no inverted roundrect is produced... */
4008
            if( double_data[c] > double_data[c+2] ){double_data[c+4] = double_data[c];double_data[c] = double_data[c+2];double_data[c+2] = double_data[c+4];}
4009
            if( double_data[c+3] > double_data[c+1] ){double_data[c+4] = double_data[c+1];double_data[c+1] = double_data[c+3];double_data[c+3] = double_data[c+4];}
18557 bpr 4010
            tmp_buffer=my_newmem(MAX_BUFFER);
18623 bpr 4011
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,6,[%.*f,%.*f],[%.*f,%.*f],[%d,%d],[%d,%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],int_data[0],int_data[0],int_data[0],int_data[0],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 4012
            add_to_buffer(tmp_buffer);
4013
            if(onclick != 0){object_cnt++;}
4014
    /* object_cnt++; */
4015
          }
4016
          dragstuff[6] = 1;
4017
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
4018
          reset();
4019
          break;
4020
        case RULER:
4021
  /*
4022
  @ ruler x,y,x-width,y-height,mode
4023
  @ x,y are the initial location
4024
  @ x-width, y-height are the ruler dimensions width &amp; height in xy-coordinate system
4025
  @ the ruler scale is by definition the x-scale, set by command ''xrange``. For example: a ruler x-width of 6 will have a scale ranging from 0 to 6
4026
  @ mode: use -1 to set the ruler interactive (eg mouse movement of ruler; drag &amp; rotate)<br>use mode = '0&deg; - 360&deg;' to set the ruler with a static angle of some value
4027
  @ if combined with a protractor, use replyformat = 32
4028
  @ only one ruler allowed (for the time being)
4029
  @ when using command ''zoom``, pay <b>attention</b> to the size and symmetry of your canvas to avoid a partial image, locate the start position near the center of the visual canvas; technical: the actual ''ruler`` is just a static generated image in a new canvas-memory. This image is only generated once, and a copy of its bitmap is translated & rotated onto the visible canvas. That is the reason for the ''high-speed dragging and rotating``. I have limited its size to xsize &times; ysize e.g. the same size as the visual canvas...
4030
  @ usage: first left click on the ruler will activate dragging; a second left click will activate rotating (just move mouse around), a third click will freeze this position and the x/y-coordinate and angle in radians will be stored in reply(3), a next click will restart this sequence...
4031
  @%ruler_interactive%size 800,400%xrange -10,10%yrange -10,10%strokecolor blue%opacity 200,50%filled%fillcolor lightgrey%ruler -9,0,10,2,-1%display degree,blue,22
4032
  @%ruler_set_degree_45%size 800,400%xrange -10,10%yrange -10,10%strokecolor blue%opacity 200,50%filled%fillcolor lightgrey%ruler 0,0,10,2,45
4033
  @%ruler_set_degree_125%size 800,400%xrange -10,10%yrange -10,10%strokecolor blue%opacity 200,50%filled%fillcolor lightgrey%ruler 0,0,10,2,125
4034
  */
4035
          for( i = 0;i < 5; i++ ){
4036
            switch(i){
4037
              case 0: double_data[0] = get_real(infile,0);break; /* x-center */
4038
              case 1: double_data[1] = get_real(infile,0);break; /* y-center */
4039
              case 2: double_data[2] = get_real(infile,0);break; /* x-width */
4040
              case 3: double_data[3] = get_real(infile,0);break; /* y-width */
4041
              case 4: int_data[0] = (int)(get_real(infile,1)); /* passive mode */
4042
                decimals = find_number_of_digits(precision);
4043
                if( int_data[0] < 0 ){
4044
                  js_function[JS_FIND_ANGLE] = 1;
4045
                }
18557 bpr 4046
                add_js_ruler(double_data[0],double_data[1],double_data[2],double_data[3], font_family,stroke_color,stroke_opacity,fill_color,fill_opacity,line_width,int_data[0],use_snap);
4047
                tmp_buffer=my_newmem(MAX_BUFFER);
4048
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, ";ruler%d(); ",canvas_root_id));
18552 bpr 4049
                add_to_buffer(tmp_buffer);
4050
                reply_precision = precision;
4051
                /* no reply from ruler if non-interactive */
4052
                if( reply_format == 0 && int_data[0] == -1 ){reply_format = 31;}
4053
                break;
4054
              default: break;
4055
            }
4056
          }
4057
          break;
4058
        case RESET:
4059
  /*
4060
  @ reset
4061
  @ keyword
4062
  @ disables the effects of the <a href="noreset">noreset</a> command
4063
  @ so the next objects will not be <a href="#filled">filled</a> and <a href="#dashed">dashed</a>
4064
  */
4065
          no_reset = FALSE; reset();
4066
          break;
4067
        case RESETOFFSET:
4068
  /*
18556 bpr 4069
  @ resetoffset
4070
  @ keyword ; use to restore text placement on the canvas to the real (x;y) coordinates of the left bottom corner of the text
4071
  @ may be active for commands <a href="#text">text</a> and <a href="#string">string</a> (e.g. objects in the drag/drop/onclick-librariy
18552 bpr 4072
  */
4073
          use_offset = 0;
4074
          break;
4075
        case ROTATE:
4076
  /*
18556 bpr 4077
  @ rotate rotation_angle
4078
  @ angle in degrees
4079
  @ (only) the next object will be rotated is given angle
4080
  @ positive values rotate counter clockwise
4081
  @ attention: all objects will be rotated around their first point...<br><code>rotate 45<br>triangle 1,1,5,1,3,4,red</code><br>will rotate 45 degrees around point (1:1)
4082
  @ if another rotation center is needed, use command <a href="#rotationcenter">rotationcenter xc,yc</a>.<br>to reset this rotationcenter, use keyword <a href="#killrotate">killrotate</a>
4083
  @ attention: rotate will mess up the interactivity of the rotated object <br>e.g. if combined with command <a href="#drag">drag xy</a> or keyword <a href="#onclick">onclick</a>: the mouse recognises the original -unrotated- coordinates of the object
4084
  @%rotate_1%size 400,400%xrange -10,10%yrange -10,10%fpoly yellow,0,0,4,3,2,5%rotate 45%fpoly violet,0,0,4,3,2,5%killrotate%rotate 90%fpoly violet,0,0,4,3,2,5%
18552 bpr 4085
  */
4086
          use_rotate = TRUE;
4087
          angle = -1*(get_real(infile,1));/* -1: to be compatible with Flydraw... */
4088
          break;
4089
        case ROTATION_CENTER:
4090
  /*
4091
  @ rotationcenter x_center,y_center
4092
  @ define an rotation center in your x/y-coordinate system
4093
  @ wims will not check the validity of your input; use javascript console to debug any erors
4094
  @ if not defined a rotation will be around the first point of an object
4095
  @ to be used before command <a href="#rotate">rotate</a>
18572 bpr 4096
  @ use <a href="#killrotate">killrotate</a> to reset to 'null' <br>(eg. the rotationcenter of the next object(s) will be the first (x;y) coordinate of the object(s))
18552 bpr 4097
  @ all other commands will use this rotation center, unless a <a href="#killrotation">killrotation</a> is given
4098
  @%rotationcenter%size 400,400%xrange -5,10%yrange -5,10%circles green,3,3,4.25%rotationcenter 3,3%opacity 255,80%fpoly yellow,0,0,4,3,2,5%rotate 45%fpoly violet,0,0,4,3,2,5%rotate 90%fpoly lightblue,0,0,4,3,2,5%rotate 135%fpoly blue,0,0,4,3,2,5%rotate 180%fpoly orange,0,0,4,3,2,5%rotate 225%fpoly green,0,0,4,3,2,5%rotate 270%fpoly cyan,0,0,4,3,2,5%rotate 315%fpoly purple,0,0,4,3,2,5%linewidth 3%point 3,3,red%mouse red,22
4099
  @%rotationcenter_slider%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%fillcolor black%strokecolor yellow%rotationcenter 0,0%fontsize 28%slider 0,2*pi,400,30,angle degrees active, rotate...%plot red,5*sin(x)%filled%linewidth 1%opacity 150,50%fillcolor orange%angle 0,0,pi,0,0,blue
4100
  */
4101
          for( i = 0;i < 2; i++ ){
4102
            switch(i){
4103
              case 0: rotationcenter[0] = get_real(infile,0);break; /* x-center */
4104
              case 1: rotationcenter[1] = get_real(infile,1);break; /* y-center */
4105
            }
4106
            string_length = 1 + snprintf(NULL,0,"[%f,%f ]",rotationcenter[0],rotationcenter[1]);
18557 bpr 4107
 
18552 bpr 4108
            rotation_center = my_newmem(string_length);
4109
            snprintf(rotation_center,string_length,"[%f,%f]",rotationcenter[0],rotationcenter[1]);
4110
          }
4111
          break;
4112
        case SIZE:
4113
      /*
18556 bpr 4114
  @ size width,height
4115
  @ set canvas size in pixels
4116
  @ mandatory first command (can only be preceded by keyword <a href="#popup">popup</a>)
4117
  @ if xrange and/or yrange is not given the range will be set to pixels:<br>xrange 0,xsize yrange 0,ysize<br>note: lower left corner is origin (0:0) !!! this in contrast to flydraw
18552 bpr 4118
      */
4119
          found_size_command = 1;
4120
          /* using fabs: however "xsize == int": so "xsize = abs( (int) get_real(infile,0))" would be the idea... */
4121
          xsize = (int)(fabs(round(get_real(infile,0)))); /* just to be sure that sizes > 0 */
4122
          ysize = (int)(fabs(round(get_real(infile,1))));
4123
          /* sometimes we want xrange / yrange to be in pixels...without telling x/y-range */
4124
          xmin = 0;xmax = xsize;
4125
          ymin = 0;ymax = ysize;
11806 schaersvoo 4126
 
4127
/*
4128
 The sequence in which stuff is finally printed is important !!
4129
*/
18552 bpr 4130
          fprintf(stdout,"\n\
4131
          <script>\n\
4132
          /*<![CDATA[*/\n\
4133
          if( typeof(wims_status) === 'undefined' ){ var wims_status = \"$status\";};\
4134
          if( typeof(use_dragdrop_reply) === 'undefined' ){ var use_dragdrop_reply = false;};\
4135
          if( typeof(canvas_scripts) === 'undefined' ){ var canvas_scripts = new Array();};\
4136
          canvas_scripts.push(\"%d\");\n/*]]>*/\n</script>\n\
4137
          ",canvas_root_id);
11806 schaersvoo 4138
 
18552 bpr 4139
          /* style=\"display:block;position:relative;margin-left:auto;margin-right:auto;margin-bottom:4px;\" */
4140
          if( use_tooltip != 2){
4141
            fprintf(stdout,"<!-- canvasdraw div -->\n\
4142
            <div tabindex=\"0\" id=\"canvas_div%d\" style=\"max-width:%dpx;width:%dpx;height:%dpx\" class=\"canvas_wrapper\" oncontextmenu=\"return false;\">\
4143
             <canvas class=\"canvas_placeholder\" width=\"%d\" height=\"%d\"></canvas>\
4144
            </div>\n\
4145
            <!-- tooltip and input placeholder -->\n\
4146
            <div id=\"tooltip_placeholder_div%d\" style=\"text-align:center\">\
4147
             <span id=\"tooltip_placeholder%d\" class=\"tooltip_placeholder\"></span></div>\
4148
            <!-- include actual object code via include file -->\n\
4149
            <script id=\"canvas_script%d\" src=\"%s\" defer></script>\n",canvas_root_id,xsize,xsize,ysize,xsize,ysize,canvas_root_id,canvas_root_id,canvas_root_id,getfile_cmd);
4150
          } else {
11806 schaersvoo 4151
/*
14066 bpr 4152
set canvas_div invisible and do not include placeholder in main html page:
15111 schaersvoo 4153
the js-include will also be in a popup window...to be shown when wims &#36;status = done
11806 schaersvoo 4154
*/
18552 bpr 4155
            fprintf(stdout,"<!-- canvasdraw div invisible -->\n\
4156
            <div tabindex=\"0\" id=\"canvas_div%d\" class=\"canvas_wrapper\" style=\"display:none;max-width:%dpx;width:%dpx;height:%dpx;\">\
4157
             <canvas class=\"canvas_placeholder\" width=\"%d\" height=\"%d\"></canvas>\
4158
            </div>\n\
4159
            <div id=\"tooltip_placeholder_div%d\" style=\"display:none;position:relative;margin-left:auto;margin-right:auto;margin-bottom:4px;\">\
4160
             <span id=\"tooltip_placeholder%d\" class=\"tooltip_placeholder\"></span></div>\
4161
            <!-- include actual object code via include file -->\n\
4162
            <script id=\"canvas_script%d\" src=\"%s\"></script>\n",canvas_root_id,xsize,xsize,ysize,xsize,ysize,canvas_root_id,canvas_root_id,canvas_root_id,getfile_cmd);
4163
          }
11806 schaersvoo 4164
 
14071 bpr 4165
/* these must be global...it is all really very poor javascript:( */
15734 schaersvoo 4166
fprintf(js_include_file,"\n/* begin generated javascript include for canvasdraw version %s */\n\
11806 schaersvoo 4167
\"use strict\";\n\
15111 schaersvoo 4168
/* these variables and functions must be global */\
11806 schaersvoo 4169
var read_dragdrop%d;\
14038 schaersvoo 4170
var read_canvas_images;\
11806 schaersvoo 4171
var read_canvas%d;\
4172
var set_clock;\
4173
var clear_draw_area%d;\
4174
var update_draw_area%d;\
14038 schaersvoo 4175
var place_image_on_canvas;\
11806 schaersvoo 4176
var draw_boxplot;\
4177
var redraw_all%d;\
15111 schaersvoo 4178
var userdraw_primitive;\
4179
var wims_canvas_function%d = function(){\n/* common used stuff */\
4180
var userdraw_x = [];var userdraw_y = [];var userdraw_radius = [];\
11806 schaersvoo 4181
var xsize = %d;\
4182
var ysize = %d;\
4183
var precision = 100;\
4184
var canvas_div = document.getElementById(\"canvas_div%d\");\
4185
var create_canvas%d = function(canvas_type,size_x,size_y){var cnv;if(document.getElementById(\"wims_canvas%d\"+canvas_type)){ cnv = document.getElementById(\"wims_canvas%d\"+canvas_type);}else{try{ cnv = document.createElement(\"canvas\"); }catch(e){alert(\"Your browser does not support HTML5 CANVAS:GET FIREFOX !\");return;};canvas_div.appendChild(cnv);};cnv.width = size_x;cnv.height = size_y;cnv.style.top = 0;cnv.style.left = 0;cnv.style.position = \"absolute\";cnv.id = \"wims_canvas%d\"+canvas_type;return cnv;};\
4186
function findPosX(i){ var obj = i;var curleft = 0;if(obj.offsetParent){while(1){curleft += obj.offsetLeft;if(!obj.offsetParent){break;};obj = obj.offsetParent;};}else{if(obj.x){curleft += obj.x;};};return curleft;};function findPosY(i){var obj = i;var curtop = 0;if(obj.offsetParent){while(1){curtop += obj.offsetTop;if(!obj.offsetParent){break;};obj = obj.offsetParent;};}else{if(obj.y){curtop += obj.y;};};return curtop;};\
18638 bpr 4187
function x2px(x){if(use_xlogscale == 0 ){let res=parseFloat((x-xmin)/(xmax - xmin)*xsize);return (res==xsize)?xsize-1:res;}else{let x_max = Math.log(xmax)/Math.log(xlogbase);let x_min = Math.log(xmin)/Math.log(xlogbase);let x_in = Math.log(x)/Math.log(xlogbase);let res=(x_in-x_min)/(x_max - x_min)*xsize; return (res==xsize)?xsize-1:res;};};\
18606 bpr 4188
function px2x(px){if(use_xlogscale == 0 ){return px*(xmax - xmin)/xsize + xmin;}else{let x_max = Math.log(xmax)/Math.log(xlogbase);let x_min = Math.log(xmin)/Math.log(xlogbase);let x_out = x_min +px*(x_max - x_min)/xsize;return Math.pow(xlogbase,x_out);};};\
4189
function px2y(py){if(use_ylogscale == 0 ){return ymax - py*(ymax - ymin)/ysize;}else{let y_max = Math.log(ymax)/Math.log(ylogbase);let y_min = Math.log(ymin)/Math.log(ylogbase);let y_out = y_max +py*(y_min - y_max)/ysize;return Math.pow(ylogbase,y_out);};};\
18638 bpr 4190
function y2px(y){if(use_ylogscale == 0){let res= parseFloat((ymax-y)/(ymax - ymin)*ysize);return (res==ysize)?ysize-1:res;}else{var y_max = Math.log(ymax)/Math.log(ylogbase);var y_min = Math.log(ymin)/Math.log(ylogbase);var y_in = Math.log(y)/Math.log(ylogbase);return (y_max - y_in)*ysize/(y_max - y_min);};};\
11806 schaersvoo 4191
function scale_x_radius(rx){return rx*xsize/(xmax - xmin);};\
4192
function scale_y_radius(ry){return ry*ysize/(ymax - ymin);};\
4193
function distance(x1,y1,x2,y2){return Math.sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) );};\
4194
function distance_to_line (r,q,x,y){var c = (y) - (-1/r)*(x);var xs = r*(c - q)/(r*r+1);var ys = (r)*(xs)+(q);return parseInt(Math.sqrt( (xs-x)*(xs-x) + (ys-y)*(ys-y) ));};\
4195
function move(obj,dx,dy){for(var p = 0 ; p < obj.x.length; p++){obj.x[p] = obj.x[p] + dx;obj.y[p] = obj.y[p] + dy;};return obj;};\
15111 schaersvoo 4196
var snap_x = 1;var snap_y = 1;\
11806 schaersvoo 4197
function snap_to_x(x){return x2px(snap_x*(Math.round((px2x(x))/snap_x)));};\
11890 schaersvoo 4198
function snap_to_y(y){return y2px(snap_y*(Math.round((px2y(y))/snap_y)));};\
15111 schaersvoo 4199
function multisnap_check(x,y,snap){switch(snap){case 1:return [snap_to_x(x),snap_to_y(y)];break;case 2:return [snap_to_x(x),y];break;case 3:return [x,snap_to_y(y)];break;case 4:return snap_to_points(x,y);break;case 5: return snap_to_fun(x,y);break;default: return [x,y];break;};};\
11806 schaersvoo 4200
var xlogbase = 10;\
4201
var ylogbase = 10;\
4202
var use_xlogscale = 0;\
4203
var use_ylogscale = 0;\
11891 schaersvoo 4204
var x_strings = {};var x_strings_up = [];\
11806 schaersvoo 4205
var y_strings = null;\
4206
var use_jsmath = 0;\
4207
var xstart = 0;\
4208
var ystart = 0;\
4209
var unit_x=\" \";\
4210
var unit_y=\" \";\
15111 schaersvoo 4211
var dragdrop_reply = [];\
15734 schaersvoo 4212
var external_canvas = create_canvas%d(%d,xsize,ysize);",VERSION,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,xsize,ysize,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,EXTERNAL_IMAGE_CANVAS);
15111 schaersvoo 4213
/* var xstart,ystart are normally 0 : in case of sgraph they have the 'jump' in the graph */
18552 bpr 4214
          break;
4215
        case SEGMENT:
4216
  /*
4217
  @ segment x1,y1,x2,y2,color
4218
  @ alternative: seg
4219
  @ draw a line segment between points (x1:y1)--(x2:y2) in color ''color``
4220
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
4221
  @%segment_onclick%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%onclick%segment 1,1,-9,3,green
4222
  @%segment_drag_y%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%drag y%segment 1,1,-9,3,green
4223
  */
4224
          for(i=0;i<5;i++) {
4225
            switch(i){
4226
              case 0: double_data[0]= get_real(infile,0);break; /* x1-values */
4227
              case 1: double_data[1]= get_real(infile,0);break; /* y1-values */
4228
              case 2: double_data[2]= get_real(infile,0);break; /* x2-values */
4229
              case 3: double_data[3]= get_real(infile,0);break; /* y2-values */
4230
              case 4: stroke_color=get_color(infile,1);/* name or hex color */
4231
                if(use_rotate == TRUE ){rotate(4,angle,rotationcenter,2);}
4232
                if(use_affine == TRUE ){ transform(4,2);}
4233
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
4234
                decimals = find_number_of_digits(precision);
18557 bpr 4235
                tmp_buffer=my_newmem(MAX_BUFFER);
4236
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,double_data[1],decimals,double_data[3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 4237
                add_to_buffer(tmp_buffer);
4238
                if(onclick != 0){object_cnt++;}
4239
                /* object_cnt++; */
4240
                reset();
4241
                break;
4242
              default: break;
4243
            }
4244
          }
4245
          dragstuff[4] = 1;
4246
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
4247
          break;
4248
        case SEGMENTS:
4249
  /*
4250
  @ segments color,x1,y1,x2,y2,...,x_n,y_n
4251
  @ alternative: segs
4252
  @ draw multiple segments between points (x1:y1)--(x2:y2).....and... (x_n-1:y_n-1)--(x_n:y_n) in color ''color``
4253
  @ use command ''linewidth int`` to adjust size
4254
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually (!)
4255
  @%segments_onclick%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%onclick%segments green,1,1,3,3,0,0,-3,3,1,1,4,-1,-5,5,-3,-1
4256
  @%segments_drag_y%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%drag y%segments green,1,1,3,3,0,0,-3,3,1,1,4,-1,-5,5,-3,-1
4257
  */
4258
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
4259
          fill_color = stroke_color;
4260
          i=0;
4261
          while( ! done ){     /* get next item until EOL*/
4262
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
4263
            if(i%2 == 0 ){
4264
              double_data[i] = get_real(infile,0); /* x */
4265
            }
4266
            else {
4267
              double_data[i] = get_real(infile,1); /* y */
4268
            }
4269
            i++;
4270
          }
4271
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
4272
          if(use_affine == TRUE ){ transform(i-1,2);}
4273
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
4274
          decimals = find_number_of_digits(precision);
4275
          for(c = 0 ; c < i-1 ; c = c+4){
18557 bpr 4276
            tmp_buffer=my_newmem(MAX_BUFFER);
4277
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 4278
            add_to_buffer(tmp_buffer);
4279
            if(onclick != 0){object_cnt++;}
4280
    /* object_cnt++;*/
4281
          }
4282
          reset();
4283
          dragstuff[4] = 1;
4284
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
4285
          break;
4286
        case SETLIMITS:
4287
  /*
18556 bpr 4288
  @ setlimits
4289
  @ keyword: if set, it will produce 4 inputfields for ''xmin,xmax,ymin,ymax`` and an ''ok`` button
4290
  @ may be used for inputfield based zooming / panning
4291
  @ may be styled using command <a href="#css">css</a>
4292
  @ use commands <a href="#xlabel">xlabel / ylabel</a> to change text from xmin to ''xlabel`` etc
4293
  @ note: the input value will not be checked on validity
4294
  @%setlimits%size 400,400%xrange -10,10%yrange -10,10%precision 1%xlabel T%ylabel H%axis%axisnumbering%grid 2,2,grey,2,2,5,grey%precision 100%multistrokecolors red,green,blue,orange%multilinewidth 1,1,2,2%multistrokeopacity 0.6,0.7,0.8,0.9%jsplot red,1/x,-1,x,1/(x-3),1/(x+3)%setlimits
18552 bpr 4295
  */
4296
          js_function[JS_SAFE_EVAL] = 1;
4297
          js_function[JSPLOT_AND_ZOOM] = 1;
4298
          add_setlimits(font_size,css_class);
4299
          done = TRUE;
4300
          break;
4301
        case SETPIXEL:
4302
  /*
4303
  @ setpixel x,y,color
4304
  @ A rectangular "point" with diameter 1 pixel centered at (x:y) in xrange / yrange
4305
  @ pixels can <b>not</b> be dragged or clicked
4306
  @ "pixelsize = 1" may be changed by command <code>pixelsize int</code>
4307
  @%setpixel%size 400,400%xrange -10,10%yrange -10,10%setpixel 1,1,red%pixelsize 2%setpixel 2,2,green%pixelsize 3%setpixel 3,3,blue%
4308
  */
4309
          js_function[DRAW_PIXELS] = 1;
4310
          for(i=0;i<3;i++){
4311
            switch(i){
4312
              case 0: double_data[0] = get_real(infile,0); break; /* x */
4313
              case 1: double_data[1] = get_real(infile,0); break; /* y */
4314
              case 2: stroke_color = get_color(infile,1);
18557 bpr 4315
                tmp_buffer=my_newmem(MAX_BUFFER);
4316
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_setpixel([%f],[%f],\"%s\",%.2f,%d);\n",double_data[0],double_data[1],stroke_color,stroke_opacity,pixelsize));
18552 bpr 4317
                add_to_buffer(tmp_buffer);
4318
                break;
4319
              default:break;
4320
            }
4321
          }
4322
          reset();
4323
          break;
4324
        case SLIDER:
4325
  /*
4326
  @ slider start_value,end_value,width px,height px,type,label
4327
  @ type may be: ''x,y,angle``
4328
  @ if a slider value display is desired, use for argument ''type``: ''x display``, ''y display``, ''angle radian``, ''angle degree``
4329
  @ is the slider is used for animation, add keyword ''anim`` or ''animate`` to ''type``; for now only one animated slider may be used...
4330
  @ if a unit (or something like that...) for x/y-value display is needed, use commands ''xunit`` and / or ''yunit``
4331
  @ if the translation should be performed using a function, use for type: ''x function``, ''y function``<br>use commands ''sliderfunction_x`` and/or ''sliderfunction_y`` before the slider command to define the functions. Example:<code>sliderfunction_x x^2<br>sliderfunction_y y^2<br>slider -5,5,100,100,xy function,Some_Text<br>...some stuff to slide<br>killslider<br>sliderfunction_x x^2-2<br>slider -15,15,100,10,x function,Some_Other_Text<br>...more stuff to slide<br>killslider... etc</code>
4332
  @ use command ''slider`` before draggable/clickable objects.
4333
  @ drag and drop may be combined with rotation slider<br>for example an arrow rotated by a slider may be placed anywhere (drag&drop)<br><code>size 300,300<br>xrange -5,5<br>yrange -5,5<br>grid 1,1,grey<br>linewidth 3<br>drag xy<br>fillcolor orange<br>strokecolor blue<br>slider 0,2*pi,250,30,angle degrees,Rotate arrow<br>arrow 2,2,5,5,8,red</code><br>note: except a combination 'drag' and 'slider' for command 'latex, katex, mathml, html, obabel'
4334
  @ no slider for a math function, these can be traced using command ''trace_jscurve some_function_in_x``
4335
  @ a slider will affect all draggable objects after the ''slider`` command...<br>and can be used to group translate / rotate several objects...<br>until a next ''slider`` or keyword ''killslider``
4336
  @ amount of sliders is not limited.
4337
  @ a slider can not be set ''snaptogrid`` or other ''snapto*`` : you may always use 'drag xy' in combination with the slider objects
4338
  @ <code>javascript:read_dragdrop();</code> will return an array with ''object_number:slider_value``
4339
  @ every draggable object may have its own slider (no limit in amount of sliders)
4340
  @ label: some slider text. <br>Note: on <a target='new' href='https://katex.org'>KaTeX</a> enabled wims, TeX produced by wims command ''mathmlmath``, is allowed.
4341
  @ use fillcolor for slider controlkey
4342
  @ use strokecolor for slider bar
4343
  @ use fontfamily / fontcolor to set used fonts
4344
  @ use opacity (only fill opacity will be used) to set transparency
4345
  @ the slider canvas will be added to the ''tooltip div``: so incompatible with command tooltip ; setlimits etc
18655 schaersvoo 4346
  @%slider_x_y_angle%%size 300,300%xrange -5,5%yrange -5,5%grid 1,1,grey%linewidth 3%fillcolor orange%strokecolor blue%slider 0,2*pi,300,30,angle degrees,Rotate arrow%arrow 0,0,4.5,0,8,red%killslider%opacity 200,100%slider -2,2,300,30,x ,move blue rectangle%frect -4,4,1,-1,blue%killslider%linewidth 2%slider -2,2,300,30,y,move green rectangle%frect -4,4,1,-1,green
4347
  @%slider%%size 300,300%xrange -6,6%yrange -6,6%grid 1,1,grey%linewidth 1%slider 0,2*pi,300,28,angle degree, name%fillcolor lightgreen%opacity 255,30%ftriangle 2,2,-2,2,0,0,red%ftriangle -2,2,-2,-2,0,0,blue%ftriangle -2,-2,2,-2,0,0,green%ftriangle 2,-2,2,2,0,0,orange%rotationcenter 0,0%frect -2,2,2,-2,black
4348
  @%slider_animate%%size 300,300%xrange -6,6%yrange -6,6%grid 1,1,grey%linewidth 1%slider 0,2*pi,300,28,angle anim , name%fillcolor lightgreen%opacity 255,30%ftriangle 2,2,-2,2,0,0,red%ftriangle -2,2,-2,-2,0,0,blue%ftriangle -2,-2,2,-2,0,0,green%ftriangle 2,-2,2,2,0,0,orange%rotationcenter 0,0%frect -2,2,2,-2,black
4349
  @%slider_html_image%%size 400,400%xrange -6,6%yrange -6,6%bgcolor white%grid 1,1,grey%linewidth 1%slider 0,2*pi,300,28,angle degree,%centered%html 0,0,<img src="gifs/domains/sciences/flasks.svg" width="100px" height="100px">
18552 bpr 4350
  */
4351
          js_function[INTERACTIVE] = 1;
4352
          int_data[2] = 0; /* --> show_display = 0; */
4353
          for(i=0; i<6 ; i++){
4354
            switch(i){
4355
              case 0: double_data[0] = get_real(infile,0);break; /* start value */
4356
              case 1: double_data[1] = get_real(infile,0);break; /* end value */
4357
              case 2: int_data[0] = (int)(get_real(infile,0));break; /* width */
4358
              case 3: int_data[1] = (int)(get_real(infile,0));break; /* height */
4359
              case 4: temp = get_string_argument(infile,0); /* type: x,y,angle */
4360
                if( strstr(temp,"displ")!=0 ||  strstr(temp,"deg")!=0 || strstr(temp,"rad")!=0 ){int_data[5] = 1; }else{int_data[5] = 0;}
4361
                if(strstr(temp,"anim")!= 0){int_data[3] = 1;}else{int_data[3] = 0;}
4362
                if(strstr(temp,"angle")!= 0){slider_type="R";if( strstr(temp,"rad")!= 0){int_data[2] = 3;}if( strstr(temp,"deg")!= 0){int_data[2] = 4;}}
4363
                else
4364
                  if(strstr(temp,"xy") != 0){slider_type = "XY";if( strstr(temp,"disp")!= 0){int_data[2] = 5;}}
4365
                    else
4366
                      if(strstr(temp,"x") != 0){slider_type = "X";if( strstr(temp,"disp")!= 0){int_data[2] = 1;}}
4367
                      else
4368
                        if(strstr(temp,"y") != 0){slider_type = "Y";if( strstr(temp,"disp")!= 0){int_data[2] = 2;}}
4369
                          else
4370
                            canvas_error("slider can be of type: x,y,angle,fun_x:fun_y");
4371
                  break;
4372
                case 5: temp = get_string_argument(infile,1); if( strstr(temp,"\"") != 0 ){ temp = str_replace(temp,"\""," ");}
4373
        /* slider label : in case of latex/mathmlmath we need to remove the extra " */
4374
              break;
4375
            }
4376
          }
4377
          if(use_slider == -1 ){ /* add once */
4378
            add_slider(int_data[3]);
4379
            if(int_data[5] == 1 ){add_slider_display(precision,font_size,font_color,stroke_opacity);}
4380
          }
4381
          use_slider++;
18656 schaersvoo 4382
          if(int_data[3] == 0){
18557 bpr 4383
            tmp_buffer=my_newmem(MAX_BUFFER);
18570 bpr 4384
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"slider%d = new slider(\"%s\",\"%s\",%d,%d,%d,%d,\"%s\",\"%s\",[%f,%f],%f,%f,'%s',%d);\n",use_slider,slider_type,temp,use_slider,int_data[0],int_data[1],line_width,fill_color,stroke_color,fill_opacity,stroke_opacity,double_data[0],double_data[1],font_family,int_data[2]));
18552 bpr 4385
          }else{
18557 bpr 4386
 
18552 bpr 4387
            add_slider(int_data[3]);/* use only once !! */
18557 bpr 4388
            tmp_buffer=my_newmem(MAX_BUFFER);
18570 bpr 4389
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"slider%d = new animslider(\"%s\",\"%s\",%d,%d,%d,%d,\"%s\",\"%s\",[%f,%f],%f,%f,'%s',%d);\n",use_slider,slider_type,temp,use_slider,int_data[0],int_data[1],line_width,fill_color,stroke_color,fill_opacity,stroke_opacity,double_data[0],double_data[1],font_family,int_data[2]));
18552 bpr 4390
          }
4391
          add_to_buffer(tmp_buffer);
4392
          fprintf(js_include_file,"var slider%d;",use_slider);
4393
          use_dragstuff = 2;
4394
//      dragstuff[22] = 1; /* dragstuff switch no 22 is a slider...*/
18656 schaersvoo 4395
          js_function[INTERACTIVE] = 1; /* no need to click on object to use slider... */
18552 bpr 4396
      //js_function[JS_ROTATE_MOUSE] = 1;
4397
          c = 0;
4398
          for(i=last_slider;i<=use_slider;i++){
4399
            int_data[c] = i; c++;
4400
          }
4401
          my_sliders = data2js_array(int_data,use_slider - last_slider+1);
4402
          break;
4403
        case SGRAPH:
4404
  /*
18556 bpr 4405
  @ sgraph xstart,ystart,xmajor,ymajor,xminor,yminor,majorgrid_color,minorgrid_color
4406
  @ primitive implementation of a ''broken scale`` graph...
4407
  @ not very versatile: only usable in combination with userdraw <br>eg no other objects will obey this "coordinate system"<br>if you want to place an object into this coordinate system, be aware that 10% or 20% of xsize and/or ysize is ''lost``.<br>Use these "formulas" to recalculate the virtual coordinates:<br>factor=0.8 in case xstart != xmin (or ystart != ymin)<br>factor=0.9 in case xstart = xmin (or ystart = ymin)<br>px_x_point = ((factor*xsize)/(xmax - xstart))*(x_point - xmax)+xsize<br>x_recalculated = px*(xmax - xmin)/xsize + $xmin<br>px_y_point = -1*factor*y_point*ysize/(ymax - ystart) + ymax*factor*ysize/(ymax - ystart)<br>y_recalculated = ymax - py*(ymax - ymin)/ysize<br>
4408
  @%sgraph%size 400,400%xrange 0,10000%yrange 0,100%sgraph 9000,50,100,10,4,4,grey,blue%userinput_xy%linewidth 2%userdraw segments,red%precision 0%mouse blue,22
18552 bpr 4409
  */
4410
            js_function[DRAW_SGRAPH] = 1;
4411
            for(i = 0 ; i < 8 ;i++){
4412
              switch(i){
4413
                case 0:double_data[0] = get_real(infile,0);break;
4414
                case 1:double_data[1] = get_real(infile,0);break;
4415
                case 2:double_data[2] = get_real(infile,0);break;
4416
                case 3:double_data[3] = get_real(infile,0);break;
4417
                case 4:int_data[0] = (int)(get_real(infile,0));break;
4418
                case 5:int_data[1] = (int)(get_real(infile,0));break;
4419
                case 6:stroke_color = get_color(infile,0);break;
4420
                case 7:font_color = get_color(infile,1);
18557 bpr 4421
                tmp_buffer=my_newmem(MAX_BUFFER);
4422
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "xstart = %f;\n ystart = %f;\ndraw_sgraph(%d,%d,%f,%f,%d,%d,\"%s\",\"%s\",\"%s\",%f,%d);\n", double_data[0],double_data[1],GRID_CANVAS,precision,double_data[2],double_data[3],int_data[0],int_data[1],stroke_color,font_color,font_family,stroke_opacity,font_size));
18552 bpr 4423
                add_to_buffer(tmp_buffer);
4424
                break;
4425
                default:break;
4426
              }
4427
            }
4428
      /* sgraph(canvas_type,precision,xmajor,ymajor,xminor,yminor,majorcolor,minorcolor,fontfamily,opacity)*/
4429
          break;
4430
        case SNAPTOFUNCTION:
4431
  /*
4432
  @ snaptofunction some_function_in_x,some_funtion_in_y
4433
  @ alternative: snaptofun
4434
  @ the next object will snap to the calculated values
4435
  @ note: snaptofun is probably not really useful feature...
4436
  @ if you want only modification of y-values,just use: <code>snaptofunction x,5*sin(1/y)</code>
4437
  @ if you want only modification of x-values,just use: <code>snaptofunction 5*sin(1/x),y</code>
4438
  @ for now only one instance of ''snaptofunction`` is allowed
4439
  @ use rawmath on your functions: no validity checking is done by wims !
4440
  @ note: switching x and y coordinates? <code>snaptofunction y,x</code>
4441
  @%snaptofunction_1%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 100%snaptofunction x,5*sin(x)%linewidth 3%crosshairsize 6%userdraw crosshairs,red%linewidth 2%curve blue,5*sin(x)%xunit = x-value%display x,blue,22
4442
  @%snaptofunction_2%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 100%snaptofunction y^2-9,y%#snaptofunction y^2-9,abs(y)%linewidth 3%crosshairsize 6%userdraw crosshairs,red%linewidth 2%curve blue,sqrt(x+9)%curve blue,-1*sqrt(x+9)%yunit = y-value%display y,blue,22
4443
  */
4444
          temp = get_string_argument(infile,0);
4445
          use_snap = 2;
4446
          use_snap = 5;
4447
          js_function[JS_MATH] = 1;
4448
          fprintf(js_include_file,"var snap_fun = {x:to_js_math('%s'),y:to_js_math('%s')};function snap_to_fun(px,py){ var x = px2x(px); var y = px2y(py); return [ x2px(eval(snap_fun.x)) , y2px(eval(snap_fun.y)) ];};",temp,get_string(infile,1));
4449
          break;
4450
        case SNAPTOPOINTS:
4451
  /*
4452
  @ snaptopoints x1,y1,x2,y2,x3,y3....
4453
  @ a userdraw object will snap to these points.
18572 bpr 4454
  @ the array size (e.g. the number of points) of command ''snaptopoints`` is limited by constant MAX_INT (canvasdraw.h)<br>this command may be repeated multiple times (no limit) to add points
18552 bpr 4455
  @ a draggable object (use command ''drag x|y|xy``) will snap to the closed of these points when dragged (mouseup)
4456
  @ other options: use keyword ''snaptogrid``, ''xsnaptogrid`` or ''ysnaptogrid``
18616 bpr 4457
  @%snaptopoints_1%size 400,400%xrange -5,5%yrange -5,5%snaptopoints -1,-3,-1,-2,-1,0,-1,1,-1,2,-1,3,1,-3,1,-2,1,-1,1,0,1,1,1,2,1,3%linewidth 2%points red,-1,-3,-1,-2,-1,0,-1,1,-1,2,-1,3,1,-3,1,-2,1,-1,1,0,1,1,1,2,1,3%userdraw arrows,red
4458
  @%snaptopoints_2%size 400,400%xrange -5,5%yrange -5,5%snaptopoints -1,-3,-1,-2,-1,0,-1,1,-1,2,-1,3,1,-3,1,-2,1,-1,1,0,1,1,1,2,1,3%linewidth 3%%points blue,-1,-3,-1,-2,-1,0,-1,1,-1,2,-1,3,1,-3,1,-2,1,-1,1,0,1,1,1,2,1,3%drag xy%ftriangle -4,0,-2,3,0,0,red
18552 bpr 4459
  */
4460
          i = 0;
4461
          while( ! done ){     /* get next item until EOL*/
4462
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
4463
            if(i%2 == 0 ){
4464
              double_data[i] = get_real(infile,0); /* x */
4465
            }
4466
            else {
4467
              double_data[i] = get_real(infile,1); /* y */
4468
            }
4469
            i++;
4470
          }
4471
          decimals = find_number_of_digits(precision);
4472
      /* NEED AN EXTRA COUNTER VARIABLE FOR MORE THAN 2 CALLS */
4473
          fprintf(js_include_file,"if( temp_push_array === 'undefined' ){var temp_push_array;};if( points_to_snap_on === 'undefined' ){var points_to_snap_on;};var temp_push_array = [%s];\n",double_xy2js_array(double_data,i,decimals));
4474
          if( snap_to_points_cnt == 0 ){
4475
            fprintf(js_include_file,"points_to_snap_on = temp_push_array;function find_min_diff(x,y,X,Y){var diff = 100000000;var chk;var idx = 0;var p = 0;while(X[p] != null){chk = distance(x,y,X[p],Y[p]);if( chk  < diff ){ diff = chk; idx = p;};p++;};return idx;};function snap_to_points(x,y){x = px2x(x); y = px2y(y);var xpoints = points_to_snap_on[0];var ypoints = points_to_snap_on[1];var idx = find_min_diff(x,y,xpoints,ypoints);x = xpoints[idx];y = ypoints[idx];return [x2px(x),y2px(y)];};");
4476
          }else{
4477
            fprintf(js_include_file,"points_to_snap_on[0].push.apply(points_to_snap_on[0],temp_push_array[0]);points_to_snap_on[1].push.apply(points_to_snap_on[1],temp_push_array[1]);");
4478
          }
4479
          snap_to_points_cnt = 1; /* do not repeat including the js-functions...just once*/
4480
          use_snap = 4;
4481
          break;
4482
        case SNAPTOGRID:
4483
  /*
18556 bpr 4484
  @ snaptogrid
4485
  @ keyword (no arguments required)
4486
  @ a draggable object (use command ''drag x|y|xy``) will snap to the given grid when dragged (mouseup)
4487
  @ in case of userdraw the drawn points will snap to xmajor / ymajor grid
4488
  @ if no grid is defined, points will snap to every integer xrange/yrange value. (eg snap_x=1,snap_y=1)
4489
  @ if you do not want a visible grid, but you only want a ''snaptogrid`` with some value...define this grid with opacity 0.
4490
  @ if xminor / yminor is defined,(use keyword ''axis`` to activate the minor steps) the drawing will snap to xminor and yminor<br>use only even dividers in x/y-minor...for example <code>snaptogrid<br>axis<br>grid 2,1,grey,4,4,7,red</code> will snap on x=0, x=0.5, x=1, x=1.5 .... will snap on y=0, y=0.25 y=0.5 y=0.75 ...
4491
  @%snaptogrid_1%size 400,400%xrange -5,5%yrange -5,5%axis%axisnumbering%precision 1%grid 1,1,grey,2,2,6,grey%linewidth 2%snaptogrid%userdraw crosshairs,blue%mouse red,22
4492
  @%snaptogrid_2%size 400,400%xrange -5,5%yrange -5,5%axis%axisnumbering%precision 1%grid 1,1,grey,4,1,6,grey%linewidth 1%snaptogrid%userdraw crosshairs,blue%mouse red,22
18552 bpr 4493
  */
4494
          use_snap = 1;
4495
          break;
4496
        case SQUARE:
4497
  /*
4498
  @ square x,y,side (px),color
4499
  @ draw a square with left top corner (x:y) with side ''side`` in color 'color'
4500
  @ use command <code>fsquare x,y,side,color</code> for a filled square
4501
  @ use command/keyword <a href='#filled'>filled</a> before command <code>square x,y,side,color</code>
4502
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
4503
  @%square%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%filled%fillcolor blue%square 0,0,120,green
4504
  */
4505
          for(i=0;i<4;i++){
4506
            switch(i){
4507
            case 0:double_data[0] = get_real(infile,0);break; /* x1-values */
4508
            case 1:double_data[1] = get_real(infile,0);break; /* y1-values */
4509
            case 2:double_data[2] = get_real(infile,0);break; /* width in px */
4510
            case 3:stroke_color = get_color(infile,1);/* name or hex color */
4511
              decimals = find_number_of_digits(precision);
4512
              double_data[3] = double_data[0] + (xmax - xmin)*double_data[2]/xsize;
4513
              double_data[4] = double_data[1] + -1*(ymax - ymin)*double_data[2]/ysize;
4514
              if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
18557 bpr 4515
              tmp_buffer=my_newmem(MAX_BUFFER);
4516
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,1,[%.*f,%.*f,%.*f,%.*f],[%.*f,%.*f,%.*f,%.*f],[%d],[%d],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[3],decimals,double_data[3],decimals,double_data[0],decimals,double_data[1],decimals,double_data[1],decimals,double_data[4],decimals,double_data[4],line_width,line_width,line_width,stroke_color,stroke_opacity,stroke_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 4517
              add_to_buffer(tmp_buffer);
4518
              if(onclick != 0){object_cnt++;}/* object_cnt++; */
4519
              reset();break;
4520
            default: break;
4521
            }
4522
          }
4523
          dragstuff[1] = 1;
4524
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
4525
          break;
4526
        case STATUS:
4527
  /*
4528
  @ status
4529
  @ keyword
4530
  @ alernative: nostatus
4531
  @ used to override the effects of ''status=done`` in wims (answer.phtml)
4532
  @ affects ''readonly`` in inputfields / textareas in canvasimage and all userdraw based commands
4533
  @ e.g.: if keyword ''status`` is set, the pupil will be able to modify the canvas when the ''wims &#36;status variable`` is set to ''done``
4534
  */
11806 schaersvoo 4535
 
18552 bpr 4536
          fprintf(js_include_file,"\nwims_status=\"waiting\";\n");
4537
          break;
4538
        case STRING:
4539
  /*
18556 bpr 4540
  @ string color,x,y,the text string
4541
  @ may be set ''onclick`` or ''drag xy``
4542
  @ note: when set ''onclick``, use an extra command ''fontsize`` (default: fontsize=12) to adjust the size of the clicked text-string<br>note: a clicked text string will be hardcoded : fontsize+10 in the font family courier
18572 bpr 4543
  @ unicode supported: <code>string red,0,0,\\u2232</code><br> See <a target='new' href='https://en.wikipedia.org/wiki/Mathematical_operators_and_symbols_in_Unicode'>https://en.wikipedia.org/wiki/Mathematical_operators_and_symbols_in_Unicode</a><br> See <a  target='new' href='https://en.wikipedia.org/wiki/Greek_script_in_Unicode'>https://en.wikipedia.org/wiki/Greek_script_in_Unicode</a>
18556 bpr 4544
  @ use a command like <code>fontfamily italic 24px Arial</code> to set fonts on browser that support font change
4545
  @ super / sub script is supported, using '<b>_</b>' and '<b>^</b>' <br>The font family for the sub/sup string will be Helvetica e.g. your font family settings will be ignored <br>to force end the subscript/supscript, use an extra space...see example:
4546
  @%string_sup_sub%size 400,400%xrange -6,6%yrange -6,6%fontfamily 22px Arial%# you can use a single space for separation in formula...%# use double space to create new word%string blue,-5,3,H_3O^+ + OH^-  \\u2192 2H_2O%# you can use a single space for separation in formula...%string red,-5,-3,H_3 O^+ + OH^\\u2212  \\u2192 2H_2 O%
4547
  @%string%size 400,400%xrange -10,10%yrange -10,10%fontfamily 14px Arial%crosshair -3,-3,red%crosshair 3,3,blue%string red,-3,-3,Hello World%fontfamily Italic 18px Arial%string red,3,3,Hello World%fontfamily 22pt STIX%string black,-10,8,\\u03B1 \\u03B2 \\u03B3 \\u03B4 \\u03B5 \\u03B6 \\u03B7 \\u03B8 \\u03B9 \\u03BA \\u03BB \\u03BC \\u03BD \\u03BE \\u03BF
18552 bpr 4548
  */
4549
          if( use_rotate == TRUE  ){js_function[JS_ROTATE_MOUSE] = 1; }
4550
          dragstuff[14] = 1;
4551
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
4552
          for(i=0;i<5;i++){
4553
            switch(i){
4554
              case 0: stroke_color = get_color(infile,0);break;/* name or hex color */
4555
              case 1: double_data[0] = get_real(infile,0);break; /* x in xrange*/
4556
              case 2: double_data[1] = get_real(infile,0);break; /* y in yrange*/
4557
              case 3: decimals = find_number_of_digits(precision);
4558
                if(use_affine == TRUE ){ transform(2,2);}
4559
        /* rotate is done by HTML5/CANVAS context rotation */
4560
                temp = get_string_argument(infile,1);
4561
                if(strstr(temp,"_") != NULL || strstr(temp,"^") != NULL){js_function[DRAW_SUBSUP] = 1;}
4562
                decimals = find_number_of_digits(precision);
4563
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
18557 bpr 4564
                tmp_buffer=my_newmem(MAX_BUFFER);
4565
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,14,[%.*f],[%.*f],[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[1],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,0,0,0,use_rotate,angle,temp,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 4566
                add_to_buffer(tmp_buffer);
4567
                if(onclick != 0){object_cnt++;}
4568
      //onclick = 0;
4569
      //use_offset = 0;
4570
                reset();
4571
                break;
4572
              default:break;
4573
            }
4574
          }
4575
          break;
4576
        case STRINGUP:
4577
  /*
18556 bpr 4578
  @ stringup color,x,y,rotation_degrees,the text string
4579
  @ may be set ''onclick`` or ''drag xy``
4580
  @ note: when set ''onclick``, use an extra command ''fontsize`` (default: fontsize=12) to adjust the size of the clicked text-string<br>note: a clicked text string will be hardcoded : fontsize+10 in the font family courier
4581
  @ unicode supported: <code>stringup red,0,0,45,\\u2232</code>
4582
  @ use a command like <code>fontfamily bold 34px Courier</code> to set fonts on browser that support font change
4583
  @ you could use keyword <a href='#yoffset'>yoffset</a> to -sometimes- do a small correction of text placement under/above a point (e.g. text &amp; point have thesame coordinates)
18572 bpr 4584
  @ note: no need to ''killrotate`` after ''stringup``<br><code>onclick<br>rotate 45<br>string red,0,0,AAAAAA<br>killrotate<br>string red,4,4,BBBBBB</code><br>is identical with:<br><code>onclick<br>stringup red,0,0,45,AAAAAA<br>string red,4,4,BBBBBB</code>
18556 bpr 4585
  @ super / sub script is supported, using '<b>_</b>' and '<b>^</b>' <br>to end the subscript/supscript, use an extra space...see example:
4586
  @%stringup_sub_sup%size 400,400%xrange -6,6%yrange -6,6%fontfamily 22px Arial%# use single space for separation in formula...%# use double space to create new word%stringup red,-5,0,45,H_3 O^+ + OH^\\u2212  \\u2192 2H_2 O%
4587
  @%stringup%size 400,400%xrange -10,10%yrange -10,10%fontsize 24%fontfamily 14px Arial%crosshair -3,0,red%crosshair 3,0,blue%onclick%stringup red,-3,0,-90,Hello World%drag xy%stringup red,-3,0,-45,Hello World%stringup red,-3,0,45,Hello World%stringup red,-3,0,90,Hello World%stringup blue,3,0,-90,Hello World%stringup blue,3,0,-45,Hello World%stringup blue,3,0,45,Hello World%stringup blue,3,0,90,Hello World
11806 schaersvoo 4588
 
18552 bpr 4589
  */
4590
      /* html5 canvas rotation is only used for text objects  */
4591
          use_rotate = TRUE ;
4592
          dragstuff[14] = 1;
4593
          js_function[JS_ROTATE_MOUSE] = 1;
4594
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
10953 bpr 4595
 
18552 bpr 4596
          for(i=0;i<6;i++){
4597
            switch(i){
4598
              case 0: stroke_color = get_color(infile,0);break;/* name or hex color */
4599
              case 1: double_data[0] = get_real(infile,0);break; /* x */
4600
              case 2: double_data[1] = get_real(infile,0);break; /* y */
4601
              case 3: angle = get_real(infile,0);break;/* rotation */
4602
              case 4: decimals = find_number_of_digits(precision);
4603
                temp = get_string_argument(infile,1);
4604
                if(strstr(temp,"_") != NULL || strstr(temp,"^") != NULL){js_function[DRAW_SUBSUP] = 1;}
4605
                decimals = find_number_of_digits(precision);
4606
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
18557 bpr 4607
                tmp_buffer=my_newmem(MAX_BUFFER);
4608
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,14,[%.*f],[%.*f],[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[1],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,0,0,0,use_rotate,angle,temp,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 4609
                add_to_buffer(tmp_buffer);
4610
                if(onclick != 0){object_cnt++;}
4611
                //onclick = 0;
4612
                //use_offset = 0;
4613
                reset();
4614
                break;
4615
              default:break;
4616
            }
4617
          }
4618
          use_rotate = FALSE;
4619
          break;
4620
        case STYLE:
4621
  /*
18556 bpr 4622
  @ highlight color,opacity,linewidth
4623
  @ NOT IMPLEMENTED
4624
  @ use command ''onclick``: when the object receives a userclick it will increase its linewidth
18552 bpr 4625
  */
4626
         break;
4627
        case STROKECOLOR:
4628
  /*
4629
  @ strokecolor colorname or #hex
4630
  @ to be used for commands that do not supply a color argument (like command ''linegraph``)
4631
  */
4632
          stroke_color = get_color(infile,1);
4633
          break;
4634
        case FLY_TEXT:
4635
  /*
4636
  @ text fontcolor,x,y,font,text_string
4637
  @ font may be described by keywords: giant,huge,normal,small,tiny
4638
  @ use command ''fontsize`` to increase base fontsize for these keywords
4639
  @ may be set ''onclick`` or ''drag xy``
4640
  @ backwards compatible with flydraw
4641
  @ unicode supported: text red,0,0,huge,\\u2232
4642
  @ special: use '_' and '^' to imitate html sup/sub, like H_3O^+ + OH^\\u22i2  \\u2192 2H_2 O
4643
  @ much better to use command <a href='#string'>string</a> combined with <a href='#fontfamily'>fontfamily</a> for a more fine grained control over html5 canvas text element
4644
  @ super / sub script is supported, using '<b>_</b>' and '<b>^</b>' <br>to end the subscript/supscript, use an extra space...see <a href='#string'>string </a> command
4645
  @ Avoid mixing old flydraw commands ''text``, ''textup`` with new canvasdraw commands ''string``, ''stringup``. If the fontfamily was set completely like <code>fontfamily italic 24px Arial</code>. In that case reset ''fontfamily`` to something lke ''fontfamily Arial`` before the old flydraw commands.
4646
  @%text%size 400,400%xrange -10,10%yrange -10,10%fontsize 14%onclick%drag xy%text green,-4,-4,small,Hello World%drag xy%text red,-4,-2,large,Hello World%drag xy%text blue,-4,0,huge,Hello World%drag xy%text green,-4,3,giant,Hello World%drag xy
4647
  */
4648
        for(i = 0; i < 5 ;i++){
4649
          switch(i){
4650
            case 0: stroke_color = get_color(infile,0);break;/* font_color == stroke_color name or hex color */
4651
            case 1: double_data[0] = get_real(infile,0);break; /* x */
4652
            case 2: double_data[1] = get_real(infile,0);break; /* y */
4653
            case 3: fly_font = get_string_argument(infile,0);
4654
              if(strcmp(fly_font,"giant") == 0){
4655
                fly_font_size = (int)(font_size + 24);
4656
              }
4657
              else {
4658
                if(strcmp(fly_font,"huge") == 0){
4659
                  fly_font_size = (int)(font_size + 14);
4660
                }
4661
                else {
4662
                  if(strcmp(fly_font,"large") == 0){
4663
                    fly_font_size = (int)(font_size + 6);
4664
                  }
4665
                  else {
4666
                    if(strcmp(fly_font,"small") == 0){
4667
                      fly_font_size = (int)(font_size - 4);
4668
                      if(fly_font_size<0){fly_font_size = 8;}
4669
                    }
4670
                  }
4671
                }
4672
              }
4673
              break;
4674
            case 4:
4675
              temp = get_string_argument(infile,1);
4676
              if(strstr(temp,"_") != NULL || strstr(temp,"^") != NULL){js_function[DRAW_SUBSUP] = 1;}
4677
              decimals = find_number_of_digits(precision);
4678
              if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
4679
              if(use_affine == TRUE ){ transform(2,2);}
18557 bpr 4680
              tmp_buffer=my_newmem(MAX_BUFFER);
4681
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,14,[%.*f],[%.*f],[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%f,\"%s\",%d,%s,%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[1],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,0,0,0,use_rotate,angle,temp,fly_font_size,"null",my_sliders,rotation_center,use_offset));
18552 bpr 4682
              add_to_buffer(tmp_buffer);
4683
              if(onclick != 0){object_cnt++;}
4684
              reset();
4685
              break;
4686
            default:break;
4687
            }
4688
          }
4689
          dragstuff[14] = 1;
4690
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
4691
          break;
4692
        case TEXTAREA:
4693
  /*
18556 bpr 4694
  @ textarea x,y,cols,rows,readonly,value
4695
  @ may be further controlled by <a href="#css">css</a>
4696
  @ if ''&#36;status=done`` (e.g. in answer.phtml) the inputfield will be cleared and set readonly. Override this by keyword <a href="#status">status</a>.
4697
  @ if mathml inputfields are present and / or some userdraw is performed, these data will <b>not</b> be send as well (<code>javascript:read_canvas();</code>)
4698
  @ keyword ''xoffset | centered`` is not active for command ''textarea``
4699
  @%textarea%size 400,400%xrange -10,10%yrange -10,10%css color:red;background-color:lightblue;font-size:14px;text-align:center%textarea -3,-2,6,3,1,?%css color:blue;background-color:yellow;font-size:14px;text-align:center%textarea 0,-2,8,2,1,?
18552 bpr 4700
  */
4701
          js_function[DRAW_TEXTAREAS] = 1;
4702
          for(i = 0 ; i<6;i++){
4703
            switch(i){
4704
              case 0: int_data[0]=x2px(get_real(infile,0));break; /* x in px */
4705
              case 1: int_data[1]=y2px(get_real(infile,0));break; /* y in px */
4706
              case 2: int_data[2]=abs( (int)(get_real(infile,0)));break;/* cols */
4707
              case 3: int_data[3]=abs( (int)(get_real(infile,0)));break;/* rows */
4708
              case 4: if( get_real(infile,1) >0){int_data[4] = 1;}else{int_data[3] = 0;};break; /* readonly */
4709
              case 5: temp = get_string_argument(infile,1);
18557 bpr 4710
                tmp_buffer=my_newmem(MAX_BUFFER);
4711
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_textareas(%d,%d,%d,%d,%d,%d,%d,\"%s\",\"%s\");\n",canvas_root_id,input_cnt,int_data[0],int_data[1],int_data[2],int_data[3],int_data[4],css_class,temp));
18552 bpr 4712
                add_to_buffer(tmp_buffer);
4713
                input_cnt++;break;
4714
              default: break;
4715
            }
4716
          }
4717
          if(reply_format == 0 ){reply_format = 15;}
4718
          reset();
4719
          break;
4720
        case TEXTFILL:
4721
  /*
4722
  @ textfill x0,y0,color,some_text
4723
  @ x0,y0 in xrange / yrange
4724
  @ color will be used for the font color
4725
  @ use command <a href="#fontfamily">fontfamily</a> to set font type and size
4726
  @ there is also a command <a href="#userdraw">userdraw textfill,color,some_text</a>
4727
  @%textfill%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%fontfamily 24pt Arial%circles red,0,0,3,3,3,6%textfill 4,4,blue,HELLO WORLD
4728
  */
11806 schaersvoo 4729
 
18552 bpr 4730
          js_function[DRAW_TEXTFILL] = 1;
4731
          if(js_function[DRAW_FILLTOBORDER] != 1 ){/* use only once */
4732
            js_function[DRAW_FILLTOBORDER] = 1;
4733
            add_js_filltoborder(canvas_type);
4734
          }
4735
          decimals = find_number_of_digits(precision);
4736
          for(i=0;i<4;i++){
4737
            switch(i){
4738
              case 0: double_data[0] = get_real(infile,0); break; /* x in px */
4739
              case 1: double_data[1] = get_real(infile,0); break; /* y in py */
4740
              case 2: font_color = get_color(infile,0); break;
4741
              case 3: temp = get_string(infile,1);
18557 bpr 4742
                tmp_buffer=my_newmem(MAX_BUFFER);
4743
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_textfill(%d,%*.f,%*.f,'%s','%s',%d,%d,'%s',false); ",FILL_CANVAS+fill_cnt,decimals,double_data[0],decimals,double_data[1],font_color,font_family,xsize,ysize,temp));
18552 bpr 4744
                add_to_buffer(tmp_buffer);
4745
                fill_cnt++;
4746
                break;
4747
              default:break;
4748
            }
4749
          }
4750
          reset();
4751
          break;
4752
        case FLY_TEXTUP:
4753
  /*
18556 bpr 4754
  @ textup fontcolor,x,y,font,text_string
4755
  @ can <b>not</b> be set ''onclick`` or ''drag xy`` (because of translaton matrix...mouse incompatible)
4756
  @ font may be described by keywords: giant,huge,normal,small,tiny
4757
  @ use command ''fontsize`` to increase base fontsize for the keywords
4758
  @ backwards compatible with flydraw
4759
  @ unicode supported: textup red,0,0,huge,\\u2232
4760
  @ use command ''stringup`` and ''fontfamily`` for a more fine grained control over html5 canvas text element
4761
  @ Avoid mixing old flydraw commands ''text``, ''textup`` with new canvasdraw commands ''string``; ''stringup``. If the fontfamily was set completely like <code>fontfamily italic 24px Arial</code>. In that case reset ''fontfamily`` to something like ''fontfamily Arial`` before the old flydraw commands.
18552 bpr 4762
  */
4763
          js_function[DRAW_TEXTS] = 1;
4764
          for(i = 0; i<5 ;i++){
4765
            switch(i){
4766
              case 0: font_color = get_color(infile,0);break;/* name or hex color */
4767
              case 1: int_data[0] = x2px(get_real(infile,0));break; /* x */
4768
              case 2: int_data[1] = y2px(get_real(infile,0));break; /* y */
4769
              case 3: fly_font = get_string_argument(infile,0);
4770
                if(strcmp(fly_font,"giant") == 0){
4771
                  fly_font_size = (int)(font_size + 24);
4772
                }
4773
                else {
4774
                  if(strcmp(fly_font,"huge") == 0){
4775
                    fly_font_size = (int)(font_size + 14);
4776
                  }
4777
                  else {
4778
                    if(strcmp(fly_font,"large") == 0){
4779
                      fly_font_size = (int)(font_size + 6);
4780
                    }
4781
                    else {
4782
                      if(strcmp(fly_font,"small") == 0){
4783
                        fly_font_size = (int)(font_size - 4);
4784
                        if(fly_font_size<0){fly_font_size = 8;}
4785
                      }
4786
                    }
4787
                  }
4788
                }
4789
                break;
4790
              case 4:
4791
                decimals = find_number_of_digits(precision);
4792
                temp = get_string_argument(infile,1);
4793
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
18557 bpr 4794
                tmp_buffer=my_newmem(MAX_BUFFER);
4795
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_text(%d,%d,%d,%d,\"%s\",\"%s\",%.2f,90,\"%s\",%d,%.2f,%d);\n",STATIC_CANVAS,int_data[0],int_data[1],fly_font_size,"null",font_color,stroke_opacity,temp,use_rotate,angle,use_offset));
18552 bpr 4796
                add_to_buffer(tmp_buffer);
4797
                reset();
4798
        //use_offset = 0;
4799
                break;
4800
              default:break;
4801
            }
4802
          }
4803
          break;
4804
        case TRACE_JSCURVE:
4805
  /*
18556 bpr 4806
  @ trace_jscurve some_math_function
4807
  @ will use a crosshair to trace the jsmath curve
4808
  @ two inputfields will display the current x/y-values (numerical evaluation by javascript)
4809
  @ default labels ''x`` and ''y``; use commands ''xlabel some_x_axis_name`` and ''ylabel some_y_axis_name`` to customize the labels for the input fields
4810
  @ use commands fontsize and css to format the fonts for labels and inputfields.
4811
  @ use commands ''linewidth, strokecolor, crosshairsize`` to adjust the corsshair.
4812
  @ the client browser will convert your math function to javascript math.<br>use parenthesis and rawmath: use 2*x instead of 2x etc etc no check is done on the validity of your function and/or syntax (use error console to debug any errors...)
4813
  @ be aware that the formulas of the plotted function(s) can be found in the page javascript source
4814
  @%trace_jscurve%size 400,400%xrange -10,10%yrange -10,10%precision 0%axis%axisnumbering%grid 2,2,grey,2,2,5,gray%recision 100%css color:blue;%linewidth 4%crosshairsize 8%trace_jscurve 5*sin(0.1*x^2)%linewidth 1%jsplot red,5*sin(0.1*x^2)%#only one curve can be traced
18552 bpr 4815
  */
4816
          js_function[INTERACTIVE] = 1;
4817
          js_function[DRAW_CROSSHAIRS] = 1;
4818
          js_function[DRAW_LINES] = 1;
4819
          js_function[JS_MATH] = 1;
4820
          add_trace_js_mouse(TRACE_CANVAS,stroke_color,get_string(infile,1),font_size,stroke_opacity,line_width,crosshair_size,css_class);
4821
          break;
4822
        case TRANGE:
4823
  /*
4824
  @ trange tmin,tmax
4825
  @ alternative: ranget
4826
  @ default -2,2
4827
  */
4828
          use_parametric = TRUE;
4829
          for(i = 0 ; i<2; i++){
4830
            switch(i){
4831
              case 0: tmin = get_real(infile,0);break;
4832
              case 1: tmax = get_real(infile,1);break;
4833
              default: break;
4834
            }
4835
          }
4836
          if(tmin >= tmax ){canvas_error(" trange is not OK: tmin &lt; tmax!\n");}
4837
          break;
4838
        case TRANSLATION:
4839
  /*
18556 bpr 4840
  @ translation tx,ty
4841
  @ alternative: translate
4842
  @ will translate the next objects tx in xrange and ty in yrange
4843
  @ use command ''killtranstation`` to end the command
18569 bpr 4844
  @%translation%size 400,400%xrange -10,10%yrange -10,10%linewidth 1%fillpattern grid%triangle -6,6,8,6,5,1,blue%translation 2,2%ftriangle -6,6,8,6,5,1,red
18552 bpr 4845
  */
4846
          for(i = 0 ; i<2;i++){
4847
            switch(i){
4848
              case 0: affine_matrix[4] = get_real(infile,0);break;
4849
              case 1: affine_matrix[5] = get_real(infile,1);
4850
                use_affine = TRUE;
4851
      /* the other values affine_matrix[0..3] remain untouched*/
4852
                break;
4853
              default: break;
4854
            }
4855
          }
4856
          break;
4857
        case TRIANGLE:
4858
  /*
18556 bpr 4859
  @ triangle x1,y1,x2,y2,x3,y3,color
4860
  @ use ftriangle or keyword <a href='#filled'>filled</a> for a solid triangle
4861
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
4862
  @%triangle%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%opacity 250,150%drag xy%triangle 0,0,-4,4,6,8,red%drag xy%ftriangle 0,0,-4,-4,6,-8,red%fillpattern grid%drag xy%ftriangle -6,6,8,6,5,1,blue
18552 bpr 4863
  */
4864
          for(i=0;i<7;i++){
4865
            switch(i){
4866
              case 0: double_data[0] = get_real(infile,0);break; /* x */
4867
              case 1: double_data[1] = get_real(infile,0);break; /* y */
4868
              case 2: double_data[2] = get_real(infile,0);break; /* x */
4869
              case 3: double_data[3] = get_real(infile,0);break; /* y */
4870
              case 4: double_data[4] = get_real(infile,0);break; /* x */
4871
              case 5: double_data[5] = get_real(infile,0);break; /* y */
4872
              case 6: stroke_color = get_color(infile,1);/* name or hex color */
4873
                decimals = find_number_of_digits(precision);
18623 bpr 4874
                if(fillcolor) {fill_color=fillcolor;} else {fill_color=stroke_color;}
18552 bpr 4875
                if( use_rotate == TRUE ){ rotate(6,angle,rotationcenter,2);}
4876
                if( use_affine == TRUE ){ transform(6,2);}
4877
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
18557 bpr 4878
                tmp_buffer=my_newmem(MAX_BUFFER);
18623 bpr 4879
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,5,%s,[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,double_xy2js_array(double_data,6,decimals),line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 4880
                add_to_buffer(tmp_buffer);
4881
                if(onclick != 0){object_cnt++;}
4882
          /* object_cnt++;*/
4883
                reset();
4884
                break;
4885
              default: break;
4886
            }
4887
          }
4888
          dragstuff[5] = 1;
4889
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
4890
          break;
4891
        case TRIANGLES:
4892
  /*
18556 bpr 4893
  @ triangles color,x1,y1,x2,y2,x3,y3,...
4894
  @ use ftriangles or keyword <a href='#filled'>filled</a> for solid triangles
4895
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually (!)
4896
  @%triangles%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%onclick%triangles red,0,0,-4,4,6,8,0,0,-4,-4,6,-8,-6,6,8,6,5,1%# the same as 3 calls to command triangle
18552 bpr 4897
  */
4898
          stroke_color = get_color(infile,0);/* name or hex color */
18623 bpr 4899
          if(fillcolor) {fill_color=fillcolor;} else {fill_color=stroke_color;}
18552 bpr 4900
          i = 0;
4901
          decimals = find_number_of_digits(precision);
4902
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
4903
          while( ! done ){
4904
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
4905
            double_data[0] = get_real(infile,0); /* x1 */
4906
            double_data[1] = get_real(infile,0); /* y1 */
4907
            double_data[2] = get_real(infile,0); /* x2 */
4908
            double_data[3] = get_real(infile,0); /* y2 */
4909
            double_data[4] = get_real(infile,0); /* x3 */
4910
            double_data[5] = get_real(infile,1); /* y3 */
18557 bpr 4911
            tmp_buffer=my_newmem(MAX_BUFFER);
18623 bpr 4912
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,5,%s,[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,double_xy2js_array(double_data,6,decimals),line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 4913
            add_to_buffer(tmp_buffer);
4914
            if(onclick != 0){object_cnt++;}
4915
            i = i + 6;
4916
          }
4917
          reset();
4918
          dragstuff[5] = 1;
4919
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
4920
          break;
4921
        case USERBOXPLOT:
4922
  /*
18556 bpr 4923
  @ userboxplot
4924
  @ keyword, no arguments
4925
  @ use before command <a href="#boxplot">boxplot x_or_y,box-height_or_box-width,x_or_y-position</a>
4926
  @ if set, the student will have to calculate "min,Q1,median,Q3,max" and feed these data into the ''draw_boxplot`` function
4927
  @ for example: put the canvas-script into a html element with id='boxplot' and set style='display:none'<br>define a variable called ''student_boxplot`` and fill it with the 5 student-data (from inputfields or something)<br><code>var student_boxplot = new Array(5)<br>function show_boxplot(){<br>student_boxplot[0] = min;<br>student_boxplot[1] = Q1;<br>student_boxplot[2] = median;<br>student_boxplot[3] = Q3;<br>student_boxplot[4] = max;<br>document.getElementById('boxplot').style.display = "block";<br>draw_boxplot(12345,1,2.00,5.00,[0,0,0,0,0],4,"0,0,255",0.78,"255,165,0",0.60,1,0,1,1);<br>};</code><br>In the canvas-script the function draw_boxplot has the following arguments:<br>draw_boxplot=function(canvas_type,xy,hw,cxy,data,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1)
18552 bpr 4928
  */
4929
          js_function[DRAW_BOXPLOT] = 1;
4930
          fprintf(js_include_file,"var boxplot_source = 3;\n");
4931
          js_function[DRAW_JSBOXPLOT] = 2;
4932
          break;
4933
        case USERBOXPLOTDATA:
4934
  /*
18556 bpr 4935
  @ userboxplotdata
4936
  @ keyword, no arguments
4937
  @ use before command <a href="#boxplot">boxplot x_or_y,box-height_or_box-width,x_or_y-position</a>
4938
  @ if set, the student will have to generate some statistical data. These data should be put in a named array ''student_boxplot_data``
4939
  @ ''min,Q1,median,Q3,max`` are calculated by a js-function and the 'draw_boxplot' function will draw a boxplot.
4940
  @ see command <a href="#userboxplot">userboxplot</a> for calling 'draw_boxplot()'
18552 bpr 4941
  */
4942
          js_function[DRAW_BOXPLOT] = 1;
4943
          fprintf(js_include_file,"var boxplot_source = 2;\n");
4944
          js_function[DRAW_JSBOXPLOT] = 1;
4945
          break;
4946
        case USERDRAW:
4947
  /*
4948
  @ userdraw object_type,color
4949
  @ only a single object_type is allowed.
4950
  @ right mouse click will remove last drawn object.
4951
  @ for multiple different 'userdraw' objects in an exercise, use command <a href="#multidraw">multidraw</a>
18572 bpr 4952
  @ implemented object_type: <ul><li>point</li><li>points</li><li>crosshair</li><li>crosshairs</li><li>line</li><li>lines</li><li>vline</li><li>vlines</li><li>hline</li><li>hlines</li><li>demiline</li><li>demilines</li><li>segment</li><li>segments</li><li>polyline | brokenline</li><li>circle</li><li>circles</li><li>arrow</li><li>arrow2 (double arrow)</li><li>arrows</li><li>arrows2 (double arrows)</li><li>curvedarrow</li><li>curvedarrows</li><li>curvedarrow2</li><li>curvedarrows2</li><li>triangle</li><li>polygon</li><li>poly[3-9] (e.g poly3 ... poly7...poly9</li><li>rect</li><li>roundrect</li><li>rects</li><li>roundrects</li><li>freehandline | path</li><li>freehandlines | paths</li><li>clickfill: fill the clicked area with color<br>multiple areas may be selected <br>multiple colors may be provided using commands <a href='#colorpalette'>colorpalette color1,color2,color3,...</a> use <a href='#replyformat'>replyformat 10</a> for checking the user click color ... reply=x1:y1:color1,x2:y2:color2...<br>attention: this will <b>not</b> work for pattern filling, because the pattern image is only generated once and after creation can not be changed !<br>the opacity of this image on a separate canvas is set to 0.01 and not 0 (!!)...in the ''fill algorithm`` the opacity of the matching pixels is set to 1</li><li>dotfill: fill the clicked area with a dot pattern; use command linewidth to change dot size</li><li>diamondfill: fill the clicked area with a diamond pattern</li><li>hatchfill: fill the clicked area with a hatch pattern</li><li>gridfill: fill the clicked area with a grid pattern</li><li>textfill: fill the clicked area with a repeating string<br>userdraw textfill,blue,some_text<br>use command <a href="#fontfamily">fontfamily</a> to adjust text style and size</li><li>''clickfill | pattern filling`` in general:<br>the clicks may be set <a href="#snaptogrid">snaptogrid</a><br>can be used together with command <a href="#floodfill">floodfill or fill</a><br><b>always</b> use together with command <a href="#clearbutton">clearbutton some_text</a> for removal of all click_colored areas<br>the function read_canvas() will return the click coordinates in the sequence of the user clicks<br>use command <a href="#canvastype">canvastype</a> to fill another canvas (default should be fine: DRAG_CANVAS = 5)</li><li>text <br>an inputfield is provided, unicode allowed. The text is drawn a the mouse click, or if used with command ''userinput inputfield`` also at the given x/y-coordonates</li><li>arc</li><li>arcs</li><li>image<br>only a single "image" of every supported type(*) may be added to canvas window from the surrounding html page.<br>the image should have an 'id' and an onclick handler.<br>(*) supported types are ''svg``,''bitmap``,''p-element``,''div-element`` and ''mathml/tex-code`` with ''\\mmlid{int}``.</li><li>images</li><li>input<br>place a single inputfield on ''canvas`` <br>use commands 'css' for css styling: use command ''linewidth`` for adjusting the input field size (default 1)</li><li>inputs<br>place multiple inputfield: placing inputfields on top of each other is not possible</li><li>function : identical to <a href="#userinput">userinput function</a></li></ul>
18552 bpr 4953
  @ note: mouselisteners are only active if ''&#36;status != done`` (eg only drawing in an active/non-finished exercise) <br> to overrule use command/keyword ''status`` (no arguments required)
4954
  @ note: object_type text: Any string or multiple strings may be placed anywhere on the canvas.<br>Use command ''fontfamily`` to set font
4955
  @ note: object_type polygone: Will be finished (the object is closed) when clicked on the first point of the polygone again.
4956
  @ note: all objects will be removed -after a javascript confirm box- when clicked on an object point with middle or right mouse button (e.g. event.button != 1: all buttons but left)
18572 bpr 4957
  @ use a prefix <a href='#filled'>filled</a> or ''f`` to set fillable objects filled. (fcircles,filledcircles etc)<br> in case of ''fillpattern`` do not use the ''f`` prefix !
18552 bpr 4958
  @ for non solid filling, use command <a href="#fillpattern">fillpattern grid,hatch,diamond,dot</a>
4959
  @ use <a href='#opacity'>opacity int,int</a> and <a href='#fillcolor'>fillcolor color</a> to trigger coloured filling of fillable objects
4960
  @ use command ''dashed`` and/or ''dashtype int,int`` to trigger dashing
4961
  @ use command ''replyformat int`` to control / adjust output formatting of javascript function read_canvas(); (the defaults should be fine...)
4962
  @ may be combined with onclick or drag xy of other components of flyscript objects (although not very useful...)
4963
  @ may be combined with keyword <a href='#userinput_xy'>userinput_xy</a>
4964
  @ may be combined width the <a href='#snaptogrid'>snaptogrid snaptopoints </a> etc, to simplify the checking of the student reply
4965
  @ the cursor may be appropriately styled using command <a href='cursor'>cursor</a>
4966
  @ note: when zooming / panning after a drawing, the drawing will NOT be zoomed / panned...this is a "design" flaw and not a feature <br>To avoid trouble do not use zooming / panning together width userdraw.!<br>use command <a href="#multidraw">multidraw</a> is this is a problem for you...
4967
  @ note: the default replyformat for ''userdraw input(s),color`` used format x1;y1;text1 \n x2;y2;test2 \n x_n;y_n;text_n (e.g. it is not a comma separated array...use ''direct exec`` to test)
4968
  @ note: a special case is ''userdraw image,boguscolor``. Images (bitmap or svg or div) present in the exercise page and the img/svg/div-tag with an unique 'id' and <code>onclick='javascript:place_image_on_canvas(this.id)'</code> can be placed onto the canvas.<br>The ''id`` and (x;y) coordinates will be returned using read_canvas();<br> native MathML, MathJax or KaTeX typesetting may be included in div's.(experiments; wims_modules svn version only!)
4969
  @ note: command <br><code>userdraw function,color</code> is identical to acombination of <code>strokecolor color</code> and <code>userinput function</code><br>
18572 bpr 4970
  @ note: commands :<br><code>multicolors red,green,blue<br>multilabel f(x)=:g(x)=:h(x)=<br>userdraw functions3,color</code><br>is identical to commands :<br><code>functionlabel f(x)=:p(x)=:w(x)=<br>strokecolor red<br>userinput function <br>strokecolor green<br>userinput function <br>strokecolor blue<br>userinput function</code>
18552 bpr 4971
  @%userdraw_canvastype_a%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%grid 2,2,grey%replyformat 10%colorpalette orange,yellow,red,green,lightgreen,blue,lightblue,cyan%canvastype 4%userdraw clickfill,blue%clearbutton REMOVE LAST RECTANGLE
4972
  @%userdraw_canvastype_b%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%canvastype 4%snaptogrid%replyformat 10%userdraw dotfill,blue%clearbutton REMOVE LAST RECTANGLE
4973
  @%userdraw_rect%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw rect,green
4974
  @%userdraw_rects%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw rects,green
4975
  @%userdraw_frect%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw frect,green
18635 bpr 4976
  @%userdraw_frects%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%filled%opacity 200,50%userdraw rects,green
4977
  @%userdraw_roundrect%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%filled%opacity 200,50%userdraw roundrect,green
4978
  @%userdraw_roundrects%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%filled%opacity 200,50%userdraw roundrects,green
4979
  @%userdraw_froundrect%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%filled%opacity 200,50%userdraw roundrect,green
4980
  @%userdraw_froundrects%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%filled%opacity 200,50%userdraw roundrects,green
18552 bpr 4981
  @%userdraw_line%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw line,green
4982
  @%userdraw_lines%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw lines,green
4983
  @%userdraw_vline%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw vline,green
4984
  @%userdraw_vlines%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw vlines,green
4985
  @%userdraw_hline%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw hline,green
4986
  @%userdraw_hlines%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw hlines,green
4987
  @%userdraw_demiline%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw demiline,green
4988
  @%userdraw_demilines%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw demilines,green
4989
  @%userdraw_arc%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw arc,green
4990
  @%userdraw_arcs%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw arcs,green
4991
  @%userdraw_point%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw point,green
4992
  @%userdraw_points%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw points,green
4993
  @%userdraw_arrow%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw arrow,green
4994
  @%userdraw_arrows%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw arrows,green
4995
  @%userdraw_arrow2%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw arrow2,green
4996
  @%userdraw_arrows2%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw arrows2,green
4997
  @%userdraw_curvedarrow%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 1%linewidth 3%userdraw curvedarrow,red%clearbutton REMOVE ALL ARROWS
4998
  @%userdraw_curvedarrows%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 1%linewidth 3%userdraw curvedarrows,red%clearbutton REMOVE ALL ARROWS
4999
  @%userdraw_curvedarrow2%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 1%linewidth 3%userdraw curvedarrow2,red%clearbutton REMOVE ALL ARROWS
5000
  @%userdraw_curvedarrows2%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%precision 1%linewidth 3%userdraw curvedarrows2,red%clearbutton REMOVE ALL ARROWS
5001
  @%userdraw_crosshair%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw crosshair,green
5002
  @%userdraw_crosshairs%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw crosshairs,green
18635 bpr 5003
  @%userdraw_circle%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%filled%opacity 200,50%userdraw circle,green
5004
  @%userdraw_circles%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%filled%opacity 200,50%userdraw circles,green
18552 bpr 5005
  @%userdraw_segment%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw segment,green
5006
  @%userdraw_segments%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw segments,green
5007
  @%userdraw_line%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw line,green
5008
  @%userdraw_lines%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw lines,green
18635 bpr 5009
  @%userdraw_triangle%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%filled%opacity 200,50%userdraw triangle,green
5010
  @%userdraw_poly5%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw poly5,green
18552 bpr 5011
  @%userdraw_filled_poly5%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%filled%userdraw poly5,green
5012
  @%userdraw_poly7%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%userdraw poly7,green
5013
  @%userdraw_filled_poly7%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%filled%userdraw poly7,green
18635 bpr 5014
  @%userdraw_polyline%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw polyline,green
18552 bpr 5015
  @%userdraw_freehandline%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw freehandline,green
5016
  @%userdraw_filled_freehandline%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%fillcolor orange%opacity 200,50%filled%userdraw freehandline,green
5017
  @%userdraw_freehandlines%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%opacity 200,50%userdraw freehandlines,green
5018
  @%userdraw_input%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%userdraw input,green
5019
  @%userdraw_inputs%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%userdraw inputs,green
5020
  @%userdraw_text%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%fontfamily 42px Courier%userdraw text,green
5021
  @%userdraw_function%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 1%grid 2,2,grey,2,2,5,grey%multicolors orange,red,green,blue,cyan%precision 1000%userdraw functions3,red%jscurve blue,x^2,-x^2,5*cos(x)%precision 1%mouse red,22
5022
  @%userdraw_clickfill_colorpalette%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%circles blue,0,0,4,1,1,6,3,3,3,-3,-3,5%opacity 255,120%colorpalette red,green,yellow,blue%userdraw clickfill,green
5023
  @%userdraw_clickfill_1%size 400,400%xrange -10,10%yrange -10,10%linewidth 3%circles blue,0,0,4,1,1,6,3,3,3,-3,-3,5%opacity 255,120%userdraw clickfill,green
18609 bpr 5024
  @%userdraw_clickfill_2%size 400,400%xrange -10,10%yrange -10,10%circles blue,0,0,2,1,1,5,5,5,4,-5,5,6,5,-5,6%userdraw hatchfill,red%#userdraw dotfill,red%#userdraw diamondfill,red%#userdraw gridfill,red
18552 bpr 5025
  @%userdraw_clickfill_2%size 400,400%xrange -10,10%yrange -10,10%bgcolor white%# to get nice click coordinates take invisible ''grid`` and use ''snaptogrid`` %grid 1,1,white%snaptogrid%circles blue,0,0,2,1,1,5,5,5,4,-5,5,6,5,-5,6%userdraw gridfill,red
5026
  */
5027
          if( use_userdraw != 0 ){ /* only one object type may be drawn*/
5028
            canvas_error("Only one userdraw primitive may be used in command 'userdraw' use command 'multidraw' for this...");
5029
          }
5030
          js_function[INTERACTIVE] = 1;
5031
          draw_type = get_string_argument(infile,0);
5032
          if( strcmp(draw_type,"textfill") == 0){
5033
            fprintf(js_include_file,"var userdraw_text_string = \"%s\";", get_string(infile,1));
5034
          }
5035
          else {
5036
            if( strcmp(draw_type,"imagefill") == 0){
5037
              fprintf(js_include_file,"var userdraw_image_url = \"%s\";", get_string(infile,1));
5038
            }
5039
            else {
5040
              stroke_color = get_color(infile,1);
5041
            }
5042
          }
5043
          if( strcmp(draw_type,"clickfill") == 0){use_filled = 1;fill_color = stroke_color;}
5044
          reply_precision = precision;
5045
          use_userdraw = 1;
5046
          fprintf(js_include_file,"\n\
15111 schaersvoo 5047
/* begin userdraw */\
5048
userdraw_x = new Array();userdraw_y = new Array();userdraw_radius = new Array();\
5049
var forbidden_zone=[xsize+1,ysize+1];var xy_cnt = 0;\
5050
var canvas_userdraw = create_canvas%d(%d,xsize,ysize);\
5051
var context_userdraw = canvas_userdraw.getContext(\"2d\");\
5052
var use_dashed = %d;\
5053
var use_snap = %d;if(use_dashed == 1){if( context_userdraw.setLineDash ){context_userdraw.setLineDash([%d,%d]);}else{if(context_userdraw.mozDash){context_userdraw.mozDash = [%d,%d];};};};\
5054
context_userdraw.lineWidth = %d;var use_filled = %d;\
5055
context_userdraw.strokeStyle =  \"rgba(%s,%.2f)\";\
5056
context_userdraw.font = \"%s\";\
15128 schaersvoo 5057
var user_is_dragging = false;\
15111 schaersvoo 5058
if(wims_status != \"done\"){\
5059
canvas_div.addEventListener(\"mousedown\" ,user_draw,false);\
5060
canvas_div.addEventListener(\"mousemove\" ,user_drag,false);\
5061
canvas_div.addEventListener(\"touchstart\",function(e){ e.preventDefault();user_draw(e.changedTouches[0]);},false);\
5062
canvas_div.addEventListener(\"touchmove\" ,function(e){ e.preventDefault();user_drag(e.changedTouches[0]);},false);\
15128 schaersvoo 5063
canvas_div.addEventListener(\"touchend\" ,function(e){ e.preventDefault();user_drawstop(e.changedTouches[0]);},false);\
15111 schaersvoo 5064
};",canvas_root_id,DRAW_CANVAS,use_dashed,use_snap,dashtype[0],dashtype[1],dashtype[0],dashtype[1],line_width,use_filled,stroke_color,stroke_opacity,font_family);
5065
 
18552 bpr 5066
          if( use_filled == 0 ){
5067
            fprintf(js_include_file,"context_userdraw.fillStyle = \"rgba(255,255,255.0)\";");
5068
          }
5069
          else {
5070
            if( use_filled == 1 ){
5071
              fprintf(js_include_file,"context_userdraw.fillStyle = \"rgba(%s,%.2f)\";",fill_color,fill_opacity);
5072
            }
5073
            else {
5074
              js_function[DRAW_FILL_PATTERN] = 1;
5075
              fprintf(js_include_file,"context_userdraw.fillStyle = create_Pattern(0,0,%d,[%s]);\n",use_filled,fill_color);
5076
            }
5077
          }
5078
          add_js_userdraw(draw_type,stroke_color,stroke_opacity,crosshair_size,arrow_head,use_offset,css_class,use_snap,canvas_type,use_filled,fill_color,fill_opacity,line_width,font_family);
5079
          reset();
5080
          break;
5081
        case USERINPUT:
5082
  /*
18556 bpr 5083
  @ userinput function inputfield
5084
  @ alternative: userinput_function
5085
  @ alternative: userinput_xy
5086
  @ ''inputfield`` is only usable in combination with some ''userdraw draw_type``
5087
  @ note: the input fields are not cleared after the object is drawn...be aware of multiple idential drawings (many clicks on the ''ok`` button)
5088
  @ ''userinput function`` may be used any time (e.g. without userdraw)
5089
  @ multiple ''userinput function`` commands may be used.
5090
  @ use command <code>functionlabel some_string</code> to define the inputfield text: default value "f(x)="
5091
  @ use command <code>strokecolor some_color</code> to adjust the plot / functionlabel color
5092
  @ use command <code>css some_css</code> to adjust the inputfields
5093
  @ use command <code>fontsize int</code> to adjust the label fonts. (default 12px)
5094
  @ the user input for the function will be corrected by a simple ''rawmath`` implementation...<br>an error message will be shown if javascript can not interpret the user input
5095
  @%userinput_function%size 400,400%xrange -10,10%yrange -10,10%functionlabel your function g(x)=%axis%axisnumbering%xlabel x-axis%ylabel y-axis%grid 2,2,grey,3,3,5,grey%css color:blue;text-align:center%userinput function%# note: number of function inputs not limited
5096
  @%userinput_points%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%# adding 2 inputfields for x and y%userinput inputfield%userdraw points,blue
5097
  @%userinput_arrows%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%#adding 4 inputfields for (x1;y1)---(x2;y2)%userinput inputfieldd%userdraw arrows,blue
5098
  @%userinput_combined%size 400,400%xrange -10,10%yrange -10,10%functionlabel your function g(x)=%axis%axisnumbering%xlabel x-axis%ylabel y-axis%precision 0%grid 2,2,grey,3,3,5,grey%css color:blue;text-align:center%precision 1000%strokecolor red%opacity 255,255%userinput function%# note: number of function inputs not limited%userdraw line,blue
18552 bpr 5099
  */
5100
          temp = get_string_argument(infile,1);
5101
          if(strstr(temp,"function") != 0  || strstr(temp,"curve") != 0  || strstr(temp,"plot") != 0 ){
5102
            if( js_function[DRAW_JSFUNCTION] != 1 ){
5103
              js_function[JS_RAWMATH] = 1;
5104
              js_function[DRAW_JSFUNCTION] = 1;
5105
              if(reply_format == 0){reply_format = 24;}/* read canvas_input values */
5106
              add_input_jsfunction(css_class,function_label,input_cnt,stroke_color,stroke_opacity,line_width,use_dashed,dashtype[0],dashtype[1],font_size);
5107
              input_cnt++;
5108
            }
5109
            else {
5110
        /* no need to add DRAW_JSFUNCTION, just call it with the parameters */
5111
            fprintf(js_include_file,"add_input_jsfunction(%d,\"%s\",%s,%d,\"%s\",\"%.2f\",%d,%d,%d,%d);\n",input_cnt,css_class,function_label,line_width,stroke_color,stroke_opacity,use_dashed,dashtype[0],dashtype[1],font_size);
5112
            input_cnt++;
5113
            }
5114
            js_function[JS_MATH] = 1;
5115
            js_function[JS_PLOT] = 1;
5116
          }
5117
          else {
5118
            if(strstr(temp,"inputfield") != 0 ){
5119
              js_function[JS_SAFE_EVAL] = 1;
5120
              js_function[ADD_USER_INPUTS] = 1;
5121
            }
5122
            else {
5123
              canvas_error("userinput argument may be \"function\" or \"inputfield\"");
5124
            }
5125
          }
5126
          break;
5127
        case USERINPUT_XY:
5128
  /*
5129
  @ userinput_xy
5130
  @ keyword (no arguments required)
5131
  @ to be used in combination with command "userdraw object_type,color"
5132
  @ if set two (or three) input fields are added to the document<br>(one for x-values, one for y-values and in case of drawing circle one for radius-values)
5133
  @ the student may use this as correction for (x:y) on a drawing (or to draw without mouse, using just the coordinates)
5134
  @ math input is allowed (e.g something like: 1+3,2*6,1/3,sqrt(3), sin(pi/4),10^-2,log(2)...)<br>eval function is ''protected`` against code injection.
5135
  @ can <b>not</b> be combined with command ''intooltip tiptext`` <br>note: the ''tooltip div element`` is used for placing inputfields
5136
  @ user drawings will not zoom on zooming (or pan on panning)
5137
  @ use command ''css some_css`` to adjust the inputarea.
5138
  @ use command ''fontsize int`` to adjust the text labels (if needed)
5139
  @%userinput_xy%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%precision 0%grid 2,2,grey,3,3,6,black%# provides inputfields for (x1:y1)---(x2:y2)%userinput_xy%linewidth 2%precision 1000%userdraw lines,blue
5140
  */
5141
      /* add simple eval check to avoid code injection with unprotected eval(string) */
5142
          js_function[JS_SAFE_EVAL] = 1;
5143
          js_function[ADD_USER_INPUTS] = 1;
5144
          break;
5145
        case USERINPUT_FUNCTION:
5146
  /*
5147
  @ userinput_function
5148
  @ alternative: userinput
5149
  @ keyword (no arguments required)
5150
  @ if set, a inputfield will be added to the page
5151
  @ repeat keyword for more function input fields
5152
  @ the userinput value will be plotted in the canvas
5153
  @ this value may be read with <code>read_canvas()</code>. <br>for do it yourself js-scripters: If this is the first inputfield in the script, its id is canvas_input0
5154
  @ use before this command ''userinput_function``,<br>commands like ''css some_css``, ''xlabel some_description``, ''opacity int,int``, ''linewidth int``, ''dashed`` and ''dashtype int,int`` to modify
5155
  @ fontsize can be set using command ''fontsize int``
5156
  @ incompatible with command ''intooltip link_text_or_image``: it uses the tooltip div for adding the inputfield
5157
  @%userinput_function%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%xlabel x-axis%ylabel y-axis%precision 0%grid 2,2,grey,2,2,5,grey%precision 1000%linewidth 2%# first inputfield%css color:blue;text-align:center;font-family:Italic;%strokecolor blue%functionlabel g(x)=:p(x)=:k(x)=%userinput function%# second inputfield%css color:green;text-align:center;font-family:Italic;%strokecolor green%userinput function%# third inputfield%css color:purple;text-align:center;font-family:Italic;%strokecolor purple%userinput function%# no limit in number of function inputfields
5158
  */
5159
          if( js_function[DRAW_JSFUNCTION] != 1 ){
5160
            js_function[DRAW_JSFUNCTION] = 1;
5161
            js_function[JS_RAWMATH] = 1;
5162
            if(reply_format == 0){reply_format = 24;}/* read canvas_input values */
5163
            add_input_jsfunction(css_class,function_label,input_cnt,stroke_color,stroke_opacity,line_width,use_dashed,dashtype[0],dashtype[1],font_size);
5164
            input_cnt++;
5165
          }
5166
          else {
5167
        /* no need to add DRAW_JSFUNCTION, just call it with the parameters */
5168
          fprintf(js_include_file,"add_input_jsfunction(%d,\"%s\",%s,%d,\"%s\",\"%.2f\",%d,%d,%d,%d);\n",input_cnt,css_class,function_label,line_width,stroke_color,stroke_opacity,use_dashed,dashtype[0],dashtype[1],font_size);
5169
          input_cnt++;
5170
          }
5171
          js_function[JS_MATH] = 1;
5172
          js_function[JS_PLOT] = 1;
5173
          break;
5174
        case VLINE:
5175
  /*
5176
  @ vline x,y,color
5177
  @ alternative: verticalline
5178
  @ draw a vertical line through point (x:y) in color 'color'
5179
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
5180
  @%vline%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%onclick%vline 0,0,red%onclick%vline 1,0,orange%onclick%vline 2,0,blue%onclick%vline 3,0,green
5181
  */
5182
          for(i=0;i<3;i++) {
5183
            switch(i){
5184
              case 0: double_data[0] = get_real(infile,0);break; /* x-values */
5185
              case 1: double_data[1] = get_real(infile,0);break; /* y-values */
5186
              case 2: stroke_color=get_color(infile,1);/* name or hex color */
5187
                double_data[2] = double_data[0];
5188
                decimals = find_number_of_digits(precision);
5189
                if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
18557 bpr 5190
                    tmp_buffer=my_newmem(MAX_BUFFER);
5191
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[2],decimals,100*ymin,decimals,100*ymax,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 5192
                add_to_buffer(tmp_buffer);
5193
                if(onclick != 0){object_cnt++;}
5194
      /* object_cnt++; */
5195
                reset();
5196
               break;
5197
            }
5198
          }
5199
          dragstuff[4] = 1;
5200
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
5201
          break;
5202
        case VLINES:
5203
  /*
5204
  @ vlines color,x1,y1,x2,y2....
5205
  @ alternative: verticallines
5206
  @ draw vertical lines through points (x1:y1),(x2:y2)... in color 'color'
5207
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually
5208
  @%vlines%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%onclick%vlines red,1,0,2,0,3,0,4,0
5209
  */
5210
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
5211
          fill_color = stroke_color;
5212
          i=0;
5213
          while( ! done ){     /* get next item until EOL*/
5214
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
5215
            if(i%2 == 0 ){
5216
              double_data[i] = get_real(infile,0); /* x */
5217
            }
5218
            else {
5219
              double_data[i] = get_real(infile,1); /* y */
5220
            }
5221
            i++;
5222
          }
5223
          decimals = find_number_of_digits(precision);
5224
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
5225
          for(c = 0 ; c < i-1 ; c = c+2){
18557 bpr 5226
            tmp_buffer=my_newmem(MAX_BUFFER);
18607 bpr 5227
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[0],[0],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c],decimals,100*ymin,decimals,100*ymax,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 5228
            add_to_buffer(tmp_buffer);
5229
            if(onclick != 0){object_cnt++;}
5230
            /* object_cnt++; */
5231
          }
5232
          reset();
5233
          dragstuff[4] = 1;
5234
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
5235
          break;
5236
        case VIDEO:
5237
  /*
5238
  @ video x,y,w,h,videofile location
5239
  @ x,y: left top corner of audio element (in xrange / yrange)
5240
  @ w,y: width and height in pixels
5241
  @ video format may be in *.mp4 (todo: other formats)
5242
  @%video%size 400,400%xrange -10,10%yrange -10,10%opacity 200,100%frect -9,9,6,-6,green%video -5,5,200,200,http://techslides.com/demos/sample-videos/small.mp4
5243
  */
5244
          js_function[DRAW_VIDEO] = 1;
5245
          for(i=0;i<5;i++){
5246
            switch(i){
5247
              case 0: int_data[0] = x2px(get_real(infile,0)); break; /* x in x/y-range coord system -> pixel */
5248
              case 1: int_data[1] = y2px(get_real(infile,0)); break; /* y in x/y-range coord system -> pixel */
5249
              case 2: int_data[2] = (int) (get_real(infile,0)); break; /* pixel width */
5250
              case 3: int_data[3] = (int) (get_real(infile,0)); break; /* height pixel height */
5251
              case 4: temp = get_string(infile,1);
18557 bpr 5252
                tmp_buffer=my_newmem(MAX_BUFFER);
5253
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_video(%d,%d,%d,%d,%d,\"%s\");\n",canvas_root_id,int_data[0],int_data[1],int_data[2],int_data[3],temp));
18552 bpr 5254
                add_to_buffer(tmp_buffer);
5255
                break;
5256
              default:break;
5257
            }
5258
          }
5259
          reset();
5260
          break;
5261
        case X_AXIS_STRINGS:
5262
  /*
18556 bpr 5263
  @ xaxis num1:string1:num2:string2:num3:string3:num4:string4:....num_n:string_n
5264
  @ alternative: xaxistext
5265
  @ usable for commands <a href="#numberline">numberline</a> and <a href="#grid">grid</a> or combinations thereof
5266
  @ use these x-axis num1...num_n values instead of default xmin...xmax
5267
  @ in case of command ''grid``. there is no need to use keyword <a href="#axisnumbering">axisnumbering</a>
5268
  @ use command <a href="#axis">axis</a> to have visual x/y-axis lines (see command <a href="#grid">grid</a>
5269
  @ use command ''fontcolor``, ''fontfamily`` to adjust font <br>defaults: black,12,Arial<br>note: command ''fontsize`` is not active for this command.(''fontsize`` can be used for the <a href="#legend">legend</a> in a <a href="#grid">grid</a>)
5270
  @ a javascript error message will flag non-matching value:name pairs
5271
  @ if the ''x-axis words`` are too big and will overlap, a simple alternating offset will be applied
5272
  @ to be used before command grid (see <a href="#grid">command grid</a>)
5273
  @ ''xmajor`` steps should be synchronised with numbers eg. ''1`` in the next example <code>grid 1,100,grey,1,4,6,grey</code>
5274
  @%xaxistext%size 800,200%xrange -1,13%yrange -5,10%axis%xaxistext 1:january:2:february:3:march:4:april:5:may:6:june:7:july:8:august:9:september:10:october:11:november:12:december%grid 1,4,grey,1,2,10,red
18552 bpr 5275
  */
5276
          use_axis_numbering++;
5277
          temp = get_string(infile,1);
5278
          if( strstr(temp,":") != 0 ){ temp = str_replace(temp,":","\",\"");}
5279
          if( strstr(temp,"pi") != 0 ){ temp = str_replace(temp,"pi","(3.1415927)");}/* we need to replace pi for javascript y-value*/
5280
          fprintf(js_include_file,"x_strings[%d] = [\"%s\"];x_strings_up[%d] = null;",use_axis_numbering,temp,use_axis_numbering);
5281
          break;
5282
        case X_AXIS_STRINGS_UP:
5283
  /*
18556 bpr 5284
  @ xaxisup num1:string1:num2:string2:num3:string3:num4:string4:....num_n:string_n
5285
  @ alternative: xaxistextup
5286
  @ the text will be rotated 90&deg; up
5287
  @ no need to use keyword <a href="#axisnumbering">axisnumbering</a>
5288
  @ use command <a href="#axis">axis</a> to have visual x/y-axis lines (see command <a href="#grid">grid</a>
5289
  @ use these x-axis num1...num_n values instead of default xmin...xmax
5290
  @ use command ''fontcolor``, <a href="#fontfamily">fontfamily</a> to adjust font <br>defaults: black,12,Arial<br>note: command ''fontsize`` is not active for this command.(''fontsize`` can be used for the <a href="#legend">legend</a> in a <a href="#grid">grid</a>)
5291
  @ a javascript error message will flag non-matching value:name pairs
5292
  @ if the ''x-axis words`` are too big, they will overlap the graph<br> (in this case the text will start from ysize upwards)
5293
  @ to be used before command grid (see <a href="#grid">command grid</a>)
5294
  @''xmajor`` steps should be synchronised with numbers eg. "1" in the next example <code>grid 1,100,grey,1,4,6,grey</code>
5295
  @%xaxistextup%size 800,300%xrange -1,13%yrange -10,10%fontfamily Italic 18pt Courier%axis%xaxistextup 1:january:2:february:3:march:4:april:5:may:6:june:7:july:8:august:9:september:10:october:11:november:12:december%grid 1,4,grey,1,2,10,red
18552 bpr 5296
  */
5297
          use_axis_numbering++;
5298
          temp = get_string(infile,1);
5299
          if( strstr(temp,":") != 0 ){ temp = str_replace(temp,":","\",\"");}
5300
          if( strstr(temp,"pi") != 0 ){ temp = str_replace(temp,"pi","(3.1415927)");}/* we need to replace pi for javascript y-value*/
5301
          fprintf(js_include_file,"x_strings_up[%d] = 1;x_strings[%d] = [\"%s\"];",use_axis_numbering,use_axis_numbering,temp);
5302
          break;
5303
        case XERRORBARS:
5304
  /*
5305
  @ xerrorbars color,E1,E2,x1,y1,x2,y2,...,x_n,y_n
5306
  @ draw multiple points with x-errorbars E1 (error value left from point) and E2 (error value right from point) at given coordinates in color 'color'
5307
  @ the errors E1 and E2 values are in xrange.
5308
  @ use command ''linewidth int`` to adust size
5309
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually (!)
5310
  @%xerrorbars%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%drag xy%xerrorbars red,0.8,1.3,0,0,1,1,2,3,3,2,4,5,5,2,6,1,-1,-2,-2,0,-3,2,-4,4,-5,-1
8386 schaersvoo 5311
 
18552 bpr 5312
  */
5313
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
5314
          fill_color = stroke_color;
5315
          i=0;
5316
          while( ! done ){     /* get next item until EOL*/
5317
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
5318
            if(i%2 == 0 ){
5319
                double_data[i] = get_real(infile,0); /* x */
5320
            }
5321
            else {
5322
              double_data[i] = get_real(infile,1); /* y */
5323
            }
5324
            i++;
5325
          }
5326
          decimals = find_number_of_digits(precision);
5327
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
5328
          for(c = 2 ; c < i-1 ; c = c+2){
18557 bpr 5329
            tmp_buffer=my_newmem(MAX_BUFFER);
5330
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,20,[%.*f],[%.*f],[%.2f],[%.2f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+1],double_data[0],double_data[1],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,1,0,0,0,use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18552 bpr 5331
            add_to_buffer(tmp_buffer);
5332
            /* object_cnt++; */
5333
            if(onclick != 0){object_cnt++;}
5334
          }
5335
          reset();
5336
          dragstuff[20] = 1;
5337
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
5338
          break;
5339
        case NEWRANGE:
5340
  /*
5341
  @ newrange xmin,xmax,ymin,ymax
5342
  @ objects defined after command will make use of this new range
5343
  @ https://wimsedu.info/?topic=dessiner-des-portions-de-fonctions-sur-un-meme-graphe
5344
  */
5345
          for(i = 0 ; i<4; i++){
5346
            switch(i){
5347
              case 0: xmin = get_real(infile,0);break;
5348
              case 1: xmax = get_real(infile,0);break;
5349
              case 2: ymin = get_real(infile,0);break;
5350
              case 3: ymax = get_real(infile,1);break;
5351
              default: break;
5352
            }
5353
          }
18557 bpr 5354
          tmp_buffer=my_newmem(MAX_BUFFER);
5355
          check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "\n\nxmin = %f;xmax = %f;ymin = %f;ymax = %f;\n\n",xmin,xmax,ymin,ymax));
18552 bpr 5356
          add_to_buffer(tmp_buffer);
5357
          break;
5358
        case XRANGE:
5359
  /*
5360
  @ xrange xmin,xmax
5361
  @ alternative: rangex
5362
  @ if not given: 0,xsize (eg in pixels)
5363
  */
18556 bpr 5364
          for(i = 0 ; i<2; i++){
5365
            switch(i){
5366
              case 0: xmin = get_real(infile,0);break;
5367
              case 1: xmax = get_real(infile,1);break;
5368
              default: break;
5369
            }
5370
          }
5371
          if(xmin >= xmax){canvas_error(" xrange is not OK: xmin &lt; xmax !");}
5372
          fprintf(js_include_file,"var xmin = %f;var xmax = %f;",xmin,xmax);
5373
          found_size_command++;
5374
          break;
18552 bpr 5375
        case XSNAPTOGRID:
5376
  /*
18556 bpr 5377
  @ xsnaptogrid
5378
  @ keyword (no arguments required)
5379
  @ a draggable object (use command ''drag x|y|xy``) will snap to the given x-grid values when dragged (mouseup)
5380
  @ in case of userdraw the drawn points will snap to xmajor grid
5381
  @ if no grid is defined, points will snap to every integer xrange value. (eg snap_x=1)
5382
  @ if you do not want a visible grid, but you only want a ''snaptogrid`` with some value...define this grid with opacity 0.
5383
  @ if xminor is defined (use keyword ''axis`` to activate xminor), the drawing will snap to xminor <br>use only even dividers in x-minor...for example<br><code>xsnaptogrid<br>axis<br>grid 2,1,grey,4,4,7,red</code><br> will snap on x=0, x=0.5, x=1, x=1.5 ....<br> will snap on y=0, y=0.25 y=0.5 y=0.75 ...<br>
5384
  @%xsnaptogrid_1%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 2%xsnaptogrid%userdraw segments,red%precision 1%display x,red,12
5385
  @%xsnaptogrid_2%size 400,400%xrange -10,10%yrange -10,10%grid 1,1,grey%linewidth 3%drag x%points red,0,0,0,0,0,0,0,0,0,0
5386
*/
5387
          use_snap = 2;
5388
          break;
18552 bpr 5389
        case XOFFSET:
5390
  /*
18556 bpr 5391
  @ xoffset
5392
  @ keyword ; to place the text centered above the text coordinates(x:y) ...
5393
  @ may be used for points or other things requiring centered labels
5394
  @ use <a href="#fontfamily">fontfamily</a> for setting the font
5395
  @ may be active for commands <a href="#text">text</a> and <a href="#string">string</a> (e.g. objects in the drag/drop/onclick-library)
18552 bpr 5396
  @%xoffset%size 400,400%xrange -10,10%yrange -10,10%fontfamily 12pt Arial%string blue,-9,-9,no offset%point -9,-9,red%centered%string blue,-6,-6,centered%point -6,-6,red%xoffset%string blue,-3,-3,xoffset%point -3,-3,red%yoffset%string blue,0,0,yoffset%point 0,0,red%xyoffset%string blue,3,3,xyoffset%point 3,3,red%resetoffset%string blue,6,6,resetoffset%point 6,6,red
5397
  */
18556 bpr 5398
          use_offset = 2;
5399
          break;
18552 bpr 5400
        case XYOFFSET:
5401
  /*
18556 bpr 5402
  @ xyoffset
5403
  @ keyword ; to place the text (x:y) to (x+dx:y+dy)... dx/dy are dependent on fontsize/fontfamily
5404
  @ may be used for points or other things requiring labels
5405
  @ use <a href="#fontfamily">fontfamily</a> for setting the font
5406
  @ only active for commands <a href="#text">text</a> and <a href="#string">string</a> (e.g. objects in the drag/drop/onclick-librariy
5407
  @ in case of inputfields the inputfield will be centered x and y on its coordinates.<br>for example:<br>inputs 1,1,10,? <br>point 1,1,red <br> the point will be completely invisible<br>note: keyword ''xyoffset`` will also provide centering if used with <a href='#userdraw'>input(s),color</a>
5408
  @%xyoffset%size 400,400%xrange -10,10%yrange -10,10%fontfamily 12pt Arial%string blue,-9,-9,no offset%point -9,-9,red%centered%string blue,-6,-6,centered%point -6,-6,red%xoffset%string blue,-3,-3,xoffset%point -3,-3,red%yoffset%string blue,0,0,yoffset%point 0,0,red%xyoffset%string blue,3,3,xyoffset%point 3,3,red%resetoffset%string blue,6,6,resetoffset%point 6,6,red
18552 bpr 5409
  */
18556 bpr 5410
          use_offset = 3;
5411
          break;
18552 bpr 5412
        case XUNIT:
5413
  /*
18556 bpr 5414
  @ xunit some_unit_for_x-values
5415
  @ unicode allowed (no html code)
5416
  @ use together with command <a href="#display">display or mouse</a>
5417
  @ will display the cursor x-coordinate in ''unit``
5418
  @%xunit%size 400,400%xrange -10,10%yrange -10,10%xunit cm \\u00B2%grid 2,2,grey%linewidth 2%userdraw segments,blue%display x,blue,18
18552 bpr 5419
  */
18556 bpr 5420
          fprintf(js_include_file,"unit_x = \"%s\";",get_string(infile,1));
5421
          break;
18552 bpr 5422
        case XLABEL:
5423
  /*
5424
  @ xlabel some_string
5425
  @ will be used to create a label for the x-axis (label is in quadrant I)
5426
  @ can only be used together with command ''grid``<br>not depending on keywords ''axis`` and ''axisnumbering``
5427
  @ font setting: italic Courier, fontsize will be slightly larger (fontsize + 4)<br>use command ''fontsize`` to adjust.<br>(command ''fontfamily`` is not active for this command)
5428
  @ use <a href="#ylabel">ylabel</a>
5429
  @%xlabel%size 400,400%xrange -10,10%yrange -10,10%axis%axisnumbering%xlabel cm\\u00B2 %ylabel v\\u00B2 %precision 1%grid 2,2,grey,2,2,5,grey
5430
  */
18556 bpr 5431
          temp = get_string(infile,1);
5432
          fprintf(js_include_file,"var xaxislabel = \"%s\";",temp);
5433
          break;
18552 bpr 5434
        case XLOGBASE:
5435
  /*
5436
  @ xlogbase number
5437
  @ sets the logbase number for the x-axis
5438
  @ default value 10
5439
  @ use together with commands xlogscale / xylogscale
5440
  */
18556 bpr 5441
          fprintf(js_include_file,"xlogbase=%d;",(int)(get_real(infile,1)));
5442
          break;
18552 bpr 5443
        case XLOGSCALE:
5444
  /*
18556 bpr 5445
  @ xlogscale ymajor,yminor,majorcolor,minorcolor
5446
  @ the x/y-range are set using commands <code>xrange xmin,xmax</code> and <code>yrange ymin,ymax</code>
5447
  @ ymajor is the major step on the y-axis; yminor is the divisor for the y-step
5448
  @ the linewidth is set using command ''linewidth int``
5449
  @ the opacity of major / minor grid lines is set by command <a href='#opacity'>opacity</a>
5450
  @ default logbase number = 10 ... when needed, set the logbase number with command ''xlogbase number``
18627 bpr 5451
  @ the x/y- axis numbering is triggered by keyword ''axisnumbering``<ul><li>use command ''precision`` before ''xlogscale`` command to set the precision (decimals) of the axis numbering</li><li>use commands ''xlabel some_text`` and/or ''ylabel some_text`` for text on axis: use command ''fontsize int`` to set the fontsize (default 12px)</li><li>use command ''fontfamily fnt_family_string`` to set the fonts for axis-numbering</li><li>use command ''fontcolor`` to set the color</li></ul>
18556 bpr 5452
  @ note: the complete canvas will be used for the ''log paper``
5453
  @ note: userdrawings are done in the log paper, e.g. javascript:read_canvas() will return the real values
5454
  @ note: command ''mouse color,fontsize`` will show the real values in the logpaper.<br>\
5455
  @ note: when using something like ''xrange 0.0001,0.01``...combined with commands <a href='#mouse'>mouse</a> and/or <a href='#userdraw'>userdraw</a>...<br> make sure the <a href='#precision'>precision</a> is set accordingly
5456
  @ note: in case of userdraw, the use of keyword <a href='#userinput_xy'>userinput_xy</a> may be handy !
5457
  @ <b>attention</b>: keyword ''snaptogrid`` may not lead to the desired result...
5458
  @ <b>attention</b>: do not use command ''zoom``
5459
  @%xlogscale%size 400,400%xrange 10,50000%yrange -5,5%xlabel x-axis%ylabel y-axis%xlogscale 10,1,black,grey%display x,red,22
18552 bpr 5460
  */
18556 bpr 5461
          use_axis_numbering++;if(use_axis_numbering > 1){use_axis_numbering = 1;}
5462
          if( js_function[DRAW_GRID] == 1 ){canvas_error("only one type of grid is allowed...");}
5463
          js_function[DRAW_XLOGSCALE] = 1;
5464
          for(i=0;i<4;i++){
5465
            switch(i){
5466
              case 0: double_data[0] = get_real(infile,0);break; /* xmajor */
5467
              case 1: int_data[0] = (int) (get_real(infile,0));break; /* xminor */
5468
              case 2: stroke_color = get_color(infile,0); break;
5469
              case 3: fill_color = get_color(infile,1);
18557 bpr 5470
                tmp_buffer=my_newmem(MAX_BUFFER);
5471
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_grid%d(%d,%d,\"%s\",\"%s\",%.2f,%.2f,%d,\"%s\",\"%s\",%d,%f,%d,%d); ",canvas_root_id,GRID_CANVAS,line_width,stroke_color,fill_color,stroke_opacity,fill_opacity,font_size,font_family,font_color,use_axis_numbering,double_data[0],int_data[0],precision));
18556 bpr 5472
                fprintf(js_include_file,"use_xlogscale=1;snap_y = %f;snap_x = xlogbase;",double_data[0]/int_data[0]);
5473
                add_to_buffer(tmp_buffer);
5474
                break;
5475
              default:break;
5476
            }
5477
          }
5478
          break;
18552 bpr 5479
        case XYLOGSCALE:
5480
  /*
18556 bpr 5481
  @ xylogscale majorcolor,minorcolor
5482
  @ the x/y-range are set using commands ''xrange xmin,xmax`` and ''yrange ymin,ymax``
5483
  @ the linewidth is set using command ''linewidth int``
5484
  @ the opacity of major / minor grid lines is set by command ''opacity [0-255],[0-255]``
5485
  @ default logbase number = 10 ... when needed, set the logbase number with command ''xlogbase number`` and/or ''ylogbase number``
18627 bpr 5486
  @ the x/y- axis numbering is triggered by keyword ''axisnumbering``<ul><li>use commands ''xlabel some_text`` and/or ''ylabel some_text`` for text on axis: use command ''fontsize int`` to set the fontsize (default 12px)</li><li>use command ''fontfamily fnt_family_string`` to set the fonts for axis-numbering</li><li>use command ''fontcolor`` to set the color</li></ul>
18556 bpr 5487
  @ note: the complete canvas will be used for the ''log paper``
5488
  @ note: userdrawings are done in the log paper, e.g. javascript:read_canvas() will return the real values
5489
  @ note: command ''mouse color,fontsize`` will show the real values in the logpaper.<br>\
5490
  @ note: when using something like ''yrange 0.0001,0.01``...combined with commands ''mouse color,fontsize`` and/or ''userdraw type,color``...<br> make sure the precision is set accordingly (eg command ''precision 10000``)
5491
  @ note: in case of userdraw, the use of keyword ''userinput_xy`` may be handy !
5492
  @ <b>attention</b>: keyword ''snaptogrid`` may not lead to the desired result...
5493
  @ <b>attention</b>: do not use command ''zoom``
5494
  @%xylogscale%size 400,400%xrange 10,50000%yrange 10,50000%xlabel x-axis%ylabel y-axis%xylogscale black,grey%display xy,red,22
18552 bpr 5495
  */
18556 bpr 5496
          use_axis_numbering++;if(use_axis_numbering > 1){use_axis_numbering = 1;}
5497
          if( js_function[DRAW_GRID] == 1 ){canvas_error("only one type of grid is allowed...");}
5498
          js_function[DRAW_XYLOGSCALE] = 1;
5499
          for(i=0;i<2;i++){
5500
            switch(i){
5501
              case 0: stroke_color = get_color(infile,0); break;
5502
              case 1: fill_color = get_color(infile,1);
18557 bpr 5503
                tmp_buffer=my_newmem(MAX_BUFFER);
5504
                check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_grid%d(%d,%d,\"%s\",\"%s\",%.2f,%.2f,%d,\"%s\",\"%s\",%d,%d); ",canvas_root_id,GRID_CANVAS,line_width,stroke_color,fill_color,stroke_opacity,fill_opacity,font_size,font_family,font_color,use_axis_numbering,precision));
18556 bpr 5505
                fprintf(js_include_file,"use_xlogscale=1;use_ylogscale=1;snap_x = xlogbase;snap_y = ylogbase;");
5506
                add_to_buffer(tmp_buffer);
5507
                break;
5508
              default:break;
5509
            }
5510
          }
5511
          break;
18552 bpr 5512
        case Y_AXIS_STRINGS:
5513
  /*
18556 bpr 5514
  @ yaxis num1:string1:num2:string2:num3:string3:num4:string4:....num_n:string_n
5515
  @ alternative: yaxistext
5516
  @ use command ''fontcolor``, ''fontfamily`` to adjust font <br>defaults: black,12,Arial<br> note: command ''fontsize`` is not active for this command.(''fontsize`` can be used for the <a href="#legend">legend</a> in a <a href="#grid">grid</a>)
5517
  @ no need to use keyword <a href="#axisnumbering">axisnumbering</a>
5518
  @ use command <a href="#axis">axis</a> to have visual x/y-axis lines (see command <a href="#grid">grid</a>
5519
  @ use these y-axis num1...num_n values instead of default ymin...ymax
5520
  @ a javascript error message will flag non-matching value:name pairs
5521
  @ to be used before command grid (see <a href="#grid">command grid</a>)
5522
  @%yaxistext%size 400,400%yrange 0,13%xrange -100,500%axis%yaxis 1:january:2:february:3:march:5:may:6:june:7:july:8:august:9:september:10:october:11:november:12:december%#'ymajor' steps should be synchronised with numbers eg. "1" in this example%grid 100,1,grey,4,1,6,grey
18552 bpr 5523
  */
18556 bpr 5524
          temp = get_string(infile,1);
5525
          if( strstr(temp,":") != 0 ){ temp = str_replace(temp,":","\",\"");}
5526
          if( strstr(temp,"pi") != 0 ){ temp = str_replace(temp,"pi","(3.1415927)");}/* we need to replace pi for javascript y-value*/
5527
          fprintf(js_include_file,"y_strings = [\"%s\"];\n ",temp);
5528
          use_axis_numbering++;
5529
          break;
18552 bpr 5530
        case YERRORBARS:
5531
  /*
5532
  @ yerrorbars color,E1,E2,x1,y1,x2,y2,...,x_n,y_n
5533
  @ draw multiple points with y-errorbars E1 (error value under point) and E2 (error value above point) at given coordinates in color 'color'
5534
  @ the errors E1 and E2 values are in yrange.
5535
  @ use command ''linewidth int`` to adust size
5536
  @ may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually (!)
5537
  @%yerrorbars%size 400,400%xrange -10,10%yrange -10,10%linewidth 2%onclick%yerrorbars red,0.8,1.3,0,0,1,1,2,3,3,2,4,5,5,2,6,1,-1,-2,-2,0,-3,2,-4,4,-5,-1
5538
  */
5539
      stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
5540
      fill_color = stroke_color;
5541
      i=0;
5542
      while( ! done ){     /* get next item until EOL*/
18556 bpr 5543
        if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
5544
        if(i%2 == 0 ){
5545
            double_data[i] = get_real(infile,0); /* x */
5546
        }
5547
        else
5548
        {
5549
            double_data[i] = get_real(infile,1); /* y */
5550
        }
5551
        i++;
18552 bpr 5552
      }
5553
      if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
5554
      for(c = 2 ; c < i-1 ; c = c+2){
18557 bpr 5555
        tmp_buffer=my_newmem(MAX_BUFFER);
5556
        check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "dragstuff.addShape(new Shape(%d,%d,%d,%d,19,[%.*f],[%.*f],[%.2f],[%.2f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+1],double_data[0],double_data[1],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,1,0,0,0,use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18556 bpr 5557
        add_to_buffer(tmp_buffer);
18552 bpr 5558
    /* object_cnt++; */
18556 bpr 5559
        if(onclick != 0){object_cnt++;}
18552 bpr 5560
      }
5561
      decimals = find_number_of_digits(precision);
5562
      reset();
5563
      dragstuff[19] = 1;
5564
      if(use_dragstuff == 0 ){ use_dragstuff = 1;}
5565
      break;
5566
        case YOFFSET:
5567
  /*
18556 bpr 5568
  @ yoffset
5569
  @ keyword; to place the text centered above the text coordinates(x:y) ...
5570
  @ may be used for points or other things requiring centered labels
5571
  @ use <a href="#fontfamily">fontfamily</a> for setting the font
5572
  @ may be active for commands <a href="#text">text</a> and <a href="#string">string</a> (e.g. objects in the drag/drop/onclick-library)
5573
  @%yoffset%size 400,400%xrange -10,10%yrange -10,10%fontfamily 12pt Arial%string blue,-9,-9,no offset%point -9,-9,red%centered%string blue,-6,-6,centered%point -6,-6,red%xoffset%string blue,-3,-3,xoffset%point -3,-3,red%yoffset%string blue,0,0,yoffset%point 0,0,red%xyoffset%string blue,3,3,xyoffset%point 3,3,red%resetoffset%string blue,6,6,resetoffset%point 6,6,red
18552 bpr 5574
  */
18556 bpr 5575
          use_offset = 1;
5576
          break;
18552 bpr 5577
        case YRANGE:
5578
  /*
5579
  @ yrange ymin,ymax
5580
  @ alternative: rangey
5581
  @ if not given 0,ysize (eg in pixels)
5582
  */
18556 bpr 5583
          for(i = 0 ; i<2; i++){
5584
            switch(i){
5585
              case 0: ymin = get_real(infile,0);break;
5586
              case 1: ymax = get_real(infile,1);break;
5587
              default: break;
5588
            }
5589
          }
5590
          if(ymin >= ymax){canvas_error(" yrange is not OK: ymin &lt; ymax !<br>");}
5591
          fprintf(js_include_file,"var ymin = %f;var ymax = %f;",ymin,ymax);
5592
          found_size_command++;
5593
          break;
18552 bpr 5594
        case YSNAPTOGRID:
5595
  /*
18556 bpr 5596
  @ ysnaptogrid
5597
  @ keyword (no arguments required)
5598
  @ a draggable object (use command ''drag x|y|xy``) will snap to the given y-grid values when dragged (mouseup)
5599
  @ in case of userdraw the drawn points will snap to ymajor grid
5600
  @ if no grid is defined, points will snap to every integer yrange value. (eg snap_y=1)
5601
  @ if you do not want a visible grid, but you only want a ''snaptogrid`` with some value...define this grid with opacity 0.
5602
  @ if yminor is defined (use keyword ''axis`` to activate yminor), the drawing will snap to yminor <br>use only even dividers in y-minor...for example<br><code>ysnaptogrid<br>axis<br>grid 2,1,grey,4,4,7,red</code><br> will snap on x=0, x=0.5, x=1, x=1.5 ....<br> will snap on y=0, y=0.25 y=0.5 y=0.75 ...<br>
5603
  @%ysnaptogrid_1%size 400,400%xrange -10,10%yrange -10,10%ysnaptogrid%grid 1,1,grey%linewidth 2%userdraw crosshairs,blue%css font-size:8px;color:blue%clearbutton delete all crosshairs
5604
  @%ysnaptogrid_2%size 400,400%xrange -10,10%yrange -10,10%ysnaptogrid%grid 1,1,grey%linewidth 3%drag y%points red,0,0,0,0,0,0,0,0,0,0
18552 bpr 5605
  */
18556 bpr 5606
          use_snap = 3;
5607
          break;
18552 bpr 5608
        case YLABEL:
5609
  /*
5610
  @ ylabel some_string
5611
  @ will be used to create a (vertical) label for the y-axis (label is in quadrant I)
5612
  @ can only be used together with command <a href="#grid">grid</a><br>not depending on keywords ''axis`` and ''axisnumbering``
5613
  @ font setting: italic Courier, fontsize will be slightly larger (fontsize + 4)<br>use command ''fontsize`` to adjust (command ''fontsize`` is not active for this command)
5614
  @ use <a href="#xlabel">xlabel</a>
5615
  @%ylabel%size 400,400%xrange -10,10%yrange -10,10%fontsize 8%axis%axisnumbering%precision 1%xlabel x-axis%ylabel y-axis%grid 1,1,grey,2,2,2,red
5616
  */
18556 bpr 5617
          temp = get_string(infile,1);
5618
          fprintf(js_include_file,"var yaxislabel = \"%s\";",temp);
5619
          break;
18552 bpr 5620
        case YLOGBASE:
5621
  /*
5622
  @ ylogbase number
5623
  @ sets the logbase number for the y-axis
5624
  @ default value 10
5625
  @ use together with commands ylogscale / xylogscale
5626
  */
5627
          fprintf(js_include_file,"ylogbase=%d;",(int)(get_real(infile,1)));
5628
          break;
5629
        case YLOGSCALE:
5630
  /*
18556 bpr 5631
  @ ylogscale xmajor,xminor,majorcolor,minorcolor
5632
  @ the x/y-range are set using commands ''xrange xmin,xmax`` and ''yrange ymin,ymax``
5633
  @ xmajor is the major step on the x-axis; xminor is the divisor for the x-step
5634
  @ the linewidth is set using command ''linewidth int``
5635
  @ the opacity of major / minor grid lines is set by command ''opacity [0-255],[0-255]``
5636
  @ default logbase number = 10 ... when needed, set the logbase number with command ''ylogbase number``
5637
  @ the x/y- axis numbering is triggered by keyword ''axisnumbering``<ul><li>use command ''precision`` before ''ylogscale`` command to set the precision (decimals) of the axis numbering</li><li>use commands ''xlabel some_text`` and/or ''ylabel some_text`` for text on axis: use command ''fontsize int`` to set the fontsize (default 12px)</li><li>use command ''fontfamily fnt_family_string`` to set the fonts for axis-numbering</li><li>use command ''fontcolor`` to set the color</li></ul>
5638
  @ note: the complete canvas will be used for the ''log paper``
5639
  @ note: userdrawings are done in the log paper, e.g. javascript:read_canvas() will return the real values
5640
  @ note: command ''mouse color,fontsize`` will show the real values in the logpaper.<br>\
5641
  @ note: when using something like ''yrange 0.0001,0.01``...combined with commands ''mouse color,fontsize`` and/or ''userdraw type,color``...<br> make sure the precision is set accordingly (eg command ''precision 10000``)
5642
  @ note: in case of userdraw, the use of keyword ''userinput_xy`` may be handy !
5643
  @ <b>attention</b>: do not use command ''zoom``
5644
  @ <b>attention</b>: keyword ''snaptogrid`` may not lead to the desired result...
18552 bpr 5645
  */
18555 bpr 5646
        use_axis_numbering++;if(use_axis_numbering > 1){use_axis_numbering = 1;}
5647
        if( js_function[DRAW_GRID] == 1 ){canvas_error("only one type of grid is allowed...");}
5648
        js_function[DRAW_YLOGSCALE] = 1;
5649
        for(i=0;i<4;i++){
5650
          switch(i){
5651
            case 0: double_data[0] = get_real(infile,0);break; /* xmajor */
5652
            case 1: int_data[0] = (int) (get_real(infile,0));break; /* xminor */
5653
            case 2: stroke_color = get_color(infile,0); break;
5654
            case 3: fill_color = get_color(infile,1);
18557 bpr 5655
              tmp_buffer=my_newmem(MAX_BUFFER);
5656
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER, "draw_grid%d(%d,%d,\"%s\",\"%s\",%.2f,%.2f,%d,\"%s\",\"%s\",%d,%f,%d,%d); ",canvas_root_id,GRID_CANVAS,line_width,stroke_color,fill_color,stroke_opacity,fill_opacity,font_size,font_family,font_color,use_axis_numbering,double_data[0],int_data[0],precision));
18555 bpr 5657
              fprintf(js_include_file,"use_ylogscale=1;snap_x = %f;snap_y = ylogbase;",double_data[0]/int_data[0]);
5658
              add_to_buffer(tmp_buffer);
5659
               break;
5660
            default:break;
5661
            }
5662
          }
5663
          break;
18552 bpr 5664
        case YUNIT:
5665
  /*
18556 bpr 5666
  @ yunit some_unit_for_y-values
5667
  @ unicode allowed (no html code)
5668
  @ use together with command mousey
5669
  @ will display the cursor y-coordinate in ''unit``
18552 bpr 5670
  */
5671
          fprintf(js_include_file,"unit_y = \"%s\";",get_string(infile,1));
5672
          break;
18555 bpr 5673
        case HYPSEGMENTS:
18556 bpr 5674
  /*
5675
  @ hypsegments color,x1,y1,x2,y2,...,x_n,y_n
5676
  @ draw multiple hyperbolic segments in the Poincaré disk between points (x1:y1)--(x2:y2).....and... (x_n-1:y_n-1)--(x_n:y_n) in color ''color``
18639 schaersvoo 5677
  @ use command ''linewidth int`` to adjust size may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a> individually (!)
18556 bpr 5678
  @%hypsegments%size 400,400%xrange -1,1%yrange -1,1%circles black,0,0,1%linewidth 2%hypsegments green,0.1,-0.3,0.6,0.7,0.3,0,-0.8,0.6,0.6,0.5,-0.5,0.6
18639 schaersvoo 5679
  */
18555 bpr 5680
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
5681
          fill_color = stroke_color;
5682
          i=0;
5683
          while( ! done ){     /* get next item until EOL*/
5684
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
5685
              if(i%2 == 0 ){
5686
                double_data[i] = get_real(infile,0); /* x */
5687
              }
5688
            else {
5689
              double_data[i] = get_real(infile,1); /* y */
5690
            }
5691
            i++;
5692
          }
5693
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
5694
          if(use_affine == TRUE ){ transform(i-1,2);}
5695
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
5696
          decimals = find_number_of_digits(precision);
5697
          for(c = 0 ; c < i-1 ; c = c+4){
18569 bpr 5698
            tmp_buffer=my_newmem(MAX_BUFFER);
18555 bpr 5699
            if (hypgeodaux(double_data+c,res,0)){
5700
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,12,[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,res[0],decimals,res[0],decimals,res[1],decimals,res[1],decimals,res[2],decimals,res[3],decimals,res[4],decimals,res[5],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
5701
            }
5702
            else {
5703
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],line_width,stroke_color,stroke_opacity,stroke_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
5704
            }
5705
            add_to_buffer(tmp_buffer);
5706
            if(onclick != 0){object_cnt++;}
5707
          }
5708
          reset();
5709
          dragstuff[4] = 1;dragstuff[12] = 1;
5710
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
5711
          break;
5712
        case HYPLINES:
18639 schaersvoo 5713
  /*
18555 bpr 5714
  @ hyplines color,x1,y1,x2,y2...x_n-1,y_n-1,x_n,y_n
18639 schaersvoo 5715
  @ draw multiple hyperbolic lines in the Poincaré disk through points (x1:y1)--(x2:y2) ...(x_n-1:y_n-1)--(x_n:y_n) in color 'color' may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
18555 bpr 5716
  @%hyplines%size 400,400%xrange -1,1%yrange -1,1%circles black,0,0,1%hyplines green,0,0.1,0.1,0.3,0.2,0.3,0.1,0.3,0,0.5,-0.5,0.4
5717
  */
5718
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
5719
          fill_color = stroke_color;
5720
          i=0;
5721
          while( ! done ){     /* get next item until EOL*/
5722
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
18562 bpr 5723
            if(i%2 == 0 ){
5724
              double_data[i] = get_real(infile,0); /* x */
5725
            }
18555 bpr 5726
            else {
5727
              double_data[i] = get_real(infile,1); /* y */
5728
            }
5729
            i++;
5730
          }
5731
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
5732
          if(use_affine == TRUE ){ transform(i-1,2);}
5733
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
18623 bpr 5734
          if(fillcolor) {fill_color=fillcolor;} else {fill_color=stroke_color;}
18555 bpr 5735
          decimals = find_number_of_digits(precision);
5736
          for(c = 0 ; c < i-1 ; c = c+4){
18569 bpr 5737
            tmp_buffer=my_newmem(MAX_BUFFER);
18555 bpr 5738
            if (hypgeodaux(double_data+c,res,1)){
5739
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,12,[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,res[0],decimals,res[0],decimals,res[1],decimals,res[1],decimals,res[2],decimals,res[3],decimals,res[4],decimals,res[5],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));}
5740
            else {
18623 bpr 5741
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,res[0],decimals,res[2],decimals,res[1],decimals,res[3],line_width,stroke_color,stroke_opacity,fill_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18555 bpr 5742
            }
5743
            add_to_buffer(tmp_buffer);
5744
            if(onclick != 0){object_cnt++;}
5745
          }
5746
          reset();
5747
          dragstuff[4] = 1;dragstuff[12] = 1;
5748
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
5749
          break;
5750
        case HYPPOLY:
18639 schaersvoo 5751
    /*
5752
    @ hyppolygon color,x1,y1,x2,y2...x_n-1,y_n-1,x_n,y_n
5753
    @ draw hyperbolicpolygon in the Poincaré disk through points (x1:y1)--(x2:y2) ...(x_n-1:y_n-1)--(x_n:y_n) -- (x1:y1)  in color 'color' may be set <a href="#drag">draggable</a> / <a href="#onclick">onclick</a>
18615 bpr 5754
    @ option fhyppolygon only for convex polygon for the moment
5755
    @%hyppolygon%size 400,400%xrange -1,1%yrange -1,1%circles black,0,0,1%hyppolygon green,0,0,0.5,0.3,0.8,-0.1,0.4,-0.5
18639 schaersvoo 5756
    */
18615 bpr 5757
          stroke_color=get_color(infile,0);
18555 bpr 5758
          fill_color = stroke_color;
5759
          i=0;
5760
          while( ! done ){     /* get next item until EOL*/
5761
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
5762
            if(i%2 == 0 ){
5763
              double_data[i] = get_real(infile,0); /* x */
5764
            }
5765
            else {
5766
              double_data[i] = get_real(infile,1); /* y */
5767
            }
5768
            i++;
5769
          }
5770
          /* il faut rajouter le premier point à la fin*/
5771
          double_data[i]=double_data[0]; double_data[i+1]=double_data[1];
5772
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
5773
          if(use_affine == TRUE ){ transform(i-1,2);}
5774
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
5775
          decimals = find_number_of_digits(precision);
5776
          for(c = 0 ; c < i-1 ; c = c+2){
18615 bpr 5777
            tmp_buffer=my_newmem(MAX_BUFFER);
18555 bpr 5778
            if (hypgeodaux(double_data+c,res,0)){
18615 bpr 5779
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,12,[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,res[0],decimals,res[0],decimals,res[1],decimals,res[1],decimals,res[2],decimals,res[3],decimals,res[4],decimals,res[5],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18555 bpr 5780
            }
5781
            else {
18623 bpr 5782
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+2],decimals,double_data[c+1],decimals,double_data[c+3],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18555 bpr 5783
            }
5784
            add_to_buffer(tmp_buffer);
5785
            if(onclick != 0){object_cnt++;}
18615 bpr 5786
          }
5787
          if(use_filled){
5788
            hypgeodaux(double_data+2,res,0);
5789
            res[4]=double_data[0]; res[5]=double_data[1];
5790
            hypgeodaux(res+4,res,0);
5791
            add_js_filltoborder(canvas_type);
5792
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"setTimeout(function(){filltoborder (%.*f,%.*f,[%s,%d],[%s,%d],%d,false,null);},1000);\n",decimals,res[6],decimals,res[7],fill_color,(int) (fill_opacity/0.0039215),fill_color,(int) (fill_opacity/0.0039215),FILL_CANVAS+fill_cnt));
5793
            add_to_buffer(tmp_buffer);
18663 bpr 5794
            fill_cnt++;
5795
          }
18569 bpr 5796
          dragstuff[4] = 1; dragstuff[12] = 1;
18555 bpr 5797
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
5798
          reset();
5799
          break;
5800
        case HYPRAYS:
5801
  /*
18556 bpr 5802
  @ hyprays color,xc,yc,x1,y1,x2,y2,x3,y3...x_n,y_n
18639 schaersvoo 5803
  @ draw hyperbolic rays in the Poincaré disk in color 'color' and center (xc:yc) may be set draggable or onclick (every individual ray)
18556 bpr 5804
  @%hyprays%size 400,400%xrange -1,1%yrange -1,1%circles black,0,0,1%onclick%hyprays blue,0.5,0.5,0.3,0.9,-0.3,0.5,-0.4,0,0.4,-0.9,-0.8,0.1,-0.1,-0.9
18639 schaersvoo 5805
  */
5806
  /*
18555 bpr 5807
   hyprays_onclick%size 400,400%xrange -1,1%yrange -1,1%circles black,0,0,1%onclick%hyprays blue,0.5,0.5,0.3,0.9,-0.3,0.5,-0.4,0,0.4,-0.9,-0.8,0.1,-0.1,-0.9
5808
   hyprays_drag_xy%size 400,400%xrange -1,1%yrange -1,1%circles black,0,0,1%drag xy%hyprays blue,0,0,0.3,0.9,-0.3,0.5,-0.4,0,0.4,-0.9,-0.8,0.1,-0.1,-0.9
5809
  */
5810
          stroke_color=get_color(infile,0);
18623 bpr 5811
          if(fillcolor) {fill_color=fillcolor;} else {fill_color=stroke_color;}
18555 bpr 5812
          double_data[0] = get_real(infile,0);/* xc */
5813
          double_data[1] = get_real(infile,0);/* yc */
5814
          i=2;
18562 bpr 5815
          while( ! done ){ /* get next item until EOL*/
18555 bpr 5816
            if(i > MAX_INT - 1){canvas_error("in command rays too many points / rays in argument: repeat command multiple times to fit");}
5817
            if(i%2 == 0 ){
5818
              double_data[i] = get_real(infile,0); /* x */
5819
            }
5820
            else {
5821
              double_data[i] = get_real(infile,1); /* y */
5822
            }
5823
            fprintf(js_include_file,"/* double_data[%d] = %f */\n",i,double_data[i]);
5824
            i++;
5825
          }
5826
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,2);}
5827
          if(use_affine == TRUE ){ transform(i-1,2);}
5828
          if( i%2 != 0 ){canvas_error("in command rays: unpaired x or y value");}
5829
          decimals = find_number_of_digits(precision);
5830
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
5831
          for(c=2; c<i;c = c+2){
18557 bpr 5832
            tmp_buffer=my_newmem(MAX_BUFFER);
18555 bpr 5833
            double_data[2]=double_data[c];double_data[3]=double_data[c+1];
5834
            if (hypgeodaux(double_data,res,0)){
5835
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,12,[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],[%.*f,%.*f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,res[0],decimals,res[0],decimals,res[1],decimals,res[1],decimals,res[2],decimals,res[3],decimals,res[4],decimals,res[5],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
5836
            }
5837
            else {
18623 bpr 5838
              check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,4,[%.*f,%.*f],[%.*f,%.*f],[30,30],[30,30],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[0],decimals,double_data[c],decimals,double_data[1],decimals,double_data[c+1],line_width,stroke_color,stroke_opacity,fill_color,stroke_opacity,0,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18555 bpr 5839
            }
5840
            add_to_buffer(tmp_buffer);
5841
            /* object_cnt++; */
5842
            if(onclick != 0){object_cnt++;}
5843
          }
5844
          reset();
5845
          dragstuff[4] = 1; dragstuff[12] = 1;
5846
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
5847
          break;
5848
        case HYPCIRCLES:
5849
        /*
5850
  @ hypcircles color,xc1,yc1,r1,xc2,yc2,r2...xc_n,yc_n,r_n
5851
  @ draw hyperbolic circles in Poincaré disk
5852
  @ <b>attention</b> r = radius in x-range (!)
5853
  @ use keyword <code>filled</code> or command <code>fhypcircles</code> to produce solid circles
5854
  @ use command <code>fillcolor color</code> to set the fillcolor
5855
  @%hypcircles%size 400,400%xrange -1,1%yrange -1,1%filled%fillcolor lightblue%opacity 255,50%hypcircles blue,0,0,1,0.4,0.4,3,0.2,0.6,6
18639 schaersvoo 5856
  */
5857
  /*
18555 bpr 5858
  hypcircles_drag%size 400,400%xrange -1,1%yrange -1,1%filled%fillcolor lightblue%opacity 255,50%drag xy%hypcircles blue,0,0,2,0.2,0.2,3,0.2,0.2,5%zoom red
5859
  hypcircles_onclick%size 400,400%xrange -1,1%yrange -1,1%filled%fillcolor lightblue%opacity 255,50%onclick%hypcircles blue,0,0,2,0.2,0.2,3,0.2,0.2,5%zoom red
5860
  hypcircles_drag_slider%size 400,400%xrange -1,1%yrange -1,1%linewidth 2%drag xy%# Click circles(s) to activate%opacity 200,50%fillcolor orange%rotationcenter 2,3%slider 0,2*pi,300,30,angle degrees,Rotate%slider -5,5*pi,300,30,x display,move in x-direction%slider -10,10*pi,300,30,y display,move in y-direction%hypcircles blue,0,0,2,0.2,0.2,3,0.2,0.2,5
5861
  */
5862
          stroke_color=get_color(infile,0); /* how nice: now the color comes first...*/
18623 bpr 5863
          if(fillcolor) {fill_color=fillcolor;} else {fill_color=stroke_color;}
18555 bpr 5864
          i=1;
18562 bpr 5865
          while( ! done ){ /* get next item until EOL*/
18555 bpr 5866
            if(i > MAX_INT - 1){canvas_error("too many points in argument: repeat command multiple times to fit");}
5867
              switch (i%3){
5868
                case 1:double_data[i-1] = get_real(infile,0);break; /* x */
5869
                case 2:double_data[i-1] = get_real(infile,0);break; /* y */
5870
                case 0:double_data[i-1] = get_real(infile,1);break; /* r */
5871
              }
5872
            i++;
5873
          }
5874
          if(use_rotate == TRUE ){rotate(i-1,angle,rotationcenter,3);}
5875
          if(use_affine == TRUE ){ transform(i-1,3);}
5876
          if( use_slider != -1 && onclick == 0){ onclick = 3; }/* no drag&onclick but slideable */
5877
          decimals = find_number_of_digits(precision);
5878
          for(c = 0 ; c < i-1 ; c = c+3){
18556 bpr 5879
            double Z2=double_data[c]*double_data[c]+double_data[c+1]*double_data[c+1];//[Z]^2
18555 bpr 5880
            double R=tanh(double_data[c+2]/2);double R2=R*R;
5881
            double den=1-R2*Z2; double XY=(1-R2)/den;
5882
            double_data[c]=XY*double_data[c];
5883
            double_data[c+1]=XY*double_data[c+1];
5884
            double_data[c+2]=(1-Z2)/den*R;
18557 bpr 5885
            tmp_buffer=my_newmem(MAX_BUFFER);
18623 bpr 5886
            check_string_length(snprintf(tmp_buffer,MAX_BUFFER,"dragstuff.addShape(new Shape(%d,%d,%d,%d,13,[%.*f],[%.*f],[%.3f],[%.3f],%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d,%d,%d,%.1f,\"%s\",%d,\"%s\",%s,%s,%d));\n",drag_type,object_cnt,onclick,use_snap,decimals,double_data[c],decimals,double_data[c+1],double_data[c+2],double_data[c+2],line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype[0],dashtype[1],use_rotate,angle,flytext,font_size,font_family,my_sliders,rotation_center,use_offset));
18555 bpr 5887
            add_to_buffer(tmp_buffer);
5888
            if(onclick != 0){object_cnt++;}/* object_cnt++; */
5889
          }
5890
          reset();
5891
          dragstuff[13] = 1;
5892
          if(use_dragstuff == 0 ){ use_dragstuff = 1; }
5893
          break;
18552 bpr 5894
        case ZOOM:
5895
  /*
18556 bpr 5896
  @ zoom button_color
5897
  @ introduce a very small ''controlpanel`` at the lower right corner (font size of the panel is fixed to: 22px Arial)
5898
  @ giving six 15&times;15px ''active`` rectangle areas<br>(''&times;,&darr;,&uarr;,&larr;,&rarr;,&minus;,+``) for zooming and/or panning of the image
5899
  @ a mouse wheel is active for in/out zooming. Drag panning is not supported (this will conflict with many ''userdraw`` or ''multidraw`` primitives)
5900
  @ the ''controlpanel`` is not active for a ''userdraw`` mousedown (but it can interfere with some ''userdraw`` types)
5901
  @ the ''&times;`` symbol will reset to your original xmax/xmin ymax/ymin values.
5902
  @ choose an appropriate color, so the small ''&times;,&darr;,&uarr;,&larr;,&rarr;,&minus;,+`` are clearly visible
5903
  @ command ''opacity`` may be used to set stroke_opacity of buttons
5904
  @ note: on zooming, text will not increase / decrease the font size (todo??)
5905
  @ note: adding ''zooming`` will increase the size of the javascript include with approx. 11 kb
18552 bpr 5906
  */
18556 bpr 5907
         js_function[INTERACTIVE] = 1;
18552 bpr 5908
          js_function[JS_ZOOM] = 1;
5909
          if( use_userdraw == 1 ){
5910
            js_function[USERDRAW_AND_ZOOM] = 1;
5911
            fprintf(js_include_file,"forbidden_zone = [%d,%d];",xsize-115,ysize - 20);
5912
          }
5913
          if(jsplot_cnt != -1){ js_function[JSPLOT_AND_ZOOM] = 1;}
5914
          stroke_color = get_color(infile,1);
5915
          /* we use BG_CANVAS (0) */
5916
          add_js_zoom_buttons(stroke_color,stroke_opacity);
5917
          done = TRUE;
5918
          break;
11806 schaersvoo 5919
 
5920
/* ready */
18552 bpr 5921
        default:sync_input(infile);
5922
        break;
5923
      }
7614 schaersvoo 5924
    }
5925
  /* we are done parsing script file */
18556 bpr 5926
    if(use_dragstuff != 0){
18562 bpr 5927
  /* add the 20kb drag code: nearly always used ... use_dragstuff==1: no-mouse ! */
18556 bpr 5928
      add_drag_code(DRAG_CANVAS,use_dragstuff,dragstuff,reply_format);
5929
      if(js_function[JS_ZOOM] == 1){
15111 schaersvoo 5930
        js_function[DRAG_AND_ZOOM] = 1;
18556 bpr 5931
      }
15111 schaersvoo 5932
  }
15116 bpr 5933
 
14066 bpr 5934
  /* check if xrange / yrange was set explicit ... or use xmin=0 xmax=xsize ymin=0 ymax=ysize: Quadrant I */
18556 bpr 5935
    if( found_size_command == 1 ){
5936
      fprintf(js_include_file,"var xmin = 0;var xmax = %d;var ymin = 0;var ymax = %d",xsize,ysize);
7983 schaersvoo 5937
    }
18556 bpr 5938
    else
5939
    {
5940
      if( found_size_command != 3 ){
5941
        canvas_error("Please specify size first and then both xrange and yrange ...");
5942
      }
5943
    }
8257 schaersvoo 5944
 
18562 bpr 5945
  /* if needed, add generic draw functions (grid / xml etc) to buffer: these are no draggable/clickable shapes / objects ! */
18556 bpr 5946
    add_javascript_function();
7614 schaersvoo 5947
   /* add read_canvas() etc functions if needed */
18556 bpr 5948
    if( reply_format > 0 ){ add_read_canvas(reply_format,reply_precision);}
7797 schaersvoo 5949
  /* no zoom, just add buffer */
18556 bpr 5950
    fprintf(js_include_file,"\n/* add buffer */\n%s};\n/* end wims_canvas_function */\nwims_canvas_function%d();\n",buffer,canvas_root_id);
7614 schaersvoo 5951
/* done writing the javascript include file */
18556 bpr 5952
    fclose(js_include_file);
5953
    }
7614 schaersvoo 5954
 
5955
/* if using a tooltip, this should always be printed to the *.phtml file, so stdout */
18556 bpr 5956
    if( use_tooltip > 0 ){
5957
      if( use_tooltip == 1 ){
5958
        add_js_tooltip(tooltip_text,bgcolor);
5959
      }
5960
      else
5961
      {
5962
      if( use_tooltip == 2 ){
5963
        add_js_popup(getfile_cmd);
5964
      }
5965
    }
9329 schaersvoo 5966
  }
18556 bpr 5967
  exit(EXIT_SUCCESS);
7614 schaersvoo 5968
}
5969
/* end main() */
5970
 
5971
/******************************************************************************
5972
**
5973
**  sync_input
5974
**
5975
**  synchronises input line - reads to end of line, leaving file pointer
5976
**  at first character of next line.
5977
**
5978
**  Used by:
5979
**  main program - error handling.
5980
**
5981
******************************************************************************/
5982
void sync_input(FILE *infile)
5983
{
18552 bpr 5984
  int c = 0;
7614 schaersvoo 5985
 
18552 bpr 5986
  if( c == '\n' || c == ';' ) return;
5987
  while( ( (c=getc(infile)) != EOF ) && (c != '\n') && (c != '\r') && (c != ';')) ;
5988
  if( c == EOF ) finished = 1;
5989
  if( c == '\n' || c == '\r' || c == ';') line_number++;
5990
  return;
7614 schaersvoo 5991
}
5992
 
5993
/******************************************************************************/
15111 schaersvoo 5994
void transform(int num,int incr){
5995
/*.
5996
only "double_data[]" is used for transformations !!
5997
*/
5998
 int i;int ii;double x,y;
5999
 for(i=0;i<num;i = i+incr){
6000
  ii = i+1;
6001
  x = double_data[i]*affine_matrix[0] + double_data[ii]*affine_matrix[1]+affine_matrix[4];
6002
  y = double_data[i]*affine_matrix[2] + double_data[ii]*affine_matrix[3]+affine_matrix[5];
15601 schaersvoo 6003
 /*
17351 bpr 6004
  printf("(%f:%f) &rarr; (%f:%f)<br>",double_data[i],double_data[ii],x,y);
15601 schaersvoo 6005
 */
15111 schaersvoo 6006
  double_data[i] = x;
6007
  double_data[ii] = y;
6008
 }
6009
}
6010
 
6011
void rotate(int num,double angle,double center[],int incr){
6012
 int i;int ii;double rad = angle * 0.0174532925199;
6013
 double c = cos(rad);
6014
 double s = sin(rad);
6015
 double x,y;
6016
 for(i=0;i<num;i = i+incr){
6017
  ii = i+1;
6018
  x = c*(double_data[i]-center[0]) + s*(double_data[ii] - center[1] ) + center[0];
6019
  y = c*(double_data[ii]-center[1]) - s*(double_data[i] - center[0] ) + center[1];
6020
  double_data[i] = x;
6021
  double_data[ii] = y;
17351 bpr 6022
 // printf("(x:y) - (%f:%f)<br>",x,y);
15111 schaersvoo 6023
 }
6024
}
6025
/* not used: see transform()
6026
void translate(int num){
6027
 int i;int ii;
6028
 double x,y;
6029
 for(i=0;i<num;i = i+2){
6030
  ii = i+1;
6031
  x = double_data[i] + affine_matrix[4];
6032
  y = double_data[ii] + affine_matrix[5];
6033
  double_data[i] = x;
6034
  double_data[ii] = y;
6035
 }
6036
}
6037
*/
7614 schaersvoo 6038
char *str_replace(const char *str, const char *old, const char *new){
18562 bpr 6039
  if(strlen(str) > MAX_BUFFER){canvas_error("string argument too big");}
6040
  char *ret, *r;
6041
  const char *p, *q;
6042
  size_t oldlen = strlen(old);
6043
  size_t count = 0;
6044
  size_t retlen = 0;
6045
  size_t newlen = strlen(new);
6046
  if (oldlen != newlen){
6047
    for (count = 0, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen){
18552 bpr 6048
      count++;
6049
      retlen = p - str + strlen(p) + count * (newlen - oldlen);
18562 bpr 6050
    }
18552 bpr 6051
  }
18562 bpr 6052
  else {
6053
    retlen = strlen(str);
6054
  }
6055
  if ((ret = malloc(retlen + 1)) == NULL){
6056
    ret = NULL;
6057
    canvas_error("string argument is NULL");
6058
  }
6059
  else
6060
  {
6061
    for (r = ret, p = str; (q = strstr(p, old)) != NULL; p = q + oldlen) {
18552 bpr 6062
      size_t l = q - p;
6063
      memcpy(r, p, l);
6064
      r += l;
6065
      memcpy(r, new, newlen);
6066
      r += newlen;
18562 bpr 6067
    }
6068
    strcpy(r, p);
18552 bpr 6069
  }
18562 bpr 6070
  return ret;
7614 schaersvoo 6071
}
6072
 
6073
/******************************************************************************/
7848 bpr 6074
 
7614 schaersvoo 6075
char *get_color(FILE *infile , int last){
18562 bpr 6076
  int c,i = 0,is_hex = 0;
6077
  char temp[MAX_COLOR_STRING], *string;
6078
  const char *not_allowed = "0123456789";
6079
  while(( (c=getc(infile)) != EOF ) && ( c != '\n') && ( c != ',' ) && ( c != ';' )  && ( c != '\t' ) ){
6080
    if( i > MAX_COLOR_STRING ){ canvas_error("colour string is too big ... ? ");}
6081
    if( c == '#' ){
18552 bpr 6082
      is_hex = 1;
18562 bpr 6083
    }
6084
    if( c != ' '){
18552 bpr 6085
      if( is_hex == 0 ){if(strchr(not_allowed,c) != 0){canvas_error("found something like a number...but is should have been a colour or #hex color number...<br>Do not use R,G,B !!! ");}}
6086
      temp[i]=tolower(c);
6087
      i++;
18562 bpr 6088
    }
18552 bpr 6089
  }
18562 bpr 6090
  if( ( c == '\n' || c == EOF || c == ';' || c == '\t' ) && last == 0){canvas_error("expecting more arguments in command");}
6091
  if( c == '\n' || c == ';'  || c == '\t' ){ done = TRUE; line_number++; }
6092
  if( c == EOF ){finished = 1;}
6093
  if( finished == 1 && last != 1 ){ canvas_error("expected more arguments");}
6094
  temp[i]='\0';
6095
  if( strlen(temp) == 0 ){ canvas_error("expected a colorname or hexnumber, but found nothing !!");}
6096
  if( is_hex == 1 ){
6097
    char red[3], green[3], blue[3];
6098
    red[0]   = toupper(temp[1]); red[1]   = toupper(temp[2]); red[2]   = '\0';
6099
    green[0] = toupper(temp[3]); green[1] = toupper(temp[4]); green[2] = '\0';
6100
    blue[0]  = toupper(temp[5]); blue[1]  = toupper(temp[6]); blue[2]  = '\0';
6101
    int r = (int) strtol(red,   NULL, 16);
6102
    int g = (int) strtol(green, NULL, 16);
6103
    int b = (int) strtol(blue,  NULL, 16);
6104
    int L0 = 1+snprintf(NULL,0,"%d,%d,%d",r,g,b);
6105
    string = my_newmem(L0);
6106
    snprintf(string,L0,"%d,%d,%d",r,g,b);
6107
    return string;
6108
  }
6109
  else
6110
  {
6111
    string = (char *)my_newmem(sizeof(temp));
6112
    snprintf(string,sizeof(temp),"%s",temp);
6113
    for( i = 0; i < NUMBER_OF_COLORNAMES ; i++ ){
18552 bpr 6114
      if( strcmp( colors[i].name , string ) == 0 ){
18562 bpr 6115
        return colors[i].rgb;
18552 bpr 6116
      }
18562 bpr 6117
    }
6118
    canvas_error("I was expecting a color name or hexnumber...but found nothing.");
18552 bpr 6119
  }
18562 bpr 6120
  return "0,0,255";
7614 schaersvoo 6121
}
6122
 
14066 bpr 6123
char *get_string(FILE *infile,int last){ /* last = 0: more arguments ; last=1 final argument */
18562 bpr 6124
  int c,i=0;
6125
  char  temp[MAX_BUFFER], *string;
6126
  while(( (c=getc(infile)) != EOF ) && ( c != '\n') && ( c != '\t') ){
6127
    temp[i]=c;
6128
    i++;
6129
    if(i > MAX_BUFFER){ canvas_error("string size too big...repeat command to fit string");break;}
6130
  }
6131
  if( ( c == '\n' ||  c == '\t'  || c == EOF ) && last == 0){
6132
    canvas_error("expecting more arguments in command");}
6133
  if( c == '\n' ||  c == '\t') { done = TRUE; line_number++; }
6134
  if( c == EOF ) {finished = 1;}
6135
  temp[i]='\0';
6136
  if( strlen(temp) == 0 && last != 3 ){
6137
    canvas_error("expected a word or string, but found nothing!");}
6138
  string=(char *)my_newmem(strlen(temp));
6139
  snprintf(string,sizeof(temp),"%s",temp);
6140
  return string;
7614 schaersvoo 6141
}
6142
 
14066 bpr 6143
char *get_string_argument(FILE *infile,int last){  /* last = 0: more arguments ; last=1 final argument */
18562 bpr 6144
  int c,i=0;
6145
  char temp[MAX_BUFFER], *string;
6146
  while(( (c=getc(infile)) != EOF ) && ( c != '\n') && ( c != '\t') && ( c != ',')){
6147
    temp[i]=c;
6148
    i++;
6149
    if(i > MAX_BUFFER){ canvas_error("string size too big...will cut it off");break;}
6150
  }
6151
  if( ( c == '\n' || c == EOF) && last == 0){canvas_error("expecting more arguments in command");}
6152
  if( c == '\n' || c == '\t' ) { line_number++; }
6153
  if( c == EOF ) {finished = 1;}
6154
  if( finished == 1 && last == 0 ){ canvas_error("expected more arguments");}
6155
  temp[i]='\0';
10953 bpr 6156
/*
18562 bpr 6157
  17.10.2014 removed (question Perrin)
6158
  may cause some unwanted effects...
6159
  if( strlen(temp) == 0 ){ canvas_error("expected a word or string (without comma), but found nothing !!");}
8322 schaersvoo 6160
*/
18562 bpr 6161
  string=(char *)my_newmem(sizeof(temp));
6162
  snprintf(string,sizeof(temp),"%s",temp);
6163
  done = TRUE;
6164
  return string;
7614 schaersvoo 6165
}
6166
 
14066 bpr 6167
double get_real(FILE *infile, int last){ /* accept anything that looks like an number ?  last = 0: more arguments ; last=1 final argument */
18562 bpr 6168
  int c,i=0,found_calc = 0;
6169
  double y;
6170
  char tmp[MAX_INT];
6171
  /*
6172
   these things are 'allowed functions': *,^,+,-,/,(,),e,arc,cos,tan,pi,log,ln,sqrt,abs
6173
   but there should be a better way to avoid segfaults !
6174
  */
6175
  const char *allowed = "earcostanpilogqb*+-/^()";/* assuming these are allowed stuff in a 'number'*/
6176
  const char *not_allowed = "#dfhjkmuvwxyz{}[]%&~!$";/* avoid segmentation faults in a "atof()" and "wims eval" */
6177
  while(( (c=getc(infile)) != EOF ) && ( c != ',') && (c != '\n') && (c != '\t') && ( c != ';')){
6178
    if( c != ' ' ){
8224 bpr 6179
      if( i == 0 &&  c == '+' ){
18562 bpr 6180
        continue;
8224 bpr 6181
      }
7614 schaersvoo 6182
      else
6183
      {
18562 bpr 6184
        c = tolower(c);
6185
        if( strchr(not_allowed,c) != 0 ){canvas_error("found a character not associated with a number...");}
6186
        if( strchr(allowed,c) != 0 ){found_calc = 1;}/* hand the string over to wims eval() */
6187
        tmp[i] = c;
6188
        i++;
7614 schaersvoo 6189
      }
6190
    }
18562 bpr 6191
    if( i > MAX_INT - 1){canvas_error("number too large");}
6192
  }
6193
  if( ( c == '\n' || c == EOF || c == ';' || c == '\t' ) && last == 0){canvas_error("expecting more arguments in command");}
6194
  if( c == '\n' || c == ';' || c == '\t' ){ done = TRUE; line_number++; }
6195
  if( c == EOF ){done = TRUE ; finished = 1;}
6196
  tmp[i]='\0';
6197
  if( strlen(tmp) == 0 ){canvas_error("expected a number, but found nothing !!");}
6198
  if( found_calc == 1 ){ /* use wims eval to calculate 2*pi/3 */
6199
    void *f = eval_create(tmp);
6200
    assert(f);if( f == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;}
6201
    y = eval_x(f, 1);
6202
    /* if function is bogus; y = 1: so no core dumps */
6203
    eval_destroy(f);
6204
  }
6205
  else
6206
  {
6207
   y = atof(tmp);
6208
  }
6209
  return y;
7614 schaersvoo 6210
}
6211
void canvas_error(char *msg){
18562 bpr 6212
  fprintf(stdout,"\n</script><hr><span style=\"color:red\">FATAL syntax error: line %d: %s</span><hr>",line_number,msg);
6213
  finished = 1;
6214
  exit(EXIT_SUCCESS);
7614 schaersvoo 6215
}
6216
/* convert x/y coordinates to pixel */
6217
int x2px(double x){
18606 bpr 6218
  int res=(x-xmin)/(xmax-xmin)*xsize;
6219
  return (res==xsize)?xsize-1:res;
7614 schaersvoo 6220
}
6221
int y2px(double y){
18606 bpr 6222
  int res=(ymax-y)/(ymax-ymin)*ysize;
6223
  return (res==ysize)?ysize-1:res;
7614 schaersvoo 6224
}
6225
double px2x(int x){
18562 bpr 6226
  return (x*(xmax - xmin)/xsize + xmin);
7614 schaersvoo 6227
}
6228
double px2y(int y){
18562 bpr 6229
  return (y*(ymax - ymin)/ysize + ymin);
7614 schaersvoo 6230
}
6231
void add_to_buffer(char *tmp){
17351 bpr 6232
//fprintf(stdout,"tmp = %s<br>buffer = %s<br>",tmp,buffer);
18562 bpr 6233
  if( tmp == NULL || tmp == 0 ){ canvas_error("nothing to add_to_buffer()...");}
6234
  /*  do we have enough space left in buffer[MAX_BUFFER] ? */
6235
  int space_left = (int) (sizeof(buffer) - strlen(buffer));
6236
  if( space_left > strlen(tmp)){
6237
    strncat(buffer,tmp,space_left - 1);/* add safely "tmp" to the string buffer */
6238
  }
6239
  else
6240
  {
6241
    canvas_error("your memory buffer is too big<br>simplify your script...it produces too many lines ");
6242
  }
6243
  tmp = NULL;free(tmp);
6244
  return;
7614 schaersvoo 6245
}
6246
void reset(){
18562 bpr 6247
  if(no_reset == FALSE){ /* 8/5/2020 */
6248
    use_filled = FALSE;
6249
    use_dashed = FALSE;
6250
    if(onclick != 4 ){onclick = 0;} /* slider param 'active'... onclick=4 */
6251
    drag_type = -1;
6252
    use_offset = 0;
18623 bpr 6253
    fillcolor = FALSE;
18562 bpr 6254
  }
7614 schaersvoo 6255
}
15111 schaersvoo 6256
char *getMML(char *tex){
18562 bpr 6257
  int my_pipe[2];pid_t pid;
6258
  if(pipe(my_pipe)){canvas_error("mathml(): pipe() failure.\n");}
15111 schaersvoo 6259
  pid = fork();
6260
  if (pid == (pid_t) 0){
18562 bpr 6261
    char *argv[]={"wims_mathml","--use-zoom","0","--tex-size 100%","--max-mml-size","1024","--tex-string",tex,NULL};
6262
    close(my_pipe[0]);dup2(my_pipe[1], 1);dup2(my_pipe[1], 2);close(my_pipe[1]);
6263
    execv("../bin/wims_mathml",argv);canvas_error("could not execute wims_mathml\n");
15111 schaersvoo 6264
  }
6265
  else
15116 bpr 6266
  {
18562 bpr 6267
    if (pid < (pid_t) 0){
6268
      close(my_pipe[0]);close(my_pipe[1]);canvas_error("mathml(): fork() failure.\n");
6269
    }
6270
    int status;FILE *stream;close(my_pipe[1]);stream = fdopen (my_pipe[0], "r");
6271
    char buffer[MAX_BUFFER+1];memset(buffer,'\0',MAX_BUFFER);
6272
    fgets(buffer, MAX_BUFFER, stream);
6273
    int L0 = 1 + snprintf(NULL,0,"%s", buffer);
6274
    tex = my_newmem(L0);memset(tex,'\0',L0);
6275
    snprintf(tex,L0,"%s",buffer);
6276
    fclose (stream);close(my_pipe[0]);waitpid(pid, &status, 0);
15111 schaersvoo 6277
  }
18562 bpr 6278
  return tex;
15111 schaersvoo 6279
}
7614 schaersvoo 6280
 
15111 schaersvoo 6281
char *getSVGMOL(char *inputtype,char *keys){
6282
  int idx;
6283
  char *forbidden[] = {"-O","-H","-z","-L","-o","-m"};
6284
  char *argv[1+strlen(keys)];
6285
  argv[0] = "obabel"; argv[1] = "-i"; argv[2] = inputtype;
6286
  idx = 3;int i;
6287
  char *ptr = strtok(keys,",");
6288
  while(ptr != NULL ){
6289
    for(i = 0 ; i < 6; i++ ){if( strncmp(ptr,forbidden[i],2) == 0 ){return "NOT ALLOWED ARGUMENT";}}
6290
    argv[idx] = ptr; idx++;
17351 bpr 6291
    if(idx > 18){canvas_error("too many arguments for obabel....see docs<br>");}
15111 schaersvoo 6292
    ptr = strtok(NULL,",");
6293
  }
6294
  /* last arguments; no 'javascript', only 'svg to STDOUT' and 'NULL' */
6295
  argv[idx] = "-xj";argv[idx+1] = "-o"; argv[idx+2] = "svg";argv[idx+3] = NULL;
6296
  int link[2];
6297
  pid_t pid;
6298
  char buffer[MAX_BUFFER+1];
6299
  memset(buffer,'\0',MAX_BUFFER);
6300
  if (pipe(link)==-1){canvas_error("pipe");}
6301
  if ((pid = fork()) == -1){canvas_error("fork");}
15116 bpr 6302
 
15111 schaersvoo 6303
  char *svgmol = "error";
6304
  int string_length = 0;
15116 bpr 6305
 
15111 schaersvoo 6306
  if(pid == 0) {
6307
    dup2 (link[1], STDOUT_FILENO);
6308
    dup2(link[0],  STDERR_FILENO);/* remove annoying messages '1 molecule converted' */
6309
    close(link[0]);
6310
    close(link[1]);
6311
    execvp("obabel",argv);
6312
  } else {
6313
    close(link[1]);
18109 schaersvoo 6314
    read(link[0],buffer, sizeof(buffer));
15111 schaersvoo 6315
    close(link[0]);
6316
    /* need to remover newline from svg-string on freebsd */
6317
    char *pch = strstr(buffer, "\n");
6318
    while(pch != NULL){
18555 bpr 6319
      strncpy(pch, " ", 1);
6320
      pch = strstr(buffer, "\n");
15111 schaersvoo 6321
    }
6322
    string_length = 1 + snprintf(NULL,0,"%s",buffer);
6323
    svgmol= my_newmem(string_length);
6324
    snprintf(svgmol,string_length,"%s",buffer);
6325
    wait(NULL);
6326
  }
18562 bpr 6327
  return svgmol;
15111 schaersvoo 6328
}
6329
/* GNU libmatheval library for evaluating mathematical functions. */
15601 schaersvoo 6330
char *eval(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int plotsteps,int precision,double rotationcenter[]){
18555 bpr 6331
  void *f;
6332
  double x;
6333
  double y;
6334
  double xorg;
6335
  int xv;
6336
  int i = 0;
6337
  int xstep =(int)(xsize/plotsteps);
6338
  if( xstep == 0 ){xstep = 1;}
6339
  double a = (xmax - xmin)/xsize;
6340
  f = eval_create(fun);
6341
  assert (f);
6342
  if( f == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;}
6343
  /* we supply the true x/y values...draw_curve() will convert these (x:y) to pixels : used for pan/scale */
6344
  double xydata[MAX_BUFFER+1];/* hmmm */
6345
  int lim_ymin =(int)( ymin - 4*fabs(ymin));/* 19-4-2015 replacing "abs" by "fabs"*/
6346
  int lim_ymax =(int)( ymax + 4*fabs(ymax));/* 19-4-2015 replacing "abs" by "fabs"*/
6347
  double c = 1.0;double s = 1.0;
6348
  if( use_rotate == TRUE ){s = sin(angle*0.0174533);c = cos(angle*0.0174533);}
6349
  for ( xv = 0 ;xv < xsize ; xv = xv+xstep ){
18562 bpr 6350
    x = (double) (xv*a + xmin);
6351
    xorg = x;
6352
    if( i < MAX_BUFFER - 2){
18552 bpr 6353
      y = eval_x(f, x);
6354
      if(y < lim_ymax && y > lim_ymin ){
18562 bpr 6355
        if( use_affine == TRUE ){
6356
          x = x*affine_matrix[0] + y*affine_matrix[1]+affine_matrix[4];
6357
          y = xorg*affine_matrix[2] + y*affine_matrix[3]+affine_matrix[5];
6358
        }
6359
        if( use_rotate == TRUE){
6360
          x = (c * (x - rotationcenter[0])) + (s * (y - rotationcenter[1])) + rotationcenter[0];
6361
          y = (c * (y - rotationcenter[1])) - (s * (xorg - rotationcenter[0])) + rotationcenter[1];
6362
        }
6363
        xydata[i++] = x;
18552 bpr 6364
        xydata[i++] = y;
6365
      }
18562 bpr 6366
    }
6367
    else
6368
    {
18552 bpr 6369
      canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps or some other means to reduce the amount of data... ");
18562 bpr 6370
    }
18552 bpr 6371
  }
18562 bpr 6372
  eval_destroy(f);
6373
  return double_xy2js_array(xydata,i,find_number_of_digits(precision));
15111 schaersvoo 6374
}
18663 bpr 6375
static int filtre (int a, int b, int c, int d){
6376
  return ((a>0)||(b>0)||(c>0)||(d>0))&&((a<0)||(b<0)||(c<0)||(d<0));
6377
}
18669 bpr 6378
/* plot a levelcurve
6379
  modified 08/2025 bernardi */
6380
char *eval_levelcurve(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int levelstep,int precision,double level){
18562 bpr 6381
  void *f = eval_create(fun);
6382
  if( f == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;}
18669 bpr 6383
  int ptx=xsize/levelstep, pty=ysize/levelstep;
6384
  double dx = (xmax - xmin)/ptx;
6385
  double dy = (ymax - ymin)/pty;
6386
  int sgns[(ptx+1)*(pty+1)];
18664 bpr 6387
  double x, y, diff, xydata[MAX_BUFFER+1];
18663 bpr 6388
  int i, j, k;
18669 bpr 6389
  for (j = 0; j <= ptx; ++j)
6390
    for (k = 0; k <= pty; ++k){
18665 bpr 6391
      x = xmin + j*dx;
6392
      y = ymin + k*dy;
6393
      diff = eval_x_y(f,x,y) - level;
18669 bpr 6394
      sgns[k+j*(pty+1)] = (diff > 0) ? 1 : -(diff < 0);
18663 bpr 6395
    };
6396
  i = 0;
18669 bpr 6397
  for (j = 0; j < ptx; ++j)
6398
    for (k = 0; k < pty; ++k){
6399
      int b = k+j*(pty+1);
6400
      if(filtre(sgns[b],sgns[b+1],sgns[b+pty+1],sgns[b+pty+2])){
18663 bpr 6401
        if (i >= MAX_BUFFER)
6402
          canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps, decrease image size...\nor some other means to reduce the amount of data... ");
6403
        xydata[i++] = xmin+j*dx;
6404
        xydata[i++] = ymin+k*dy;
18552 bpr 6405
      }
18562 bpr 6406
    }
6407
  eval_destroy(f);
6408
  return double_xy2js_array(xydata,i,find_number_of_digits(precision));
15111 schaersvoo 6409
}
7614 schaersvoo 6410
 
15111 schaersvoo 6411
/* plot parametric function */
18562 bpr 6412
char *eval_parametric(int xsize,int ysize,char *fun1,char* fun2,double xmin,
6413
  double xmax,double ymin,double ymax,
6414
  double tmin,double tmax,int plotsteps,int precision,double rotationcenter[]){
6415
  void *fx;
6416
  void *fy;
6417
  double t;
6418
  int i = 0;
6419
  double tstep = (tmax-tmin)/plotsteps;
6420
  if( tstep == 0 ){canvas_error("zero step for t variable : reduce plotsteps or inrease trange");}
6421
  fx = eval_create(fun1);
6422
  fy = eval_create(fun2);
6423
  assert(fx);
6424
  assert(fy);
6425
  if( fx == NULL || fy == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;}
15111 schaersvoo 6426
    /* we supply the true x/y values...draw_curve() will convert these (x:y) to pixels : used for pan/scale */
18664 bpr 6427
 double xydata[MAX_BUFFER+1];/* hmmm */
18562 bpr 6428
 double x; /* real x-values */
6429
 double y; /* real y-values */
6430
 double xorg;
6431
 /*
6432
 29/12/2020
6433
 disabled to try and synchronise curve+affine behaviour in complex scripts produced by "elec, tool circuit" (BPR)
15623 schaersvoo 6434
    int lim_ymin =(int)( ymin - 4*fabs(ymin));
6435
    int lim_ymax =(int)( ymax + 4*fabs(ymax));
6436
    */
18562 bpr 6437
  double c = 1.0;double s = 1.0;
6438
  if( use_rotate == TRUE ){s = sin(angle*0.0174533);c = cos(angle*0.0174533);}
6439
  for( t = tmin ;t <= tmax ; t = t + tstep ){
6440
    if( i < MAX_BUFFER - 2 ){
18552 bpr 6441
      y = eval_t(fy, t);
6442
  /*    if(y > lim_ymin && y < lim_ymax){*/
18562 bpr 6443
      x = eval_t(fx, t);
6444
      if( x == x){ /* no NaN */
6445
        xorg = x;
6446
        if( use_affine == TRUE ){
6447
          x = x*affine_matrix[0] + y*affine_matrix[1]+affine_matrix[4];
6448
          y = xorg*affine_matrix[2] + y*affine_matrix[3]+affine_matrix[5];
6449
        }
6450
        if( use_rotate == TRUE){
6451
          x = (c * (x - rotationcenter[0])) + (s * (y - rotationcenter[1])) + rotationcenter[0];
6452
          y = (c * (y - rotationcenter[1])) - (s * (xorg - rotationcenter[0])) + rotationcenter[1];
6453
        }
6454
        xydata[i++] = x;
6455
        xydata[i++] = y;
6456
      }
6457
  /*    } */
18552 bpr 6458
    }
18562 bpr 6459
    else
6460
    {
18552 bpr 6461
      canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps or some other means to reduce the amount of data... ");
18562 bpr 6462
    }
18552 bpr 6463
  }
18562 bpr 6464
  eval_destroy(fx);
6465
  eval_destroy(fy);
6466
  return double_xy2js_array(xydata,i,find_number_of_digits(precision));
15111 schaersvoo 6467
}
7614 schaersvoo 6468
 
15111 schaersvoo 6469
char *double_xy2js_array(double xy[],int len,int decimals){
6470
 /*
6471
    1,2,3,4,5,6,7,8 --> [1,3,5,7],[2,4,6,8]
6472
    int xy[] is already checked for errors or overflow in "get_real()"
6473
    just to be sure we double check the size of "temp"
7614 schaersvoo 6474
*/
18562 bpr 6475
  char temp[2*MAX_BUFFER], *string;
6476
  char *tmp = my_newmem(16);/* <= 9999999999999999  */
6477
  memset(temp,'\0',2*MAX_BUFFER);/* clear memory */
6478
  int i;int space_left;
6479
  temp[0] = '[';/* start js-array */
18663 bpr 6480
  for(i = 0; i < len; i = i + 2){ /*  x_points[] */
18562 bpr 6481
    if(i == len - 2){sprintf(tmp, "%.*f",decimals, xy[i]);}
6482
    else {sprintf(tmp, "%.*f,",decimals,xy[i]);}
6483
    space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
6484
    if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}
6485
    else{
6486
      canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce your image size or plotsteps ");}
15111 schaersvoo 6487
    }
6488
    strncat(temp,"],[",4); /* close js x_values array and start new */
6489
    for(i = 1; i < len;i = i + 2){ /* y_points */
18557 bpr 6490
      if(i == len - 1){ sprintf(tmp, "%.*f",decimals,xy[i]);}else{sprintf(tmp, "%.*f,",decimals,xy[i]);}
6491
      space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
6492
      if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce your image size or plotsteps");}
15111 schaersvoo 6493
    }
6494
    strncat(temp,"]",2);
6495
    string=(char *)my_newmem(sizeof(temp));
6496
    snprintf(string,sizeof(temp),"%s",temp);
6497
    return string;
6498
}
7614 schaersvoo 6499
 
15111 schaersvoo 6500
char *list2js_array(char *list, char *s){/* abc:defg:hjiuy:qwer --> ["abc","defg","hjiuy","qwer"] */
6501
#define MAX_ARG 128
18562 bpr 6502
  if( strlen(list)> MAX_ARG - 1){canvas_error("argument is too large (&gt; 128)");}
6503
  char tmp[MAX_ARG];
6504
  size_t p = 0;
6505
  tmp[0] = '[';
6506
  tmp[1] = '\"';
6507
  size_t t = 2;
6508
  while(list[p] != '\0'){
6509
    if( list[p] == s[0] ){
6510
      tmp[t++]='\"';tmp[t++]=',';tmp[t++]='\"';
6511
    }
6512
    else
6513
    {
6514
      tmp[t++] = list[p];
6515
    }
6516
    p++;
15111 schaersvoo 6517
  }
18562 bpr 6518
  tmp[t++]='\"';tmp[t++]=']';tmp[t++]= '\0';
6519
  char *js_array = (char *)my_newmem(sizeof(tmp));
6520
  snprintf(js_array,sizeof(tmp),"%s",tmp);
6521
  return js_array;
15111 schaersvoo 6522
}
7963 schaersvoo 6523
 
15111 schaersvoo 6524
char *xy2js_array(int xy[],int len){
6525
 /*
6526
    1,2,3,4,5,6,7,8 --> [1,3,5,7],[2,4,6,8]
6527
    int xy[] is already checked for errors or overflow in "get_real()"
6528
    just to be sure we double check the size of "temp"
7614 schaersvoo 6529
*/
18562 bpr 6530
  char temp[MAX_BUFFER], *string;
6531
  char *tmp = my_newmem(16);/* <= 9999999999999999  */
6532
  memset(temp,'\0',MAX_BUFFER);/* clear memory */
6533
  int i;int space_left;
6534
  temp[0] = '[';/* start js-array */
6535
  for(i = 0; i < len;i = i + 2){ /*  x_points[] */
6536
    if(i == len - 2){sprintf(tmp, "%d", xy[i]);}else{sprintf(tmp, "%d,", xy[i]);}
6537
    space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
6538
    if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}
6539
    else {
6540
    canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce image size or plotsteps ");}
6541
  }
6542
  strncat(temp,"],[",4); /* close js x_values array and start new */
6543
  for(i = 1; i < len;i = i + 2){ /* y_points */
6544
    if(i == len - 1){ sprintf(tmp, "%d", xy[i]);}else{sprintf(tmp, "%d,", xy[i]);}
6545
    space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
6546
    if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}
6547
    else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data\nreduce image size or plotsteps \n");}
6548
  }
6549
  strncat(temp,"]",2);
6550
  string=(char *)my_newmem(sizeof(temp));
6551
  snprintf(string,sizeof(temp),"%s",temp);
6552
  return string;
7614 schaersvoo 6553
}
6554
 
15111 schaersvoo 6555
char *data2js_array(int data[],int len){
6556
 /*
6557
    1,2,3,4,5,6,7,8 --> [1,2,3,4,5,6,7,8]
6558
    int data[] is already checked for errors or overflow in "get_real()"
6559
    just to be sure we double check the size of "temp"
7614 schaersvoo 6560
*/
18562 bpr 6561
  char temp[MAX_BUFFER], *string;
6562
  char *tmp = my_newmem(16);/* <= 9999999999999999  */
6563
  memset(temp,'\0',MAX_BUFFER);/* clear memory */
6564
  int i;int space_left;
6565
  temp[0] = '[';/* start js-array */
6566
  for(i = 0; i < len; i++){
6567
    if(i == len - 1){sprintf(tmp, "%d", data[i]);}else{sprintf(tmp, "%d,", data[i]);}
6568
    space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
6569
    if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}
6570
    else{
6571
    canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce image size or plotsteps ");
15111 schaersvoo 6572
    }
18562 bpr 6573
  }
6574
  strncat(temp,"]",2);
6575
  string=(char *)my_newmem(sizeof(temp));
6576
  snprintf(string,sizeof(temp),"%s",temp);
6577
  return string;
15111 schaersvoo 6578
}
7614 schaersvoo 6579
 
15111 schaersvoo 6580
char *doubledata2js_array(double data[],int len, int decimals){
6581
 /*
15116 bpr 6582
    1.4355,2.345353,3.3455 --> [1.44,2.35,3.35]
15111 schaersvoo 6583
    double data[] is already checked for errors or overflow in "get_real()"
6584
    just to be sure we double check the size of "temp"
8448 schaersvoo 6585
*/
18562 bpr 6586
  char temp[MAX_BUFFER], *string;
6587
  char *tmp = my_newmem(16);/* <= 9999999999999999  */
6588
  memset(temp,'\0',MAX_BUFFER);/* clear memory */
6589
  int i;int space_left;
6590
  temp[0] = '[';/* start js-array */
6591
  for(i = 0; i < len; i++){
6592
    if(i == len - 1){sprintf(tmp, "%.*f",decimals,data[i]);}
6593
    else{sprintf(tmp, "%.*f,",decimals,data[i]);}
6594
    space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
6595
    if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}
6596
    else{
6597
      canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce image size or plotsteps ");}
6598
  }
6599
  strncat(temp,"]",2);
6600
  string=(char *)my_newmem(sizeof(temp));
6601
  snprintf(string,sizeof(temp),"%s",temp);
6602
  return string;
15111 schaersvoo 6603
}
13829 bpr 6604
 
15111 schaersvoo 6605
void *my_newmem(size_t size){
18562 bpr 6606
  void  *p;
6607
  if((p = malloc(size +1)) == NULL){canvas_error("canvasdraw: ran out of memory\n");}
6608
  return p;
15111 schaersvoo 6609
}
8224 bpr 6610
 
15111 schaersvoo 6611
int find_number_of_digits(int i){
18562 bpr 6612
  if(i < 0 ){ i = -1*i;}
6613
  int digits = 0;
6614
  while ( i > 0){
6615
    digits++;
6616
    i = i/10;
6617
  }
6618
  return digits;
15111 schaersvoo 6619
}
7645 schaersvoo 6620
 
16828 schaersvoo 6621
int count_substring(char* string, char* substring) {
18164 schaersvoo 6622
  int i, j, l1, l2;
16828 schaersvoo 6623
  int count = 0;
6624
  l1 = strlen(string);
6625
  l2 = strlen(substring);
6626
  for(i = 0; i < l1 - l2 + 1; i++) {
6627
    if(strstr(string + i, substring) == string + i) {
6628
      count++;
6629
      i = i + l2 -1;
6630
    }
6631
  }
6632
  return count;
6633
}
11830 schaersvoo 6634
 
7614 schaersvoo 6635
void check_string_length(int L){
18555 bpr 6636
  if( L > MAX_BUFFER-1){
6637
    canvas_error("problem with your arguments to command...");
6638
  }
6639
  return;
7614 schaersvoo 6640
}
18555 bpr 6641
/* useful in hyp commands: determine if the hypsegment is an arc or a line */
18615 bpr 6642
/* give a point on the arc */
18555 bpr 6643
int hypgeodaux(double *q, double* ress, int full){
6644
  double alpha,beta,gamma,r,cx,cy,a1,a2,a3,tmp,
6645
    nx = -q[0]*q[2]*q[2]+(q[0]*q[0]+q[1]*q[1]+1)*q[2]-q[0]*q[3]*q[3]-q[0],
6646
    ny = -q[1]*q[2]*q[2]-q[1]*q[3]*q[3]+(q[0]*q[0]+q[1]*q[1]+1)*q[3]-q[1],
6647
    dy = -2*q[1]*q[2]+2*q[0]*q[3];
6648
  if (dy*dy*1e4 <= nx*nx+ny*ny){
6649
    if(full){
6650
      if (q[1]*q[1]+q[0]*q[0] > q[2]*q[2]+q[3]*q[3])
6651
        gamma = atan2(q[1],q[0]);
6652
      else
6653
        gamma = atan2(q[3],q[2]);
6654
      ress[0]=cos(gamma); ress[1]=sin(gamma); ress[2]=-cos(gamma); ress[3]=-sin(gamma);
6655
    }
6656
    else
6657
      {int i;for(i=0;i<4;++i) ress[i]=q[i];}
18615 bpr 6658
    ress[6]=(q[0]+q[2])/2;
6659
    ress[7]=(q[1]+q[3])/2;
18555 bpr 6660
    return 0;}
6661
  cx = ny/dy; cy=-nx/dy;
6662
  r = sqrt(cx*cx+cy*cy-1);
6663
  if(full)
6664
    {alpha=atan(1/r); beta = atan2(cy,cx);a1=M_PI+beta-alpha;a2=M_PI+beta+alpha;}
6665
  else
6666
    {a1 = atan2(q[1]-cy, q[0]-cx);a2 = atan2(q[3]-cy, q[2]-cx);}
6667
  if (fabs(a2-a1)>M_PI){if(a1<a2) a1+=2*M_PI; else a2+=2*M_PI;};
6668
  a3 = (a1+a2)/2;
6669
  if(a1>a2) {tmp=a1; a1=a2; a2=tmp;}
6670
  ress[0]=cx;
6671
  ress[1]=cy;
6672
  ress[2]=2*r;
6673
  ress[3]=2*r;
6674
  ress[4]=360+180/M_PI*a1;
6675
  ress[5]=360+180/M_PI*a2;
6676
  ress[6]=cx+r*cos(a3);
6677
  ress[7]=cy+r*sin(a3);
6678
  return 1;
6679
}
7614 schaersvoo 6680
 
6681
int get_token(FILE *infile){
18589 bpr 6682
  int left,milieu,delta,right,c,i=0;
18562 bpr 6683
  char temp[MAX_INT], *input_type;
18589 bpr 6684
  enum{rien,usefilled,usedashed};
6685
  static struct commande {char *nom; int res; int special;} table[]=
6686
  {
6687
{"#",COMMENT,0},
6688
{"affine",AFFINE,0},
6689
{"allowdups",ALLOW_DUPLICATES,0},
6690
{"angle",ANGLE,0},
6691
{"animate",ANIMATE,0},
6692
{"arc",ARC,0},
6693
{"arcarrow",ARCARROW,0},
6694
{"arrow",ARROW,0},
6695
{"arrow2",ARROW2,0},
6696
{"arrowarc",ARCARROW,0},
6697
{"arrowhead",ARROWHEAD,0},
6698
{"arrows",ARROWS,0},
6699
{"arrows2",ARROWS2,0},
6700
{"audio",AUDIO,0},
6701
{"audioobject",AUDIOOBJECT,0},
6702
{"axis",AXIS,0},
6703
{"axisnumbering",AXIS_NUMBERING,0},
6704
{"axisnumbers",AXIS_NUMBERING,0},
6705
{"backgroundimage",BGIMAGE,0},
6706
{"barchart",BARCHART,0},
6707
{"bezier",BEZIER,0},
6708
{"bgcolor",BGCOLOR,0},
6709
{"bgimage",BGIMAGE,0},
6710
{"blink",BLINK,0},
6711
{"boxplot",BOXPLOT,0},
6712
{"boxplotdata",BOXPLOTDATA,0},
6713
{"brokenline",POLYLINE,0},
6714
{"canvastype",CANVASTYPE,0},
6715
{"centered",CENTERED,0},
6716
{"centerstring",CENTERSTRING,0},
6717
{"chemtex",CHEMTEX,0},
6718
{"circle",CIRCLE,0},
6719
{"circles",CIRCLES,0},
6720
{"clearbutton",CLEARBUTTON,0},
6721
{"clicktile",CLICKTILE,0},
6722
{"clicktile_colors",CLICKTILE_COLORS,0},
6723
{"clock",CLOCK,0},
6724
{"colorpalette",COLORPALETTE,0},
6725
{"colors",MULTISTROKECOLORS,0},
6726
{"copy",COPY,0},
6727
{"copyresized",COPYRESIZED,0},
6728
{"crosshair",CROSSHAIR,0},
6729
{"crosshairs",CROSSHAIRS,0},
6730
{"crosshairsize",CROSSHAIRSIZE,0},
6731
{"css",CSS,0},
6732
{"cursor",CURSOR,0},
6733
{"curve",CURVE,0},
6734
{"curvedarrow",CURVEDARROW,0},
6735
{"curvedarrow2",CURVEDARROW2,0},
6736
{"curvedarrows",CURVEDARROWS,0},
6737
{"curvedarrows2",CURVEDARROWS2,0},
6738
{"darrow",ARROW,usedashed},
6739
{"darrow2",ARROW2,usedashed},
6740
{"dashed",DASHED,0},
6741
{"dashtype",DASHTYPE,0},
6742
{"dcurve",CURVE,usedashed},
6743
{"delete",CLEARBUTTON,0},
6744
{"demiline",HALFLINE,0},
6745
{"demilines",HALFLINES,0},
6746
{"dhline",HLINE,usedashed},
6747
{"diafill",DIAMONDFILL,0},
6748
{"diamondfill",DIAMONDFILL,0},
6749
{"disk",CIRCLE,usefilled},
6750
{"disks",CIRCLES,usefilled},
6751
{"display",MOUSE_DISPLAY,0},
6752
{"dline",LINE,usedashed},
6753
{"dotfill",DOTFILL,0},
6754
{"dplot",CURVE,usedashed},
6755
{"dpolyline",POLYLINE,usedashed},
6756
{"drag",DRAG,0},
6757
{"dsegment",SEGMENT,usedashed},
6758
{"dsegments",SEGMENTS,usedashed},
6759
{"duplicates",ALLOW_DUPLICATES,0},
6760
{"dvline",VLINE,usedashed},
6761
{"ellipse",ELLIPSE,0},
6762
{"ellipses",ELLIPSES,0},
6763
{"end",END,0},
6764
{"erase",CLEARBUTTON,0},
6765
{"farc",ARC,usefilled},
6766
{"fcircle",CIRCLE,usefilled},
6767
{"fcircles",CIRCLES,usefilled},
6768
{"fellipse",ELLIPSE,usefilled},
6769
{"fhypcircles",HYPCIRCLES,usefilled},
18615 bpr 6770
{"fhyppolygon",HYPPOLY,usefilled},
18589 bpr 6771
{"fill",FLOODFILL,0},
6772
{"fillall",FILLALL,0},
6773
{"fillcolor",FILLCOLOR,0},
6774
{"fillcolors",MULTIFILLCOLORS,0},
6775
{"filled",FILLED,0},
6776
{"filledarc",ARC,usefilled},
6777
{"filledpoly",POLY,usefilled},
6778
{"filledpolygon",POLY,usefilled},
18608 bpr 6779
{"fillopacity",FILLOPACITY,0},
18589 bpr 6780
{"fillpattern",FILLPATTERN,0},
6781
{"filltoborder",FILLTOBORDER,0},
6782
{"floodfill",FLOODFILL,0},
6783
{"fontcolor",FONTCOLOR,0},
6784
{"fontfamily",FONTFAMILY,0},
6785
{"fontsize",FONTSIZE,0},
6786
{"fpoly",POLY,usefilled},
6787
{"fpolygon",POLY,usefilled},
6788
{"frect",RECT,usefilled},
6789
{"frectangle",RECT,usefilled},
6790
{"frects",RECTS,usefilled},
6791
{"froundrect",ROUNDRECT,usefilled},
6792
{"froundrects",ROUNDRECTS,usefilled},
6793
{"fsquare",SQUARE,usefilled},
6794
{"fsquares",RECTS,usefilled},
6795
{"ftriangle",TRIANGLE,usefilled},
6796
{"ftriangles",TRIANGLES,usefilled},
6797
{"functionlabel",FUNCTION_LABEL,0},
6798
{"functionlabels",FUNCTION_LABEL,0},
6799
{"grid",GRID,0},
6800
{"gridfill",GRIDFILL,0},
6801
{"group",GROUP,0},
6802
{"halfline",HALFLINE,0},
6803
{"halflines",HALFLINES,0},
6804
{"hatchfill",HATCHFILL,0},
6805
{"highlight",STYLE,0},
6806
{"hline",HLINE,0},
6807
{"hlines",HLINES,0},
6808
{"horizontalline",HLINE,0},
6809
{"horizontallines",HLINES,0},
6810
{"html",HTML,0},
6811
{"http",HTTP,0},
6812
{"hypcircles",HYPCIRCLES,0},
6813
{"hyplines",HYPLINES,0},
6814
{"hyppolygon",HYPPOLY,0},
6815
{"hyprays",HYPRAYS,0},
6816
{"hypsegments",HYPSEGMENTS,0},
6817
{"imagefill",IMAGEFILL,0},
6818
{"imagepalette",IMAGEPALETTE,0},
6819
{"input",INPUT,0},
6820
{"intooltip",INTOOLTIP,0},
6821
{"jscurve",JSCURVE,0},
6822
{"jsmath",JSMATH,0},
6823
{"jsplot",JSCURVE,0},
6824
{"katex",LATEX,0},
6825
{"kill",KILL,0},
6826
{"killaffine",KILLAFFINE,0},
6827
{"killgroup",KILLSLIDER,0},
6828
{"killinear",KILLLINEAR,0},
6829
{"killlinear",KILLLINEAR,0},
6830
{"killreset",NORESET,0},
6831
{"killrotate",KILLROTATE,0},
6832
{"killslider",KILLSLIDER,0},
6833
{"killtranslate",KILLTRANSLATION,0},
6834
{"killtranslation",KILLTRANSLATION,0},
6835
{"latex",LATEX,0},
6836
{"lattice",LATTICE,0},
6837
{"legend",LEGEND,0},
6838
{"legendcolors",LEGENDCOLORS,0},
6839
{"levelcurve",LEVELCURVE,0},
18669 bpr 6840
{"levelstep",LEVELSTEP,0},
18589 bpr 6841
{"line",LINE,0},
6842
{"linear",LINEAR,0},
6843
{"linegraph",LINEGRAPH,0},
6844
{"lines",LINES,0},
6845
{"linewidth",LINEWIDTH,0},
6846
{"linewidths",MULTILINEWIDTH,0},
6847
{"math",LATEX,0},
6848
{"mathml",MATHML,0},
6849
{"mouse",MOUSE,0},
6850
{"mousedegree",MOUSE_DEGREE,0},
6851
{"mouseprecision",MOUSE_PRECISION,0},
6852
{"mousex",MOUSEX,0},
6853
{"mousey",MOUSEY,0},
6854
{"multicolors",MULTISTROKECOLORS,0},
6855
{"multidash",MULTIDASH,0},
6856
{"multidraw",MULTIDRAW,0},
6857
{"multifill",MULTIFILL,0},
6858
{"multifillcolors",MULTIFILLCOLORS,0},
6859
{"multifillopacity",MULTIFILLOPACITY,0},
6860
{"multiinput",MULTIUSERINPUT,0},
6861
{"multilabel",MULTILABEL,0},
6862
{"multilinewidth",MULTILINEWIDTH,0},
6863
{"multisnap",MULTISNAPTOGRID,0},
6864
{"multisnaptogrid",MULTISNAPTOGRID,0},
6865
{"multistrokecolors",MULTISTROKECOLORS,0},
6866
{"multistrokeopacity",MULTISTROKEOPACITY,0},
6867
{"multiuserinput",MULTIUSERINPUT,0},
6868
{"newrange",NEWRANGE,0},
6869
{"noreset",NORESET,0},
6870
{"nostatus",STATUS,0},
6871
{"noxaxis",NOXAXIS,0},
6872
{"noyaxis",NOYAXIS,0},
6873
{"numberline",NUMBERLINE,0},
6874
{"obabel",OBABEL,0},
6875
{"onclick",ONCLICK,0},
6876
{"opacity",OPACITY,0},
6877
{"parallel",PARALLEL,0},
6878
{"path",POLYLINE,0},
6879
{"patternfill",PATTERNFILL,0},
6880
{"piechart",PIECHART,0},
6881
{"pixels",PIXELS,0},
6882
{"pixelsize",PIXELSIZE,0},
6883
{"plot",CURVE,0},
6884
{"plotstep",PLOTSTEPS,0},
6885
{"plotsteps",PLOTSTEPS,0},
6886
{"point",POINT,0},
6887
{"pointer",CURSOR,0},
6888
{"points",POINTS,0},
6889
{"poly",POLY,0},
6890
{"polygon",POLY,0},
6891
{"polyline",POLYLINE,0},
6892
{"popup",POPUP,0},
6893
{"precision",MOUSE_PRECISION,0},
6894
{"protractor",PROTRACTOR,0},
6895
{"range",RANGE,0},
6896
{"ranget",TRANGE,0},
6897
{"rangex",XRANGE,0},
6898
{"rangey",YRANGE,0},
6899
{"rays",RAYS,0},
6900
{"rect",RECT,0},
6901
{"rectangle",RECT,0},
6902
{"rects",RECTS,0},
6903
{"replyformat",REPLYFORMAT,0},
6904
{"reset",RESET,0},
6905
{"resetoffset",RESETOFFSET,0},
6906
{"rotate",ROTATE,0},
6907
{"rotationcenter",ROTATION_CENTER,0},
6908
{"roundrect",ROUNDRECT,0},
6909
{"roundrectangle",ROUNDRECT,0},
6910
{"roundrects",ROUNDRECTS,0},
6911
{"ruler",RULER,0},
6912
{"seg",SEGMENT,0},
6913
{"segment",SEGMENT,0},
6914
{"segments",SEGMENTS,0},
6915
{"segs",SEGMENTS,0},
6916
{"setlimits",SETLIMITS,0},
6917
{"setpixel",SETPIXEL,0},
6918
{"settile",FILLPATTERN,0},
6919
{"sgraph",SGRAPH,0},
6920
{"size",SIZE,0},
6921
{"slider",SLIDER,0},
6922
{"snaptofun",SNAPTOFUNCTION,0},
6923
{"snaptofunction",SNAPTOFUNCTION,0},
6924
{"snaptogrid",SNAPTOGRID,0},
6925
{"snaptopoints",SNAPTOPOINTS,0},
6926
{"square",SQUARE,0},
6927
{"status",STATUS,0},
6928
{"string",STRING,0},
6929
{"stringup",STRINGUP,0},
6930
{"strokecolor",STROKECOLOR,0},
6931
{"strokecolors",MULTISTROKECOLORS,0},
18608 bpr 6932
{"strokeopacity",STROKEOPACITY,0},
18589 bpr 6933
{"style",STYLE,0},
6934
{"text",FLY_TEXT,0},
6935
{"textarea",TEXTAREA,0},
6936
{"textfill",TEXTFILL,0},
6937
{"textup",FLY_TEXTUP,0},
6938
{"title",CENTERSTRING,0},
6939
{"trace_jscurve",TRACE_JSCURVE,0},
6940
{"trange",TRANGE,0},
6941
{"translate",TRANSLATION,0},
6942
{"translation",TRANSLATION,0},
6943
{"transparent",OPACITY,0},
6944
{"triangle",TRIANGLE,0},
6945
{"triangles",TRIANGLES,0},
6946
{"tsteps",PLOTSTEPS,0},
6947
{"userboxplot",USERBOXPLOT,0},
6948
{"userboxplotdata",USERBOXPLOT,0},
6949
{"userdraw",USERDRAW,0},
6950
{"userinput",USERINPUT,0},
6951
{"userinput_function",USERINPUT_FUNCTION,0},
6952
{"userinput_xy",USERINPUT_XY,0},
6953
{"vector",ARROW,0},
6954
{"vectors",ARROWS,0},
6955
{"verticalline",VLINE,0},
6956
{"verticallines",VLINES,0},
6957
{"video",VIDEO,0},
6958
{"vline",VLINE,0},
6959
{"vlines",VLINES,0},
6960
{"xaxis",X_AXIS_STRINGS,0},
6961
{"xaxistext",X_AXIS_STRINGS,0},
6962
{"xaxistextup",X_AXIS_STRINGS_UP,0},
6963
{"xaxisup",X_AXIS_STRINGS_UP,0},
6964
{"xerrorbars",XERRORBARS,0},
6965
{"xlabel",XLABEL,0},
6966
{"xlogbase",XLOGBASE,0},
6967
{"xlogscale",XLOGSCALE,0},
6968
{"xoffset",XOFFSET,0},
6969
{"xrange",XRANGE,0},
6970
{"xsnaptogrid",XSNAPTOGRID,0},
6971
{"xunit",XUNIT,0},
6972
{"xylogscale",XYLOGSCALE,0},
6973
{"xyoffset",XYOFFSET,0},
6974
{"yaxis",Y_AXIS_STRINGS,0},
6975
{"yaxistext",Y_AXIS_STRINGS,0},
6976
{"yerrorbars",YERRORBARS,0},
6977
{"ylabel",YLABEL,0},
6978
{"ylogbase",YLOGBASE,0},
6979
{"ylogscale",YLOGSCALE,0},
6980
{"yoffset",YOFFSET,0},
6981
{"yrange",YRANGE,0},
6982
{"ysnaptogrid",YSNAPTOGRID,0},
6983
{"yunit",YUNIT,0},
6984
{"zoom",ZOOM,0}
6985
  };
7614 schaersvoo 6986
 
18552 bpr 6987
  while(((c = getc(infile)) != EOF)&&(c!='\n')&&(c!=',')&&(c!='=')&&(c!='\r')&&(c!='\t')){
6988
   if( i == 0 && (c == ' ') ){ continue; /* white spaces or tabs allowed before first command identifier */
6989
   }else{
6990
    if( c == ' ' ){
6991
      break;
6992
    }else{
6993
     temp[i] = c;
6994
     if(i > MAX_INT - 2){canvas_error("command string too long !");}
6995
     i++;
6996
    }
6997
   }
6998
   if(temp[0] == '#'){ break; }
6999
  }
7000
  if (c == '\n' || c == '\r' || c == '\t' ){  line_number++; }
7001
  if (c == EOF) {finished=1;return 0;}
7614 schaersvoo 7002
 
18552 bpr 7003
  temp[i]='\0';
7004
  if(strstr(temp,"dash") !=0 && strlen(temp) > 4 && strstr(temp,"dashtype") == 0 ){
7005
  /* 4/2024 adapt to Flydraw's dashing syntax for all objects with prefix "dash" */
7006
      use_dashed = TRUE;int idx=0;int p;
7007
      for( p = 4; p < strlen(temp); p++){temp[idx] = temp[p];idx++;}
7008
      input_type = (char*)my_newmem(idx); snprintf(input_type,idx+1,"%s",temp);
7009
  }else{
7010
      input_type=(char*)my_newmem(strlen(temp));
7011
      snprintf(input_type,sizeof(temp),"%s",temp);
7012
  }
18572 bpr 7013
/*  fprintf(stdout,"input_type = %s no_reset = %d <br>",input_type,no_reset);*/
18589 bpr 7014
 
7015
  left=0; right=sizeof(table)/sizeof(struct commande);
7016
  while (left<right){
7017
    milieu = (left+right)/2;
7018
    delta = strcmp(input_type, table[milieu].nom);
7019
    if (delta == 0){
18663 bpr 7020
       free(input_type);
7021
       if (table[milieu].special==usefilled) use_filled=TRUE;
7022
       if (table[milieu].special==usedashed) use_dashed=TRUE;
7023
       return table[milieu].res;
7024
    }
18589 bpr 7025
    if (delta<0) right=milieu; else left=milieu+1;
18552 bpr 7026
  }
7027
  free(input_type);
18562 bpr 7028
  ungetc(c,infile);
7029
  return 0;
7614 schaersvoo 7030
}