Page 1 of 1

Drawing HTA "canvas" graphics in Batch files

Posted: 08 Aug 2015 22:52
by Aacini
This topic is a continuation of Using "HTA input forms" in Batch files; you should read it before continue with this one.

In the same way than a HTA window can be used to get input into a Batch file, a HTA window may be used to show the output produced from a Batch file. "Canvas" is a new tag released in HTML5 that allows to show graphics in a web page; it is designed to show graphics created in a dynamic way via JavaScript code. A simple example show how easy is to output graphics from a Batch file using HTA's canvas tag:

Code: Select all

<!-- :: Batch section

@echo off
mshta.exe "%~F0"
goto :EOF

-->

<meta http-equiv='x-ua-compatible' content='ie=edge'/>
<!-- http://yousfi.over-blog.com/2015/06/html5-canvas-on-hta-support.html -->

<HTML>

<HEAD>
<HTA:APPLICATION >
<TITLE>HTA Canvas</TITLE>
</HEAD>

<BODY>

<canvas id="myCanvas" width="290" height="200" style="border:1px solid #000000;">
   Your browser does not support the HTML5 canvas element.
</canvas>

<SCRIPT language="JavaScript">

var canvas = document.getElementById("myCanvas"),
    ctx = canvas.getContext("2d");

window.resizeTo(canvas.width+34,canvas.height+62);

// Line example
ctx.moveTo(0,0);
ctx.lineTo(200,100);
ctx.stroke();

// Circle example
ctx.beginPath();
ctx.arc(95,50,40,0,2*Math.PI);
ctx.stroke();

// Blue rectangle
ctx.beginPath();
ctx.lineWidth="10";
ctx.strokeStyle="blue";
ctx.rect(50,50,150,80);
ctx.stroke();

</SCRIPT>

</BODY>
</HTML>
The next example is a large program written as a proof of concept. It is a Batch-JScript-HTA "chimera" (tri-hybrid) script that draw the Mandelbrot Set fractal graphic. The Batch code execute the JScript section that calculate the colors of all points in the graphic and store them in a file. When this part ends, the Batch code execute the HTA section that read the data from the file and draw the graphic in a standard window using <canvas> tag.

Although I read the descriptions posted here about "chimera scripts", I couldn't found a method to combine both JScript and HTA code in the same Batch file, so I had to complete my own research on this point. After several tests I achieved that all parts work as expected.

Code: Select all

/*      JScript comment: start of HTA and Batch sections
<!-- :: HTA comment: start of Batch section


:: Batch section: run JScript section to generate data; run HTA section to draw graphic

@echo off

rem "Batch-JS-HTA Mandelbrot Set.bat": Mandelbrot Set fractal graphic
rem Batch-JScript-HTA chimera (tri-hybrid) version:
rem - JScript section calculate the colors of points in screen
rem - HTA section show the graphic using HTML5 canvas tag
rem Antonio Perez Ayala, Aug/08/2015

setlocal

cls
echo/
echo/
echo Mandelbrot Set fractal graphic
echo Batch-JScript-HTA chimera (tri-hybrid) version
echo/
echo/
echo Enter horizontal size of graphic window in pixels
set maxX=400
set /P "maxX=or just press Enter for default value [%maxX%]: "
set /A maxY=maxX*3/4
echo/
echo Enter maximum iteration level
set maxLevel=64
set /P "maxLevel=or just press Enter for default value [%maxLevel%]: "
echo/
echo Calculating color points...
(
   echo %maxX% %maxY%
   CScript //nologo //E:JScript "%~F0" %maxX% %maxY% %maxLevel%
) > canvas.txt
echo/
echo Drawing graphic...
mshta.exe "%~F0" < canvas.txt
del canvas.txt
goto :EOF


:: End of Batch section


End of HTA comment and start of HTA section: draw the graphic -->


<meta http-equiv='X-UA-Compatible' content='IE=edge'/>
<!-- http://yousfi.over-blog.com/2015/06/html5-canvas-on-hta-support.html -->

<HTML>

<HEAD>
<HTA:APPLICATION >
</HEAD>

<BODY>
</BODY>

<SCRIPT language="JavaScript">

var fso   = new ActiveXObject("Scripting.FileSystemObject"),
    stdin = fso.GetStandardStream(0),
    size  = stdin.ReadLine().split(" "),
    maxX  = parseInt(size[0]), maxY = parseInt(size[1]);

window.resizeTo(maxX+34,maxY+64);
document.body.innerHTML = "<TITLE>HTA Canvas drawing - Mandelbrot Set</TITLE>" +
                          "<canvas id='myCanvas' width='"+maxX+"' height='"+maxY+"' style='border:1px solid #000000;'>" +
                          "   Your browser does not support the HTML5 canvas tag"    +
                          "</canvas>";

var canvas = document.getElementById("myCanvas"),
    ctx    = canvas.getContext("2d");

while ( ! stdin.AtEndOfStream ) {
   var value = stdin.ReadLine().split(" ");
   ctx.strokeStyle = value[3];
   ctx.beginPath();
   ctx.moveTo(value[0],value[2]);
   ctx.lineTo(value[1],value[2]);
   ctx.stroke();
}

</SCRIPT>

</HTML>


<!-- End of HTA section (last HTA comment)

End of JScript comment and start of JScript section: calculate color points */


// JScript section

// Horizontal range: for 4:3 screen use range=3 (-1,2), for 16:9 screen use range=4 (-1.5,2.5)
var             yTop = 1.1250,
    xLeft = -1.0000,   xRight = 2.0000,
             yBottom = -1.1250,
    maxX  = parseInt(WScript.Arguments(0)),
    maxY  = parseInt(WScript.Arguments(1)),
    maxLevel = parseInt(WScript.Arguments(2)),
    xStep = (xRight-xLeft)/maxX,
    yStep = (yBottom-yTop)/maxY,
    yPos  = yTop-yStep,
    bandColor = new Array("#000000","#000080","#008000","#008080","#800000","#800080","#808000","#C0C0C0",
                          "#808080","#0000FF","#00FF00","#00FFFF","#FF0000",
                                    /* fuchsia band: 2 levels wide: */      "#FF00FF","#FF00FF",
                                    /* yellow band: 4 levels wide:  */                "#FFFF00","#FFFF00","#FFFF00","#FFFF00",
                                                                                                "#FFFFFF");

for ( var y = 0 ; y <= maxY ; y++ ) {
   WScript.Stderr.Write("Line "+y+"/"+maxY+"\r");
   yPos += yStep; 
   var xPos = xLeft-xStep, prevLevel = -1, prevX = 0, prevColor;
   for ( var x = 0 ; x <= maxX ; x++ ) {
      xPos += xStep;
      var xIter = xPos, yIter = yPos, level = 0;
      for ( var i = 1 ; i < maxLevel ; i++ ) {
         var xSquare = xIter*xIter, ySquare = yIter*yIter;
         if ( (xSquare+ySquare) < 4 ) {
            yIter = 2*xIter*yIter-yPos;
            xIter = xSquare-ySquare-xPos;
         } else {
            level = i;
            break;
         }
      }

      if ( level >= 19 ) level = (level>=36) ? 19 : 1;  // the band that touch the "land" (>=36) is white
                                                        // blue band inserted between (19..35) white and yellow
      var color = bandColor[level];

      if ( level != prevLevel  ||  x == maxX ) {
         if ( prevLevel != -1 ) {
            WScript.Stdout.WriteLine(prevX+" "+x+" "+y+" "+prevColor);
            prevX = x;
         }
         prevLevel = level;
         prevColor = color;
      }
   }

}


// End of JScript section and last HTA comment -->
This is an image generated by this program with horizontal size 900 and iteration level 1000:

Image

Of course, this method is less efficient than a pure HTA file that draw the same graphic (I can post it under request), but the purpose of this example is just to prove that this technique works. More advanced applications can be developed via the same method used in the input forms: a Batch subroutine that get parameters and convert they to HTML values, so Batch file users may have access to advanced HTA features with no need to know HTML details...

Antonio

PS - A subsequent application that makes good use of this same idea is Batch-BGI: A *standard* graphics library for Batch files!

Re: Drawing HTA "canvas" graphics in Batch files

Posted: 09 Aug 2015 03:09
by Meerkat
Another gem!

No more HTA "resize" flicker problem :)

Meerkat