=== modified file 'src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.perf_tests.js'
--- src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.perf_tests.js	2020-11-03 19:09:39 +0000
+++ src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.perf_tests.js	2020-11-09 16:50:20 +0000
@@ -70,19 +70,34 @@
    var vertexShaderSource = 
    "attribute vec2 a_position;\n" +
    "attribute vec4 a_color;\n" +
+   "//attribute mediump float a_dist;\n" +
+   "//attribute vec2 a_endpos;\n" +
    "uniform vec2 u_resolution;\n" +
    "varying vec4 vs_out;\n" +
    "//mediump float gl_PointSize;\n" +
-   "void main() {\n" +
+   "vec4 convert(vec2 v)\n" +
+   "{\n" +
    "  // convert the rectangle from pixels to 0.0 to 1.0\n" +
-   "  vec2 zeroToOne = a_position / u_resolution;\n" +
+   "  vec2 zeroToOne = v / u_resolution;\n" +
    "  // convert from 0->1 to 0->2\n" +
    "  vec2 zeroToTwo = zeroToOne * 2.0;\n" +
    "  // convert from 0->2 to -1->+1 (clipspace)\n" +
    "  vec2 clipSpace = zeroToTwo - 1.0;\n" +
-   "  gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);\n" +
+   "  return vec4(clipSpace * vec2(1, -1), 0, 1);\n" +
+   "}\n" +
+   "\n" +
+   "void main() {\n" +
+   "  vec4 startPos = convert(a_position);\n" +
+   "//  vec4 endPos = convert(a_endpos);\n" +
+   "//  if (a_dist > 0.0) {\n" +
+   "    //gl_Position = mix(startPos, endPos, a_dist);\n" +
+   "  //  gl_Position = vec4(0);\n" +
+   "  //}\n" +
+   "  //else {\n" +
+   "    gl_Position = startPos;\n" +
+   "  //}\n" +
    "  vs_out = a_color / 255.0;\n" +
-   "//  gl_PointSize = 4.0;\n" +
+   "  gl_PointSize = 1.0;\n" +
    "}\n";
 
    var fragmentShaderSource = 
@@ -145,6 +160,8 @@
       
       me.canvasRenderer.clear();
       me.canvasRenderer.flash();
+      me.glCanvasRenderer.clear();
+      me.glCanvasRenderer.flash();
       var color = [0, 0, 0];
       me.canvasRenderer.drawRect(1, 1, me.width - 2, me.height - 2, color, false);
       me.canvasRenderer.flash();
@@ -163,11 +180,20 @@
          // Clear the canvas.
          me.gl2.clear(me.gl2.COLOR_BUFFER_BIT);
       }
+
+      if (me.glCanvasRenderer.gl)
+      {
+         me.glCanvasRenderer.gl.viewport(0, 0, me.glCanvasRenderer.gl.canvas.width, me.glCanvasRenderer.gl.canvas.height);
+         // Clear the canvas.
+         me.glCanvasRenderer.gl.clear(me.glCanvasRenderer.gl.COLOR_BUFFER_BIT);
+      }
    };
 
    function restoreLineStyle()
    {
       //restore line style
+      me.strokeStyle = 0;
+      me.glCanvasRenderer.setLineStroke(me.strokeStyle, 1);
       me.canvasRenderer.setLineStroke(me.strokeStyle, 1);
       me.strokesManager.applyStrokeToCanvas(me.ctx, me.strokeStyle, 1);
    }
@@ -196,6 +222,12 @@
       me.canvasRenderer.setLineStroke(me.strokeStyle, me.strokeWidth);
       me.strokesManager.applyStrokeToCanvas(me.ctx, me.strokeStyle, me.strokeWidth);
       
+      
+      me.glCanvasRenderer = new WebGLCanvasRenderer(me.offscreenCanvas, me.offscreenContext,
+            me.canvas, me.strokesManager, p2j.fonts, p2j.logger);
+      me.glCanvasRenderer.updateCanvasVisibility("visible");
+      me.glCanvasRenderer.resize(me.width, me.height);
+      
       clear();
       
       var gl = me.canvas0.getContext("webgl", {antialias: false});
@@ -223,7 +255,14 @@
       me.resolutionUniformLocation = resolutionUniformLocation;
       var colorAttributeLocation = gl.getAttribLocation(program, "a_color");
       me.colorAttributeLocation = colorAttributeLocation;
-
+      
+      /*
+      var endPosAttrLoc = gl.getAttribLocation(program, "a_endpos");
+      me.endPosAttrLoc = endPosAttrLoc;
+      var distAttrLoc = gl.getAttribLocation(program, "a_dist");
+      me.distAttrLoc = distAttrLoc;
+      */
+      
       // Create a buffer to put three 2d clip space points in
       var positionBuffer = gl.createBuffer();
       me.positionBuffer = positionBuffer;
@@ -278,482 +317,77 @@
       var offset = 8;        // start at the beginning of the buffer
       gl.vertexAttribPointer(
           colorAttributeLocation, size, type, normalize, stride, offset);
-
+/*
+      me.distBuf = gl.createBuffer();
+      gl.enableVertexAttribArray(me.distAttrLoc);
+      gl.bindBuffer(gl.ARRAY_BUFFER, me.distBuf);
+      var size = 1;          // 1 components per iteration
+      var type = gl.FLOAT;   // the data is 32bit floats
+      var normalize = false; // don't normalize the data
+      var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
+      var offset = 0;        // start at the beginning of the buffer
+      gl.vertexAttribPointer(
+          me.distAttrLoc, size, type, normalize, stride, offset);
+      me.endPosBuf = gl.createBuffer();
+      gl.enableVertexAttribArray(me.endPosAttrLoc);
+      gl.bindBuffer(gl.ARRAY_BUFFER, me.endPosBuf);
+      var size = 2;          // 2 components per iteration
+      var type = gl.FLOAT;   // the data is 32bit floats
+      var normalize = false; // don't normalize the data
+      var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
+      var offset = 0;        // start at the beginning of the buffer
+      gl.vertexAttribPointer(
+          me.endPosAttrLoc, size, type, normalize, stride, offset);
+*/
       // set the resolution
       gl.uniform2f(resolutionUniformLocation, gl.canvas.width, gl.canvas.height);
    }
 
-   /**
-    * Calculates the common part of the given line segment and the given clip rectangle and it saves
-    * the order from the left point to the right point.
-    * 
-    * @param    {Number} x1
-    *           X coordinate of the left vertex of the given line segment.
-    * @param    {Number} y1
-    *           Y coordinate of the left vertex of the given line segment.
-    * @param    {Number} x2
-    *           X coordinate of the right vertex of the given line segment.
-    * @param    {Number} y2
-    *           Y coordinate of the right vertex of the given line segment.
-    * @param    {Object} rect
-    *           The given clip rectangle
-    * 
-    * @return   {Array}
-    *           The common part of the given line with the clip rectangle [new_x1, new_y1, new_x2, new_y2],
-    *           these vertices have the same order from the left point to the right point, otherwise
-    *           it returns a condition that proves that there is no common part.
-    */
-   function cutTriangleLine(x1, y1, x2, y2, left, top, right, bottom)
-   {
-      //xa, ya xb, yb is normalized region covered this line segment
-      var xa;
-      var xb;
-      var incx = (x1 < x2);
-      if (incx)
-      {
-         xa = x1;
-         xb = x2;
-      }
-      else
-      {
-         xa = x2;
-         xb = x1;
-      }
-      var ya;
-      var yb;
-      var incy = (y1 < y2);
-      if (incy)
-      {
-         ya = y1;
-         yb = y2;
-      }
-      else
-      {
-         ya = y2;
-         yb = y1;
-      }
-
-      if (yb < top)
-      {
-         return incx ? [[left, top], [right,top]] : [[right, top], [left, top]];
-      }
-      
-      if (ya > bottom)
-      {
-         return incx ? [[left, bottom], [right, bottom]] : [[right, bottom], [left, bottom]];
-      }
-      
-      if (xb < left)
-      {
-         return incy ? [[left, top], [left, bottom]] : [[left, bottom], [left, top]];
-      }
-
-      if (xa > right)
-      {
-         return incy ? [[right, top], [right, bottom]] : [[right, bottom], [right, top]];
-      }
-      
-      xa = Math.max(left, xa),
-      ya = Math.max(top, ya),
-      xb = Math.min(right, xb),
-      yb = Math.min(bottom, yb)
-
-      // check that it is vertical or horizontal
-      if ((x1 == x2) || (y1 == y2))
-      {
-         if (incx || incy)
-         {
-            return [xa, ya, xb, yb];
-         }
-         else
-         {
-            return [xb, yb, xa, ya];
-         }
-      }
-      else
-      {
-         ya = (y1 * (x2 - xa) / (x2 - x1)) + (y2 * (xa - x1) / (x2 - x1));
-         yb = (y1 * (x2 - xb) / (x2 - x1)) + (y2 * (xb - x1) / (x2 - x1));
-         
-         if (yb <= top && ya <= top)
-         {
-            return incx ? [[left, top], [right,top]] : [[right, top], [left, top]];
-         }
-         
-         if (ya >= bottom && yb >= bottom)
-         {
-            return incx ? [[left, bottom], [right, bottom]] : [[right, bottom], [left, bottom]];
-         }
-         
-         if (ya >= bottom && yb <= bottom)
-         {
-            xa = (bottom*(x2-x1) + y2*x1 - y1*x2)/(y2-y1);
-            ya = bottom;
-         }
-         
-         if (ya <= bottom && yb >= bottom)
-         {
-            xb = (bottom*(x2-x1) + y2*x1 - y1*x2)/(y2-y1);
-            yb = bottom;
-         }
-         
-         if (ya >= top && yb <= top)
-         {
-            xb = (top*(x2-x1) + y2*x1 - y1*x2)/(y2-y1);
-            yb = top;
-         }
-         
-         if (ya <= top && yb >= top)
-         {
-            xa = (top*(x2-x1) + y2*x1 - y1*x2)/(y2-y1);
-            ya = top;
-         }
-
-         
-         if (incx)
-         {
-            return [xa, ya, xb, yb];
-         }
-         else
-         {
-            return [xb, yb, xa, ya];
-         }
-      }
-   }
-
-   function isInTriangle(x, y, x1, y1, x2, y2, x3, y3)
-   {
-      var d = (x1-x3)*(y2-y3) - (x2-x3)*(y1-y3);
-      
-      var d1 = (x-x3)*(y2-y3) - (x2-x3)*(y-y3);
-      
-      var d2 = (x1-x3)*(y-y3) - (x-x3)*(y1-y3);
-
-      var d3 = d - d1 - d2;
-      
-      if (d > 0)
-      {
-         return d1 >= 0 && d2 >= 0 && d3 >= 0;
-      }
-      else if (d < 0)
-      {
-         return d1 <= 0 && d2 <= 0 && d3 <= 0;
-      }
-      
-      var m = Math.min(x1, x2, x3);
-      var M = Math.max(x1, x2, x3);
-      
-      return (d1 == 0) && (d2 == 0) && (x >= m) && (x <= M); 
-   }
-   var clipRegions = [];
+   function drawPrimitivesTest()
+   {
+      clear();
+      var x1 = 100;
+      var y1 = 76;
+      var x2 = 300;
+      var y2 = 300;
+      var x3 = 400;
+      var y3 = 77;
+      var black = [0, 0, 0];
+      var t = [x1, y1, x2, y2, x3, y3];
+      append("Triangle" + JSON.stringify(t));
+      me.canvasRenderer.setColor(black);
+      me.canvasRenderer.drawLine(x1, y1, x2, y2, black);
+      me.canvasRenderer.drawLine(x3, y1-20, x3, y2+20, black);
+      me.canvasRenderer.flash();
+      me.canvasRenderer.drawLine(x2, y2, x3, y3, black);
+      me.canvasRenderer.flash();
+      me.canvasRenderer.drawLine(x3, y3, x1, y1, black);
+      me.canvasRenderer.flash();
+   }
    
-   function lastClippedRegion(flag)
-   {
-      return clipRegions;
-   }
-
-   function clipTriangles(triangles)
-   {
-      var result = [];
-      var lastClip = lastClippedRegion(true);
-      if (lastClip)
-      {
-         var clippedTriangles = [];
-         for (var k = 0; k < triangles.length; k++)
-         {
-            var triangle = triangles[k];
-            
-            var x1 = triangle[0];
-            var y1 = triangle[1];
-            var x2 = triangle[2];
-            var y2 = triangle[3];
-            var x3 = triangle[4];
-            var y3 = triangle[5];
-            
-            var c = [triangle[6], triangle[7], triangle[8], triangle[9]];
-            
-            for (var i = 0; i < lastClip.length; i++)
-            {
-               var rect = lastClip[i];
-               
-               var top    = rect.y;
-               var bottom = rect.y + Math.max(rect.height - 1, 0);
-               var left   = rect.x;
-               var right  = rect.x + Math.max(rect.width - 1, 0);
-               
-               var ab = cutTriangleLine(x1, y1, x2, y2, left, top, right, bottom);
-               var bc = cutTriangleLine(x2, y2, x3, y3, left, top, right, bottom);
-               var ac = cutTriangleLine(x1, y1, x3, y3, left, top, right, bottom);
-               
-               var vertices = [];
-               var last;
-               var first;
-               var square = [];
-               // a - > b -> c
-               if (ab.length == 4)
-               {
-                  var abx1 = ab[0];
-                  var aby1 = ab[1];
-                  var abx2 = ab[2];
-                  var aby2 = ab[3];
-                  if (abx1 != abx2 || aby1 != aby2)
-                  {
-                     first = [abx1, aby1];
-                     vertices.push(first);
-                     last = [abx2, aby2];
-                     vertices.push(last);
-                  }
-                  else
-                  {
-                     last = [abx1, aby1];
-                     first = last;
-                     vertices.push(last);
-                  }
-               }
-               else
-               {
-                  var v = ab[0];
-                  if (isInTriangle(v[0], v[1], x1, y1, x2, y2, x3, y3))
-                  {
-                     first = v;
-                     last = v;
-                     vertices.push(first);
-                  }
-                  v = ab[1];
-                  if (isInTriangle(v[0], v[1], x1, y1, x2, y2, x3, y3))
-                  {
-                     if (last)
-                     {
-                        if (last[0] != v[0] || last[1] != v[1])
-                        {
-                           last = v;
-                           vertices.push(v);
-                        }
-                     }
-                     else
-                     {
-                        first = v;
-                        last = v;
-                        vertices.push(first);
-                     }
-                  }
-               }
-               if (bc.length == 4)
-               {
-                  var bcx2 = bc[0];
-                  var bcy2 = bc[1];
-                  var bcx3 = bc[2];
-                  var bcy3 = bc[3];
-                  if (bcx2 != bcx3 || bcy2 != bcy3)
-                  {
-                     if (last)
-                     {
-                        if (last[0] != bcx2 || last[1] != bcy2)
-                        {
-                           vertices.push([bcx2, bcy2]);
-                        }
-                     }
-                     else
-                     {
-                        first = [bcx2, bcy2];
-                        vertices.push(first);
-                     }
-                     
-                     last = [bcx3, bcy3];
-                     vertices.push(last);
-                  }
-                  else
-                  {
-                     if (last)
-                     { 
-                        if (last[0] != bcx2 || last[1] != bcy2)
-                        {
-                           last = [bcx2, bcy2];
-                           vertices.push(last);
-                        }
-                     }
-                     else
-                     {
-                        first = [bcx2, bcy2];
-                        last = first;
-                        vertices.push(last);
-                     }
-                  }
-               }
-               else
-               {
-                  var v = bc[0];
-                  if (isInTriangle(v[0], v[1], x1, y1, x2, y2, x3, y3))
-                  {
-                     if (last)
-                     {
-                        var t = vertices.every(function(el) { return el[0] != v[0] || el[1] != v[1]});
-                        if (t)
-                        {
-                           last = v;
-                           vertices.push(v);
-                        }
-                     }
-                     else
-                     {
-                        first = v;
-                        last = v;
-                        vertices.push(first);
-                     }
-                  }
-                  v = bc[1];
-                  if (isInTriangle(v[0], v[1], x1, y1, x2, y2, x3, y3))
-                  {
-                     if (last)
-                     {
-                        var t = vertices.every(function(el) { return el[0] != v[0] || el[1] != v[1]});
-                        if (t)
-                        {
-                           last = v;
-                           vertices.push(v);
-                        }
-                     }
-                     else
-                     {
-                        first = v;
-                        last = v;
-                        vertices.push(first);
-                     }
-                  }
-               }
-               
-               if (ac.length == 4)
-               {
-                  var acx1 = ac[0];
-                  var acy1 = ac[1];
-                  var acx3 = ac[2];
-                  var acy3 = ac[3];
-                  if (acx1 != acx3 || acy1 != acy3)
-                  {
-                     if (last)
-                     {
-                        if (last[0] != acx3 || last[1] != acy3)
-                        {
-                           vertices.push([acx3, acy3]);
-                        }
-                     }
-                     else
-                     {
-                        first = [acx3, acy3];
-                        vertices.push(first);
-                     }
-                     
-                     if (first[0] != acx1 || first[1] != acy1)
-                     {
-                        vertices.push([acx1, acy1]);
-                     }
-                  }
-                  else
-                  {
-                     if (last)
-                     {
-                        if ((last[0] != acx3 || last[1] != acy3) && (first[0] != acx3 || first[1] != acy3))
-                        {
-                           vertices.push([acx3, acy3]);
-                        }
-                     }
-                     else
-                     {
-                        first = [acx3, acy3];
-                        last = first;
-                        vertices.push(last);
-                     }
-                  }
-               }
-               else
-               {
-                  var v = ac[1];
-                  if (isInTriangle(v[0], v[1], x1, y1, x2, y2, x3, y3))
-                  {
-                     if (last)
-                     {
-                        var t = vertices.every(function(el) { return el[0] != v[0] || el[1] != v[1]});
-                        if (t)
-                        {
-                           last = v;
-                           vertices.push(v);
-                        }
-                     }
-                     else
-                     {
-                        first = v;
-                        last = v;
-                        vertices.push(first);
-                     }
-                  }
-                  v = ac[0];
-                  if (isInTriangle(v[0], v[1], x1, y1, x2, y2, x3, y3))
-                  {
-                     var t = vertices.every(function(el) { return el[0] != v[0] || el[1] != v[1]});
-                     if (t)
-                     {
-                        vertices.push(v);
-                     }
-                  }
-
-               }
-               var v0, v1, v;
-               if (vertices.length >= 3)
-               {
-                  v0 = vertices[0];
-                  v1 = vertices[1];
-                  
-                  for (var j = 2; j < vertices.length; j++)
-                  {
-                     v = vertices[j];
-                     clippedTriangles.push(v0.concat(v1).concat(v).concat(c));
-                     v1 = v;
-                  }
-               }
-               else if (vertices.length == 2)
-               {
-                  v0 = vertices[0];
-                  v1 = vertices[1];
-                  clippedTriangles.push(v0.concat(v1).concat(v1).concat(c));
-               }
-               else if (vertices.length == 1)
-               {
-                  v0 = vertices[0];
-                  clippedTriangles.push(v0.concat(v0).concat(v0).concat(c));
-               }
-            }//end for lastClip
-         }//end for triangles
-         
-         result = clippedTriangles;
-      }
-      else
-      {
-         result = triangles;
-      }
-
-      return result;
-   };
-
    function clipTrianglesTest()
    {
       clear();
       var x1 = 100;
-      var y1 = 100;
+      var y1 = 100 + Math.floor(Math.random() * 50) * Math.sign(Math.random() - 0.5);
       var x2 = 300;
-      var y2 = 300;
+      var y2 = 300 - Math.floor(Math.random() * 100) * Math.sign(Math.random() - 0.5);
       var x3 = 400;
-      var y3 = 100;
-      clipRegions = [{x: 100, y: 100, width: 101, height: 201},
-                     {x: 280, y: 290, width: 101, height: 201},
-                     {x: 265, y: 275, width: 101, height: 1},
-                     {x: 201, y: 100, width: 101, height: 101},
-                     {x: 201, y: 210, width: 301, height: 40},
-                     {x: 350, y: 50, width: 101, height: 101},
-                     {x: 310, y: 10, width: 10, height: 150},
-                     {x: 325, y: 10, width: 1, height: 130},
-                     {x: 460, y: 100, width: 101, height: 101}];
+      var y3 = 100 - Math.floor(Math.random() * 50) * Math.sign(Math.random() - 0.5);
+      var clipRegions = [{x: 100, y: 100, width: 101, height: 201},
+                         {x: 280, y: 290, width: 101, height: 201},
+                         {x: 265, y: 275, width: 101, height: 1},
+                         {x: 201, y: 100, width: 101, height: 101},
+                         {x: 201, y: 210, width: 301, height: 40},
+                         {x: 350, y: 50, width: 101, height: 101},
+                         {x: 310, y: 10, width: 10, height: 150},
+                         {x: 325, y: 10, width: 1, height: 130},
+                         {x: 460, y: 100, width: 101, height: 101}];
+      me.glCanvasRenderer.clip(clipRegions);
       var black = [0, 0, 0];
       var yellow = [255, 255, 0];
+      var t = [x1, y1, x2, y2, x3, y3, 0, 0, 0, 1];
+      append("Split triangle" + JSON.stringify(t) + " into areas:");
       me.canvasRenderer.setColor(black);
       me.canvasRenderer.drawLine(x1, y1, x2, y2, black);
       me.canvasRenderer.drawLine(x2, y2, x3, y3, black);
@@ -768,7 +402,7 @@
          me.canvasRenderer.drawRect(rect.x, rect.y, rect.width, rect.height, red, false);
       }
       me.canvasRenderer.flash();
-      var test = clipTriangles([[x1, y1, x2, y2, x3, y3, 0, 0, 0, 1]]);
+      var test = me.glCanvasRenderer.clipTriangles([t]);
       
       me.canvasRenderer.setColor(yellow);
       for (var i = 0; i < test.length; i++)
@@ -782,7 +416,8 @@
          append(JSON.stringify(test[i]));
          console.debug(test[i]);
       }
-      
+      //clear clipping regions
+      me.glCanvasRenderer.unclip();
    }
    
    function xtogl(x, canvas)
@@ -982,9 +617,20 @@
    {
       var vertices = [
                       { x: x1, y: y1, color: c},
-                      { x: x2, y: y2, color: c}
+                      { x: x2, y: y2, color: c},
+                      { x: x2, y: y2+1, color: c},
+                      { x: x1, y: y1+1, color: c},
+                      { x: x1, y: y1, color: c},
+                      { x: x2, y: y2, color: c},
                       ];
-      var buffer = new ArrayBuffer(12 * 2);
+      
+/*      for (var i=0; i < 100; i++)
+      {
+         vertices.push({ x: x1, y: y1, color: c});
+         vertices.push({ x: x1 + 1, y: y1, color: c});
+         vertices.push({ x: x2, y: y2, color: c});
+      } */
+      var buffer = new ArrayBuffer(12 * vertices.length);
       //Fill array buffer
       var dv = new DataView(buffer);
       for (let i = 0; i < vertices.length; i++) {
@@ -994,14 +640,79 @@
          dv.setUint8(12 * i + 9, vertices[i].color[1]);
          dv.setUint8(12 * i + 10, vertices[i].color[2]);
          dv.setUint8(12 * i + 11, 255);
+         i += 1;
+         dv.setFloat32(12 * i, vertices[i].x, true);
+         dv.setFloat32(12 * i + 4, vertices[i].y, true);
+         dv.setUint8(12 * i + 8, vertices[i].color[0]);
+         dv.setUint8(12 * i + 9, vertices[i].color[1]);
+         dv.setUint8(12 * i + 10, vertices[i].color[2]);
+         dv.setUint8(12 * i + 11, 255);
+         i += 1;
+         dv.setFloat32(12 * i, vertices[i].x, true);
+         dv.setFloat32(12 * i + 4, vertices[i].y, true);
+         dv.setUint8(12 * i + 8, vertices[i].color[0]);
+         dv.setUint8(12 * i + 9, vertices[i].color[1]);
+         dv.setUint8(12 * i + 10, vertices[i].color[2]);
+         dv.setUint8(12 * i + 11, 255);
        }
+      me.gl.bindBuffer(me.gl.ARRAY_BUFFER, me.positionBuffer);
       me.gl.bufferData(me.gl.ARRAY_BUFFER, dv, me.gl.STATIC_DRAW);
+      me.gl.enableVertexAttribArray(me.positionAttributeLocation);
+
+      // Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
+      var size = 2;          // 2 components per iteration
+      var type = me.gl.FLOAT;   // the data is 32bit floats
+      var normalize = false; // don't normalize the data
+      var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
+      var offset = 0;        // start at the beginning of the buffer
+      me.gl.vertexAttribPointer(
+         me.positionAttributeLocation, size, type, normalize, stride, offset);
+      me.gl.disableVertexAttribArray(me.endPosAttrLoc);
+      me.gl.disableVertexAttribArray(me.distAttrLoc);
+     /* 
+      var endPos = [];
+      var w = Math.abs(x2 - x1);
+      var dist = []
+      for (var i=0; i < 100; i++)
+      {
+         endPos.push(x2);
+         endPos.push(y2);
+         endPos.push(x2);
+         endPos.push(y2);
+         endPos.push(x2);
+         endPos.push(y2);
+         dist.push((i + 1)/100);
+         dist.push((i + 1)/100);
+         dist.push((i + 1)/100);
+      }
+      me.gl.bindBuffer(me.gl.ARRAY_BUFFER, me.endPosBuf);
+      me.gl.bufferData(me.gl.ARRAY_BUFFER, new Float32Array(endPos), me.gl.STATIC_DRAW);
+      me.gl.enableVertexAttribArray(me.endPosAttrLoc);
+      var size = 2;          // 2 components per iteration
+      var type = me.gl.FLOAT;   // the data is 32bit floats
+      var normalize = false; // don't normalize the data
+      var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
+      var offset = 0;        // start at the beginning of the buffer
+      me.gl.vertexAttribPointer(
+         me.endPosAttrLoc, size, type, normalize, stride, offset);      // Set color.
+      
+      me.gl.enableVertexAttribArray(me.distAttrLoc);
+      me.gl.bindBuffer(me.gl.ARRAY_BUFFER, me.distBuf);
+      me.gl.bufferData(me.gl.ARRAY_BUFFER, new Float32Array(dist), me.gl.STATIC_DRAW);
+      var size = 1;          // 1 components per iteration
+      var type = me.gl.FLOAT;   // the data is 32bit floats
+      var normalize = false; // don't normalize the data
+      var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
+      var offset = 0;        // start at the beginning of the buffer
+      me.gl.vertexAttribPointer(
+          me.distAttrLoc, size, type, normalize, stride, offset);
+          */
       // Set color.
       //me.gl.uniform4f(me.colorUniformLocation, c[0] / 255.0, c[1] / 255.0 , c[2] / 255.0, 1);
       // Draw the geometry.
-      var primitiveType = me.gl.LINES;
+      var primitiveType = me.gl.TRIANGLES;
       var offset = 0;
-      var count = 2;
+      var count = vertices.length;
       me.gl.drawArrays(primitiveType, offset, count);
    }
    
@@ -1115,7 +826,14 @@
                     [0, 0, 64],
                     [0, 0, 0]];
       const t0 = performance.now();
-      gridTest(23, 17, 43, 23, colors, me.canvas0.width, me.canvas0.height, true, glDrawRect);
+      var fun = function(x, y, w, h, c, fill)
+      {
+         me.glCanvasRenderer.setColor(c);
+         me.glCanvasRenderer.drawRect(x, y, w, h, c, fill);
+         //me.glCanvasRenderer.flashGL();
+      }
+      gridTest(23, 17, 43, 23, colors, me.canvas0.width, me.canvas0.height, true, fun);
+      me.glCanvasRenderer.flashGL();
       const t1 = performance.now();
       append("WebGL Fill Test finished in", t1-t0);
    }
@@ -1165,7 +883,14 @@
                     [128, 0, 64],
                     [0, 0, 0]];
       const t0 = performance.now();
-      gridTest(11, 7, 51, 37, colors, me.canvas0.width, me.canvas0.height, false, glDrawRect);
+      var fun = function(x, y, w, h, c, fill)
+      {
+         me.glCanvasRenderer.setColor(c);
+         me.glCanvasRenderer.strokeRect(x, y, w, h, c, fill);
+         //me.glCanvasRenderer.flashGL();
+      }
+      gridTest(11, 7, 51, 37, colors, me.canvas0.width, me.canvas0.height, false, fun);
+      me.glCanvasRenderer.flashGL();
       const t1 = performance.now();
       append("WebGL Stroke Test finished in", t1-t0);
    }
@@ -1216,10 +941,12 @@
                     [0, 0, 0]];
       var fun = function(x1, y1, x2, y2, c, fill)
       {
-         glDrawLine(x1, y1, x2, y2, c);
+         me.glCanvasRenderer.strokeLineSegment(x1, y1, x2, y2, c);
+         //me.glCanvasRenderer.flashGL();
       }
       const t0 = performance.now();
       gridTest(17, 13, me.canvas0.width >> 1, me.canvas0.height >> 1, colors, me.canvas0.width, me.canvas0.height, false, fun);
+      me.glCanvasRenderer.flashGL();
       const t1 = performance.now();
       append("WebGL Lines Test finished in", t1-t0);
    }
@@ -1385,6 +1112,79 @@
       restoreLineStyle();
    }
    
+   function glDrawingJava2DTest()
+   {
+      clear();
+      
+      const t0 = performance.now();
+      me.strokesManager.applyStrokeToCanvas(me.ctx, 1, 1);//set style
+      me.canvasRenderer.setLineStroke(1, 1);
+      me.glCanvasRenderer.setLineStroke(1, 1);
+      var color = [0, 0, 0];
+      me.glCanvasRenderer.drawLine(10, 10, 790, 30, color);
+      me.glCanvasRenderer.drawRect(40, 40, 55, 30, color, false);
+      me.glCanvasRenderer.drawLine(210, 40, 210, 70, color);
+      me.glCanvasRenderer.drawLine(241, 40, 241, 70, color);
+      me.glCanvasRenderer.drawLine(250, 40, 305, 40, color);
+      me.glCanvasRenderer.drawLine(250, 70, 305, 70, color);
+      
+      me.strokesManager.applyStrokeToCanvas(me.ctx, 1, 2);
+      me.canvasRenderer.setLineStroke(1, 2);
+      me.glCanvasRenderer.setLineStroke(1, 2);
+      me.glCanvasRenderer.drawLine(10, 80, 790, 100, color);
+      me.glCanvasRenderer.drawRect(40, 110, 55, 30, color, false);
+      me.glCanvasRenderer.drawLine(210, 110, 210, 140, color);
+      me.glCanvasRenderer.drawLine(241, 110, 241, 140, color);
+      me.glCanvasRenderer.drawLine(250, 110, 305, 110, color);
+      me.glCanvasRenderer.drawLine(250, 140, 305, 140, color);
+
+      me.strokesManager.applyStrokeToCanvas(me.ctx, 1, 3);
+      me.canvasRenderer.setLineStroke(1, 3);
+      me.glCanvasRenderer.setLineStroke(1, 3);
+      me.glCanvasRenderer.drawLine(10, 150, 790, 170, color);
+      me.glCanvasRenderer.drawRect(40, 180, 55, 30, color, false);
+      me.glCanvasRenderer.drawLine(210, 180, 210, 210, color);
+      me.glCanvasRenderer.drawLine(241, 180, 241, 210, color);
+      me.glCanvasRenderer.drawLine(250, 180, 305, 180, color);
+      me.glCanvasRenderer.drawLine(250, 210, 305, 210, color);
+
+      me.strokesManager.applyStrokeToCanvas(me.ctx, 2, 1);
+      me.canvasRenderer.setLineStroke(2, 1);
+      me.glCanvasRenderer.setLineStroke(2, 1);
+      me.glCanvasRenderer.drawLine(10, 220, 790, 240, color);
+      me.glCanvasRenderer.drawRect(40, 250, 55, 30, color, false);
+      me.glCanvasRenderer.drawLine(210, 250, 210, 280, color);
+      me.glCanvasRenderer.drawLine(241, 250, 241, 280, color);
+      me.glCanvasRenderer.drawLine(250, 250, 305, 250, color);
+      me.glCanvasRenderer.drawLine(250, 280, 305, 280, color);
+
+      me.strokesManager.applyStrokeToCanvas(me.ctx, 3, 1);
+      me.canvasRenderer.setLineStroke(3, 1);
+      me.glCanvasRenderer.setLineStroke(3, 1);
+      me.glCanvasRenderer.drawLine(10, 290, 790, 310, color);
+      me.glCanvasRenderer.drawRect(40, 320, 55, 30, color, false);
+      me.glCanvasRenderer.drawLine(210, 320, 210, 350, color);
+      me.glCanvasRenderer.drawLine(241, 320, 241, 350, color);
+      me.glCanvasRenderer.drawLine(250, 320, 305, 320, color);
+      me.glCanvasRenderer.drawLine(250, 350, 305, 350, color);
+
+      me.strokesManager.applyStrokeToCanvas(me.ctx, 4, 1);
+      me.canvasRenderer.setLineStroke(4, 1);
+      me.glCanvasRenderer.setLineStroke(4, 1);
+      me.glCanvasRenderer.drawLine(10, 360, 790, 380, color);
+      me.glCanvasRenderer.drawRect(40, 390, 55, 30, color, false);
+      me.glCanvasRenderer.drawLine(210, 390, 210, 420, color);
+      me.glCanvasRenderer.drawLine(241, 390, 241, 420, color);
+      me.glCanvasRenderer.drawLine(250, 390, 305, 390, color);
+      me.glCanvasRenderer.drawLine(250, 420, 305, 420, color);
+      me.glCanvasRenderer.flashGL();
+      const t1 = performance.now();
+      append("WebGL Drawing Java 2D Test finished in", t1-t0);
+
+      //restore line style
+      restoreLineStyle();
+   }
+   
    function precisionTest()
    {
       clear();
@@ -1481,19 +1281,6 @@
             });
             
             var mainMenuBar = new MenuBar({});
-            /*
-            var pSubMenu = new DropDownMenu({});
-            pSubMenu.addChild(new MenuItem({
-                label: "Save"
-            }));
-            pSubMenu.addChild(new MenuItem({
-                label: "Save As..."
-            }));
-            mainMenuBar.addChild(new PopupMenuBarItem({
-                label: "File",
-                popup: pSubMenu
-            }));
-*/
             var testsSubMenu = new DropDownMenu({});
             testsSubMenu.addChild(new MenuItem({
                                                   label: "Fill Test",
@@ -1557,6 +1344,13 @@
                                                    }
                                                }));
             glTestsSubMenu.addChild(new MenuItem({
+                                                   label: "WebGL Java 2D Test",
+                                                   onClick: function(event)
+                                                   {
+                                                      glDrawingJava2DTest();
+                                                   }
+                                                 }));
+            glTestsSubMenu.addChild(new MenuItem({
                                        label: "Vertex Shader Test",
                                        onClick: function(event)
                                        {
@@ -1570,13 +1364,6 @@
                                                    {
                                                       glPrecisionTest();
                                                    }
-                                               }));
-            glTestsSubMenu.addChild(new MenuItem({
-                                                   label: "Java 2D Test",
-                                                   onClick: function(event)
-                                                   {
-                                                      glDrawingJava2DTest();
-                                                   }
                                                })); */
             mainMenuBar.addChild(new PopupMenuBarItem({
                                                        label: "WebGL Tests",
@@ -1604,18 +1391,15 @@
                   clipTrianglesTest();
                }
             }));
-            /*
-            pSubMenu2.addChild(new MenuItem({
-                label: "Copy",
-                iconClass: "dijitEditorIcon dijitEditorIconCopy"
-            }));
-            pSubMenu2.addChild(new MenuItem({
-                label: "Paste",
-                iconClass: "dijitEditorIcon dijitEditorIconPaste"
-            }));
-            */
+            pSubMenu2.addChild(new MenuItem({
+               label: "Draw Primitives Test",
+               onClick: function(event)
+               {
+                  drawPrimitivesTest();
+               }
+            }));
             mainMenuBar.addChild(new PopupMenuBarItem({
-                label: "Tools",
+                label: "Miscellaneous Tests",
                 popup: pSubMenu2
             }));
             mainMenuBar.placeAt(div.id);
@@ -1623,6 +1407,7 @@
             
             style = "width:800px;height:600px;position:relative";
             var canvasContainer = domConstruct.create("div", { style: style }, div);
+            me.canvasContainer = canvasContainer;
             style = "width:800px;height:600px;position:absolute;top:0px;left:0px;";
             var canvas0 = domConstruct.create("canvas", { style: style }, canvasContainer);
             style = "width:800px;height:600px;position:absolute;top:0px;left:0px;background-color:transparent;";
@@ -1630,7 +1415,7 @@
             style = "width:800px;height:600px;position:absolute;top:0px;left:0px;background-color:transparent;";
             var canvas2 = domConstruct.create("canvas", { style: style }, canvasContainer);
             
-            style = "width:800px;height:100px;position:relative;overflow-y:auto;";
+            style = "width:800px;height:auto;max-height:140px;position:relative;overflow-y:auto;";
             var textContainer = domConstruct.create("div", { style: style }, div);
             style = "width:100%;height:auto;margin: 1";
             var textElement = domConstruct.create("textarea", { style: style}, textContainer);
@@ -1661,12 +1446,19 @@
             me.canvas.height = me.height;
             me.canvas2.width  = me.width;
             me.canvas2.height = me.height;
-
-            init();
          });
    
    that.open = function ()
    {
+      if (!me.offscreenCanvas)
+      {
+         init();
+         if (me.glCanvasRenderer.webglCanvas.parentNode)
+         {
+            me.glCanvasRenderer.webglCanvas.parentNode.removeChild(me.glCanvasRenderer.webglCanvas);
+            me.canvasContainer.appendChild(me.glCanvasRenderer.webglCanvas);
+         }
+      }
       if (me.dialog)
       {
          me.dialog.show();

