    var sizePixels;
    var size = 8;    
    var step = 20;    
    var steps;
    var canvas;
    var context;
    var cols;
    var map;

    var offsetX = 200;
    var offsetY = 175;
    var legend;
    var blocks;
    var farby;

    function drawString(context, s, color, x, y){    	
      context.strokeStyle = color;      
      context.drawText("sans", 10, x, y+10, s);
    }

    function setColor(color, x, y, width, height) {
      if (color == 'black' || color == '#000000' || color == '#000' || color == '')
	return;
      context.fillStyle = color;      
      context.fillRect(x-1, y-1, width+2, height+2);
    }

    function writeField(fillColor) {
      context.strokeStyle = '#333';
      context.clearRect(0, 0, 1000, 1000);
      context.fillStyle   = fillColor;
      context.beginPath();
      context.moveTo(offsetX + 0.5*step*(blocks[0]), offsetY);
      context.lineTo(offsetX, offsetY + 0.866*step*(blocks[0]));      
      context.lineTo(offsetX + 0.5*step*(blocks[1]), 0.866*step*(blocks[0]) + 0.866*step*(blocks[1]) + offsetY);
      context.lineTo(offsetX + 0.5*step*(blocks[1]) + step*blocks[2],  0.866*step*(blocks[0]) + 0.866*step*(blocks[1]) + offsetY);
      context.lineTo(offsetX + 0.5*step*(blocks[1]) + step*blocks[2] + 0.5*step*(blocks[3]), offsetY + 0.866*step*(blocks[4]));
      context.lineTo(offsetX + 0.5*step*(blocks[0]) + step*blocks[5], offsetY);
      context.lineTo(offsetX + 0.5*step*(blocks[1]), offsetY);
      context.fill();
      context.closePath();
      context.beginPath();

      //blok A
      for (var i = 0; i <= blocks[0]; i++) {
	var posx = offsetX + 0.5*i*step;
	var posy = offsetY + 0.866*(blocks[0] - i)*step;
	context.moveTo(posx, posy);
	context.lineTo(posx + 500, posy + 866);
      }

      //blok B
      for (var i = 0; i <= blocks[1]; i++) {
	var posx = offsetX + 0.5*i*step;
	var posy = offsetY + 0.866*(blocks[0])*step + i*step*0.866;
	context.moveTo(posx, posy);
	context.lineTo(posx + 500, posy - 866);
      }

      //blok C
      for (var i = 1; i <= blocks[2]; i++) {
	var posx = offsetX + 0.5*(blocks[1])*step + i*step;
	var posy = offsetY + 0.866*(blocks[0])*step + 0.866*(blocks[1])*step;
	context.moveTo(posx, posy);
	context.lineTo(posx + 500, posy - 866);
      }

      //blok D
      for (var i = 0; i < blocks[3]+1; i++) {
	var posx = offsetX + 0.5*(blocks[1])*step + blocks[2]*step + 0.5*i*step;
	var posy = offsetY + 0.866*(blocks[4])*step + 0.866*(blocks[3])*step - i*0.866*step;
	context.moveTo(posx, posy);
	context.lineTo(0, posy);
      }

      //blok E
      for (var i = 0; i < blocks[4]; i++) {
	var posx = offsetX + 0.5*(blocks[0])*step + blocks[5]*step + 0.5*i*step;
	var posy = offsetY + 0.866*i*step;
	context.moveTo(posx, posy);
	context.lineTo(0, posy);
      }

      //blok F
      for (var i = 1; i <= blocks[5]; i++) {
	var posx = offsetX + 0.5*(blocks[0])*step + i*step;
	var posy = offsetY;
	context.moveTo(posx, posy);    
	context.lineTo(posx + 500, posy + 866);		
      }
            
      context.closePath();
      context.stroke();      
      writeNumbers();
    }

    function writeNumbers() {
	var textOffset = 20;
	for (var i = 0; i < blocks[0]; i++) {
	  var end = legend[0][i].length;
	  for (var j = 0; j < end; j++) {
	    drawString(context, ""+legend[0][i][j], farby[0][i][j], offsetX + blocks[0]*step*0.5 - i*step/2 - (end-j-1)*textOffset - 24, offsetY + i*step*0.866 + 4);
	  }
	}    
	for (var i = 0; i < blocks[1]; i++) {
	  var end = legend[1][i].length;
	  for (var j = 0; j < end; j++) {
	    drawString(context, ""+legend[1][i][j], farby[1][i][j], offsetX + (i+1)*step/2 - (end-j-1)*textOffset - 27, offsetY + blocks[0]*step*0.866 + (i+1)*step*0.866 - 13);
	  }
	}

	for (var i = 0; i < blocks[2]; i++) {
	  var end = legend[2][i].length
	  for (var j = 0; j < end; j++) {
	    var textOffsetX = (legend[2][i][j] < 10) ? 11 : 8;
	    drawString(context, ""+legend[2][i][j], farby[2][i][j], offsetX + 0.5*blocks[1]*step + i*step + (end-j-1)*textOffset/2 + textOffsetX, offsetY + (blocks[0] + blocks[1])*step*0.866 + (end-j-1)*textOffset*0.866 + 4);
	  }  
	}

	for (var i = 0; i < blocks[3]; i++) {
	  var end = legend[3][i].length
	  for (var j = 0; j < end; j++) {
	    var textOffsetX = (legend[3][i][j] < 10) ? 6 : 4;
	    drawString(context, ""+legend[3][i][j], farby[3][i][j], offsetX + 0.5*blocks[1]*step + blocks[2]*step + i*step*0.5 + (end-j-1)*textOffset/2 + textOffsetX, offsetY + (blocks[0]+blocks[1])*step*0.866 - i*step*0.866 + (end-j-1)*textOffset*0.866 - 4);
	  }
	}	
	
	for (var i = 0; i < blocks[4]; i++) {
	  var end = legend[4][i].length;
	  for (var j = 0; j < end; j++) {
	    var textOffsetX = (legend[4][i][j] < 10) ? 4 : 7;
	    drawString(context, ""+legend[4][i][j], farby[4][i][j], offsetX + 0.5*blocks[0]*step + blocks[5]*step + 0.5*blocks[4]*step - i*step*0.5  + (end-j-1)*textOffset/2 - textOffsetX, offsetY + 0.866*blocks[4]*step - i*step*0.866 - (end-j-1)*textOffset*0.866 - 22);
	  }
	}

	for (var i = 0; i < blocks[5]; i++) {
	  var end = legend[5][i].length
	  for (var j = 0; j < end; j++) {
	    var textOffsetX = (legend[5][i][j] < 10) ? 8 : 12;
	    drawString(context, ""+legend[5][i][j], farby[5][i][j], offsetX + 0.5*blocks[0]*step + blocks[5]*step - i*step + (end-j-1)*textOffset/2 - textOffsetX, offsetY - (end-j-1)*textOffset*0.866 - 16);
	  }
	}
    }

    function initLegend() {
	if (!legend) {
	  size = 5;
	  legend = new Array();
	  for (var i = 0; i < size*6; i++) {
	    legend[i] = new Array();
	    legend[i][0] = "1";
	    legend[i][1] = "2";
	  }
	}
    }

    function getAngle(x, y, middleX, middleY) {
	if (x-middleX == 0 && y-middleY < 0)
	  return -Math.PI/2;
	if (x-middleX == 0 && y-middleY > 0)
	  return Math.PI/2;	
	var r = Math.sqrt((x-middleX)*(x-middleX) + (y-middleY)*(y-middleY));
	return sig(y-middleY)*Math.acos((x-middleX)/r);
    }

    function sig(value) {
      return (value < 0) ? -1 : 1;
    }

    function getSize(x, y, middleX, middleY) {
      return Math.sqrt((x-middleX)*(x-middleX) + (y-middleY)*(y-middleY));
    }
    
    function mouseX(evt) {
      if (evt.pageX) return evt.pageX;
      else if (evt.clientX)
         return evt.clientX + (document.documentElement.scrollLeft ?
         document.documentElement.scrollLeft :
         document.body.scrollLeft);
      else return null;
    }
    
    function mouseY(evt) {
      if (evt.pageY) return evt.pageY;
      else if (evt.clientY)
         return evt.clientY + (document.documentElement.scrollTop ?
         document.documentElement.scrollTop :
         document.body.scrollTop);
      else return null;
    }

    function clickHandler(evt) {
	var fillColor = '#fff';
	var colorObject = document.getElementById('griddlerActualColor');
	if (colorObject && colorObject.style.backgroundColor)
	  fillColor = colorObject.style.backgroundColor;
	var offsetleft = offsettop = 0;
	var obj = canvas;
	if (obj.offsetParent) {
	  do {
	    offsetleft += obj.offsetLeft;
	    offsettop += obj.offsetTop;
	  } while (obj = obj.offsetParent);
	}
	var cursorX = mouseX(evt) - offsetleft;
	var cursorY = mouseY(evt) - offsettop;	
 	var cx = getCoordX(cursorX, cursorY);
	var cy = getCoordY(cursorX, cursorY);
	var cz = getCoordZ(cursorX, cursorY);
	if (cx == -1 || cy == -1 || cz == -1)
	  return;    	  
	if (map[cx][cy][cz] == 'gray') {
	  map[cx][cy][cz] = fillColor;	  
	  context.fillStyle   = fillColor;
    context.strokeStyle = '#333';	  
	} else {
	  map[cx][cy][cz] = 'gray';	  
	  context.fillStyle   = 'gray';
    context.strokeStyle = '#333';	  
	}
	vyplnPolicko(cx, cy, cz);
    }

    function getCoordX(x, y) {
	return getFieldCoord(y - offsetY, blocks[0] + blocks[1]);
    }

    function getCoordY(x, y) {
      var angle = getAngle(x, y, offsetX+blocks[0]*step*0.5, offsetY);
      var length = getSize(x, y, offsetX+blocks[0]*step*0.5, offsetY);
      var xLength = getColLength(angle+Math.PI/3, length);
      return getFieldCoord(xLength, blocks[4] + blocks[5]);
    }

    function getCoordZ(x, y) {
      var angle = getAngle(x, y, offsetX + blocks[0]*step*0.5 + blocks[5]*step, offsetY);      
      var length = getSize(x, y, offsetX + blocks[0]*step*0.5 + blocks[5]*step, offsetY);
      var xLength = getColLength(angle - Math.PI/3, length);
      return getFieldCoord(xLength, blocks[2] + blocks[3]);
    }

    function getFieldCoord(val, width) {
      if (val < 0)
	return -1;
      var result = Math.floor((val) / (step*0.866));
      return (result >= width) ? -1 : result;
    }    

    function getColLength(angle, length) {
 	return length*Math.sin(angle);	
    }

    /*
     * Initializes a map of the triddler which represents status of each cell.
     * 1 - the cell is filled
     * 0 - the cell is empty
     */
    function initMap() {
      map = new Array(blocks[0] + blocks[1]);
      for (var i = 0; i < blocks[0] + blocks[1]; i++) {
      	map[i] = new Array(blocks[4] + blocks[5]);
      	for (var j = 0; j < blocks[4] + blocks[5]; j++) {
      	  map[i][j] = new Array(blocks[2] + blocks[3]);
      	  for (var k = 0; k < blocks[2] + blocks[3]; k++) {
      	    map[i][j][k] = 'gray';      	    
      	  }
      	}
      }
    }

    /*
     * Initializes the triddler field.
     */
    function init(bgcolor) {      
      canvas = document.getElementById('canvas');
      if (legend)
	size = legend.length/6;
      sizePixels = step*size;      
      cols = size*2;
      steps = size;
      context = canvas.getContext('2d');
      CanvasTextFunctions.enable(context);
      context.strokeStyle = '#333';      
      initMap();
      //initLegend();
      writeField(bgcolor);      
    }

    function initForPrint(bgcolor) {      
      init(bgcolor);      
      //document.body.style += "";	// Force Opera redraw.      
    }

    function vyplnPolicko(cx, cy, cz) {
	var ry = offsetY + cx*step*0.866;
	var ind = cz - cx + cy;
	if (cx < blocks[0]) {
	  var rx = offsetX + Math.abs(cx - blocks[0])*step/2 + cy*step;
	} else {
	  var rx = offsetX + (cx - blocks[0])*step/2 + (blocks[0] + blocks[5] - cz)*step;
	  if (ind != blocks[5])
	    rx = rx - step;
	}
	if (ind == blocks[5]) {
	  context.beginPath();
	  context.moveTo(rx, ry);
	  context.lineTo(rx + step/2, ry + step*0.866);
	  context.lineTo(rx - step/2, ry + step*0.866);	  
	  context.lineTo(rx, ry);
	  context.fill();
	  context.stroke();
	  context.closePath();
	} else {
	  context.beginPath();
	  context.moveTo(rx, ry);
	  context.lineTo(rx + step, ry);
	  context.lineTo(rx + step/2, ry + step*0.866);	  
	  context.lineTo(rx, ry);
	  context.fill();
	  context.stroke();
	  context.closePath();
	}
    }

    /**
     *	Vypni sede policka bielou farbou. V podstate to sluzi na dokoncenie riesenia, ked uz sme vyriesili cely obrazok.
     */
    function vyplnPozadie(color) {      
      writeField(color);      
      for (var x = 0; x < blocks[0]+blocks[1]; x++) {
	for (var y = 0; y < blocks[4]+blocks[5]; y++) {
	  for (var z = 0; z < blocks[2]+blocks[3]; z++)
	    if (map[x][y][z] != 'gray') {
	      context.fillStyle = map[x][y][z];
	      vyplnPolicko(x, y, z);
	    }
	}
      }
    }

    function zacatZnovu() {
      initMap();
      writeField('gray');
    }

    function setSize(value) {
      size = value;
    }

    function setLegend(value) {
      legend = value;
    }

    function setOffset(valueX, valueY) {
      offsetX = valueX;
      offsetY = valueY;
    }        

    //control functions
    function setActualColor(object) {
	document.getElementById('griddlerActualColor').style.backgroundColor = object.style.backgroundColor;
    }

    function solution(id, imagewidth, imageheight) {	
	    window.open('/solutionGriddler.php?id='+id+'&type=triddler&width='+imagewidth+'&height='+imageheight, '', 'location=0,status=0,scrollbars=1,width=600,height=600');
    }

    function showHelp(category) {
	    window.open('/help/pomoc-krizovky.html#'+category, '', 'location=0,status=0,scrollbars=1,width=600,height=600');
    }

    function downloadLegend(id) {
	    location.href = '/griddlerLegend.php?type=triddler&id='+id;
    }

    function printTriddler() {
	initForPrint('white');
	window.print();	
    }