//  ---------------------------------------------------------------------------
/* This notice must be untouched at all times.
 wz_jsgraphics.js    v. 3.03
 The latest version is available at
 http://www.walterzorn.com
 or http://www.devira.com
 or http://www.walterzorn.de
 
 Copyright (c) 2002-2004 Walter Zorn. All rights reserved.
 Created 3. 11. 2002 by Walter Zorn (Web: http://www.walterzorn.com )
 Last modified: 28. 1. 2008
 
 Performance optimizations for Internet Explorer
 by Thomas Frank and John Holdsworth.
 fillPolygon method implemented by Matthieu Haller.
 
 High Performance JavaScript Graphics Library.
 Provides methods
 - to draw lines, rectangles, ellipses, polygons
 with specifiable line thickness,
 - to fill rectangles, polygons, ellipses and arcs
 - to draw text.
 NOTE: Operations, functions and branching have rather been optimized
 to efficiency and speed than to shortness of source code.
 
 LICENSE: LGPL
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License (LGPL) as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA,
 or see http://www.gnu.org/copyleft/lesser.html
 */

var jg_ok, jg_ie, jg_fast, jg_dom, jg_moz;

//  ---------------------------------------------------------------------------
function _chkDHTM(x, i) {
  x = document.body || null;
  jg_ie = x && typeof x.insertAdjacentHTML != "undefined" && document.createElement;
  jg_dom = (x && !jg_ie && typeof x.appendChild != "undefined" && typeof document.createRange != "undefined" && typeof(i = document.createRange()).setStartBefore != "undefined" && typeof i.createContextualFragment != "undefined");
  jg_fast = jg_ie && document.all && !window.opera;
  jg_moz = jg_dom && typeof x.style.MozOpacity != "undefined";
  jg_ok = !! (jg_ie || jg_dom);
}

//  ---------------------------------------------------------------------------
function _pntCnvDom() {
  var x = this.wnd.document.createRange();
  x.setStartBefore(this.cnv);
  x = x.createContextualFragment(jg_fast ? this._htmRpc() : this.htm);
  if (this.cnv) this.cnv.appendChild(x);
  this.htm = "";
}

//  ---------------------------------------------------------------------------
function _pntCnvIe() {
  if (this.cnv) this.cnv.insertAdjacentHTML("BeforeEnd", jg_fast ? this._htmRpc() : this.htm);
  this.htm = "";
}

//  ---------------------------------------------------------------------------
function _pntDoc() {
  this.wnd.document.write(jg_fast ? this._htmRpc() : this.htm);
  this.htm = '';
}

//  ---------------------------------------------------------------------------
function _pntN() {;
}

//  ---------------------------------------------------------------------------
function makeDiv(x, y, w, h) {
  var node = document.createElement ('div'); 
//  node.id = "div" + (++this.iDiv);
  node = setDimension(node, x, y, w, h);
  node.style.clip = 'rect(0,' + w + 'px,' + h + 'px,0)';
  node.style.backgroundColor = this.color;
  node.style.overflow = !jg_moz ? 'hidden' : '';
//  this.position.appendChild(node);
  return node;
}

//  ---------------------------------------------------------------------------
function makeDivIe(x, y, w, h) {
  var node = document.createElement ('div'); 
//  node.style.clip = 'rect(0,' + w + 'px,' + h + 'px,0)';
  node = setDimension(node, x, y, w, h);
  node.style.backgroundColor = this.color;
  node.style.overflow = !jg_moz ? 'hidden' : '';
  return node;
}

//  ---------------------------------------------------------------------------
function setDimension(node, x, y, w, h) {
  node.style.position ='absolute';
  node.style.left   = Math.max(0, x) + 'px';
  node.style.top    = Math.max(0, y) + 'px';
  node.style.width  = Math.max(0, w) + 'px';
  node.style.height = Math.max(0, h) + 'px';
  return node;
}
//  ---------------------------------------------------------------------------
function makeDivPrt(x, y, w, h) {
  var node = document.createElement ('div');
  node.style.position = 'absolute';
  node.style.borderLeft = w + 'px solid ' + this.color;
  node.style.left = x + 'px';
  node.style.top = y + 'px';
  node.style.width = '0px';
  node.style.height = h + 'px';
  node.style.clip = 'rect(0,' + w + 'px,' + h + 'px,0)';
  node.style.backgroundColor = this.color;
  node.style.overflow = !jg_moz ? 'hidden' : '';
//  this.position.appendChild(node);
  return node;
}

var _regex = /%%([^;]+);([^;]+);([^;]+);([^;]+);([^;]+);/g;

//  ---------------------------------------------------------------------------
function _htmRpc() {
  return this.position.toString().replace(
  _regex, '<div style="overflow:hidden;position:absolute;background-color:' + '$1;left:$2;top:$3;width:$4;height:$5"></div>\n');
}

//  ---------------------------------------------------------------------------
function _htmPrtRpc() {
  return this.position.toString().replace(
  _regex, '<div style="overflow:hidden;position:absolute;background-color:' + '$1;left:$2;top:$3;width:$4;height:$5;border-left:$4px solid $1"></div>\n');
}

//  ---------------------------------------------------------------------------
function makeLine(x1, y1, x2, y2, stroke, color, opacity) {
//  alert (this.id+'.makeLine('+x1+', '+y1+', '+x2+', '+y2+')');
  var node = document.createElement ('div');
  node.setAttribute ('id',  "line" + (++this.iLine));
  if (stroke) this.setStroke(stroke);
  if (color) this.setColor(color);
//  if (opacity) this.setOpacity(opacity);
  if (x1 > x2) {
    var _x2 = x2;
    var _y2 = y2;
    x2 = x1;
    y2 = y1;
    x1 = _x2;
    y1 = _y2;
  }
  var dx = x2 - x1,
    dy = Math.abs(y2 - y1),
    x = x1,
    y = y1,
    yIncr = (y1 > y2) ? -1 : 1;

  if (dx >= dy) {
      var pr = dy << 1,
        pru = pr - (dx << 1),
        p = pr - dx,
        ox = x;
      while (dx > 0) {
          --dx;
          ++x;
          if (p > 0) {
            node.appendChild (this.makeDiv(ox, y, x - ox, 1));
            y += yIncr;
            p += pru;
            ox = x;
          }
          else p += pr;
        }
      node.appendChild (this.makeDiv(ox, y, x2 - ox + 1, 1));
    }

  else {
      var pr = dx << 1,
        pru = pr - (dy << 1),
        p = pr - dy,
        oy = y;
      if (y2 <= y1) {
          while (dy > 0) {
            --dy;
            if (p > 0) {
              node.appendChild (this.makeDiv(x++, y, 1, oy - y + 1));
              y += yIncr;
              p += pru;
              oy = y;
            }
            else {
              y += yIncr;
              p += pr;
            }
          }
          node.appendChild (this.makeDiv(x2, y2, 1, oy - y2 + 1));
        }
      else {
          while (dy > 0) {
            --dy;
            y += yIncr;
            if (p > 0) {
              node.appendChild (this.makeDiv(x++, oy, 1, y - oy));
              p += pru;
              oy = y;
            }
            else p += pr;
          }
          node.appendChild (this.makeDiv(x2, oy, 1, y2 - oy + 1));
        }
    }
//  this.position.appendChild(node);
  return node;
};

//  ---------------------------------------------------------------------------
function makeLine2D(x1, y1, x2, y2, stroke, color, opacity) {
//  alert (this.id+'.makeLine2D('+x1+', '+y1+', '+x2+', '+y2+')');
  var node = document.createElement ('div');
  node.id = "line2D" + (++this.iLine);
  if (stroke) this.setStroke(stroke);
  if (color) this.setColor(color);
//  if (opacity) this.setOpacity(opacity);
  if (x1 > x2) {
    var _x2 = x2;
    var _y2 = y2;
    x2 = x1;
    y2 = y1;
    x1 = _x2;
    y1 = _y2;
  }
  var dx = x2 - x1,
    dy = Math.abs(y2 - y1),
    x = x1,
    y = y1,
    yIncr = (y1 > y2) ? -1 : 1;

  var s = this.stroke;
  if (dx >= dy) {
      if (dx > 0 && s - 3 > 0) {
        var _s = (s * dx * Math.sqrt(1 + dy * dy / (dx * dx)) - dx - (s >> 1) * dy) / dx;
        _s = (!(s - 4) ? Math.ceil(_s) : Math.round(_s)) + 1;
      }
      else var _s = s;
      var ad = Math.ceil(s / 2);

      var pr = dy << 1,
        pru = pr - (dx << 1),
        p = pr - dx,
        ox = x;
      while (dx > 0) {
          --dx;
          ++x;
          if (p > 0) {
            node.appendChild (this.makeDiv(ox, y, x - ox + ad, _s));
            y += yIncr;
            p += pru;
            ox = x;
          }
          else p += pr;
        }
      node.appendChild (this.makeDiv(ox, y, x2 - ox + ad + 1, _s));
    }

  else {
      if (s - 3 > 0) {
        var _s = (s * dy * Math.sqrt(1 + dx * dx / (dy * dy)) - (s >> 1) * dx - dy) / dy;
        _s = (!(s - 4) ? Math.ceil(_s) : Math.round(_s)) + 1;
      }
      else var _s = s;
      var ad = Math.round(s / 2);

      var pr = dx << 1,
        pru = pr - (dy << 1),
        p = pr - dy,
        oy = y;
      if (y2 <= y1) {
          ++ad;
          while (dy > 0) {
            --dy;
            if (p > 0) {
              node.appendChild (this.makeDiv(x++, y, _s, oy - y + ad));
              y += yIncr;
              p += pru;
              oy = y;
            }
            else {
              y += yIncr;
              p += pr;
            }
          }
          node.appendChild (this.makeDiv(x2, y2, _s, oy - y2 + ad));
        }
      else {
          while (dy > 0) {
            --dy;
            y += yIncr;
            if (p > 0) {
              node.appendChild (this.makeDiv(x++, oy, _s, y - oy + ad));
              p += pru;
              oy = y;
            }
            else p += pr;
          }
          node.appendChild (this.makeDiv(x2, oy, _s, y2 - oy + ad + 1));
        }
    }
//  this.position.appendChild(node);
  return node;
}

//  ---------------------------------------------------------------------------
function makeLineDott(x1, y1, x2, y2, stroke, color, opacity) {
//  alert (this.id+'.makeLineDott('+x1+', '+y1+', '+x2+', '+y2+')');
  var node = document.createElement ('div');
  node.id = id ? id : "lineDott" + (++this.iLine);
  if (stroke) this.setStroke(stroke);
  if (color) this.setColor(color);
//  if (opacity) this.setOpacity(opacity);
  if (x1 > x2) {
    var _x2 = x2;
    var _y2 = y2;
    x2 = x1;
    y2 = y1;
    x1 = _x2;
    y1 = _y2;
  }
  var dx = x2 - x1,
    dy = Math.abs(y2 - y1),
    x = x1,
    y = y1,
    yIncr = (y1 > y2) ? -1 : 1,
    drw = true;
  if (dx >= dy) {
      var pr = dy << 1,
        pru = pr - (dx << 1),
        p = pr - dx;
      while (dx > 0) {
          --dx;
          if (drw) this.makeDiv(x, y, 1, 1);
          drw = !drw;
          if (p > 0) {
            y += yIncr;
            p += pru;
          }
          else p += pr;
          ++x;
        }
    }
  else {
      var pr = dx << 1,
        pru = pr - (dy << 1),
        p = pr - dy;
      while (dy > 0) {
          --dy;
          if (drw) this.makeDiv(x, y, 1, 1);
          drw = !drw;
          y += yIncr;
          if (p > 0) {
            ++x;
            p += pru;
          }
          else p += pr;
        }
    }
  if (drw) this.makeDiv(x, y, 1, 1);
//  this.position.appendChild(node);
  return node;
}

//  ---------------------------------------------------------------------------
function makeOval(left, top, width, height) {
//  alert (this.id+'.makeOval('+left+', '+top+', '+width+', '+height+')');
  var node = document.createElement ('div');
  node.id = "oval" + (++this.iCirc);
  left -= width*0.5;
  top -= height*0.5;
  node.style.position ='absolute';
  node.style.left   = left + 'px';
  node.style.top    = top  + 'px';
  node.style.width  = width + 'px';
  node.style.height = height + 'px';
  left = 0;
  top  = 0;
  var a = (++width) >> 1,
    b = (++height) >> 1,
    wod = width & 1,
    hod = height & 1,
    cx = left + a,
    cy = top + b,
    x = 0,
    y = b,
    ox = 0,
    oy = b,
    aa2 = (a * a) << 1,
    aa4 = aa2 << 1,
    bb2 = (b * b) << 1,
    bb4 = bb2 << 1,
    st = (aa2 >> 1) * (1 - (b << 1)) + bb2,
    tt = (bb2 >> 1) - aa2 * ((b << 1) - 1),
    w, h;
    while (y > 0) {
      if (st < 0) {
        st += bb2 * ((x << 1) + 3);  // >
        tt += bb4 * (++x);
      }
      else if (tt < 0) {
        st += bb2 * ((x << 1) + 3) - aa4 * (y - 1);  // >
        tt += bb4 * (++x) - aa2 * (((y--) << 1) - 3);  // >
        w = x - ox;
        h = oy - y;
        if ((w & 2) && (h & 2)) {
          node.appendChild (this.makeOvalQds(cx, cy, x - 2, y + 2, 1, 1, wod, hod));
          node.appendChild (this.makeOvalQds(cx, cy, x - 1, y + 1, 1, 1, wod, hod));
        }
        else
          node.appendChild (this.makeOvalQds(cx, cy, x - 1, oy, w, h, wod, hod));
        ox = x;
        oy = y;
      }
      else {
        tt -= aa2 * ((y << 1) - 3);  // >
        st -= aa4 * (--y);
      }
    }
  w = a - ox + 1;
  h = (oy << 1) + hod;  // >
  y = cy - oy;
  node.appendChild (this.makeDiv(cx - a, y, w, h));
  node.appendChild (this.makeDiv(cx + ox + wod - 1, y, w, h));
//  this.position.appendChild(node);
  return node;
}

//  ---------------------------------------------------------------------------
function makeOval2D(left, top, width, height) {
  var node = document.createElement ('div');
  node.id = "oval2d" + (++this.iCirc);
  var s = this.stroke;
  width += s + 1;
  height += s + 1;
  var a = width >> 1,
    b = height >> 1,
    wod = width & 1,
    hod = height & 1,
    cx = left + a,
    cy = top + b,
    x = 0,
    y = b,
    aa2 = (a * a) << 1,
    aa4 = aa2 << 1,
    bb2 = (b * b) << 1,
    bb4 = bb2 << 1,
    st = (aa2 >> 1) * (1 - (b << 1)) + bb2,
    tt = (bb2 >> 1) - aa2 * ((b << 1) - 1);

  if (s - 4 < 0 && (!(s - 2) || width - 51 > 0 && height - 51 > 0)) {
      var ox = 0,
        oy = b,
        w, h, pxw;
      while (y > 0) {
          if (st < 0) {
            st += bb2 * ((x << 1) + 3);  // -->
            tt += bb4 * (++x);
          }
          else if (tt < 0) {
            st += bb2 * ((x << 1) + 3) - aa4 * (y - 1); // -->
            tt += bb4 * (++x) - aa2 * (((y--) << 1) - 3); // -->
            w = x - ox;
            h = oy - y;

            if (w - 1) {
              pxw = w + 1 + (s & 1);
              h = s;
            }
            else if (h - 1) {
              pxw = s;
              h += 1 + (s & 1);
            }
            else pxw = h = s;
              node.appendChild (this.makeOvalQds(cx, cy, x - 1, oy, pxw, h, wod, hod));
            ox = x;
            oy = y;
          }
          else {
            tt -= aa2 * ((y << 1) - 3);  // -->
            st -= aa4 * (--y);
          }
        }
      node.appendChild (this.makeDiv(cx - a, cy - oy, s, (oy << 1) + hod));
      node.appendChild (this.makeDiv(cx + a + wod - s, cy - oy, s, (oy << 1) + hod));
    }

  else {
      var _a = (width - (s << 1)) >> 1,
        _b = (height - (s << 1)) >> 1,
        _x = 0,
        _y = _b,
        _aa2 = (_a * _a) << 1,
        _aa4 = _aa2 << 1,
        _bb2 = (_b * _b) << 1,
        _bb4 = _bb2 << 1,
        _st = (_aa2 >> 1) * (1 - (_b << 1)) + _bb2,
        _tt = (_bb2 >> 1) - _aa2 * ((_b << 1) - 1),
        pxl = new Array(),
        pxt = new Array(),
        _pxb = new Array();
      pxl[0] = 0;
      pxt[0] = b;
      _pxb[0] = _b - 1;
      while (y > 0) {
          if (st < 0) {
            pxl[pxl.length] = x;
            pxt[pxt.length] = y;
            st += bb2 * ((x << 1) + 3);
            tt += bb4 * (++x);
          }
          else if (tt < 0) {
            pxl[pxl.length] = x;
            st += bb2 * ((x << 1) + 3) - aa4 * (y - 1);
            tt += bb4 * (++x) - aa2 * (((y--) << 1) - 3);
            pxt[pxt.length] = y;
          }
          else {
            tt -= aa2 * ((y << 1) - 3);
            st -= aa4 * (--y);
          }

          if (_y > 0) {
            if (_st < 0) {
              _st += _bb2 * ((_x << 1) + 3);
              _tt += _bb4 * (++_x);
              _pxb[_pxb.length] = _y - 1;
            }
            else if (_tt < 0) {
              _st += _bb2 * ((_x << 1) + 3) - _aa4 * (_y - 1);
              _tt += _bb4 * (++_x) - _aa2 * (((_y--) << 1) - 3);
              _pxb[_pxb.length] = _y - 1;
            }
            else {
              _tt -= _aa2 * ((_y << 1) - 3);
              _st -= _aa4 * (--_y);
              _pxb[_pxb.length - 1]--;
            }
          }
        }

      var ox = -wod,
        oy = b,
        _oy = _pxb[0],
        l = pxl.length,
        w, h;
      for (var i = 0; i < l; i++) {
          if (typeof _pxb[i] != "undefined") {
            if (_pxb[i] < _oy || pxt[i] < oy) {
              x = pxl[i];
              node.appendChild (this.makeOvalQds(cx, cy, x, oy, x - ox, oy - _oy, wod, hod));
              ox = x;
              oy = pxt[i];
              _oy = _pxb[i];
            }
          }
          else {
            x = pxl[i];
            node.appendChild (this.makeDiv(cx - x, cy - oy, 1, (oy << 1) + hod));
            node.appendChild (this.makeDiv(cx + ox + wod, cy - oy, 1, (oy << 1) + hod));
            ox = x;
            oy = pxt[i];
          }
        }
      node.appendChild (this.makeDiv(cx - a, cy - oy, 1, (oy << 1) + hod));
      node.appendChild (this.makeDiv(cx + ox + wod, cy - oy, 1, (oy << 1) + hod));
    }
//  this.position.appendChild(node);
  return node;
}

//  --------------------------------------------------------------------------->
function makeOvalDott(left, top, width, height) {
  var node = document.createElement ('div');
  node.id = "ovalDott" + (++this.iCirc);
  var a = (++width) >> 1,
    b = (++height) >> 1,
    wod = width & 1,
    hod = height & 1,
    hodu = hod ^ 1,
    cx = left + a,
    cy = top + b,
    x = 0,
    y = b,
    aa2 = (a * a) << 1,
    aa4 = aa2 << 1,
    bb2 = (b * b) << 1,
    bb4 = bb2 << 1,
    st = (aa2 >> 1) * (1 - (b << 1)) + bb2,
    tt = (bb2 >> 1) - aa2 * ((b << 1) - 1),
    drw = true;
  while (y > 0) {
      if (st < 0) {
        st += bb2 * ((x << 1) + 3);
        tt += bb4 * (++x);
      }
      else if (tt < 0) {
        st += bb2 * ((x << 1) + 3) - aa4 * (y - 1);
        tt += bb4 * (++x) - aa2 * (((y--) << 1) - 3);
      }
      else {
        tt -= aa2 * ((y << 1) - 3);
        st -= aa4 * (--y);
      }
      if (drw && y >= hodu) this.makeOvalQds(cx, cy, x, y, 1, 1, wod, hod);
      drw = !drw;
    }
//  this.position.appendChild(node);
  return node;
};

//  ---------------------------------------------------------------------------
makeRect = function (x, y, w, h, color, strokeColor, stroke, opacity) {
//  alert(this.id+'.makeRect ('+x+', '+y+', '+w+', '+h+', '+color+', '+strokeColor+', '+stroke+', '+opacity+')');
  if (color) {
    this.setColor(color);
    node = this.makeDiv(x, y, w, h);
    node.id = "rect" + (++this.iRect);
    if (strokeColor) {
      node.style.borderWidth = '1px';
      node.style.borderStyle = 'solid';
      node.style.borderColor = strokeColor;
    }
  } else {
    if (stroke) this.setStroke(stroke);
    if (strokeColor) this.setColor(strokeColor);
//  if (opacity) this.setOpacity(opacity);
    var s = this.stroke;
    var node = this.makeDiv(x, y, w, h); /**/
    node.appendChild (this.makeDiv(0, 0, w, s));
    node.appendChild (this.makeDiv(w, 0, s, h));
    node.appendChild (this.makeDiv(0, h, w + s, s));
    node.appendChild (this.makeDiv(0, s, s, h - s));
  }
  return node;
};

//  ---------------------------------------------------------------------------
makeRectDott = function (x, y, w, h, color, strokeColor, stroke, opacity) {
//  if (opacity) this.setOpacity(opacity);
  var node = document.createElement ('div');
  node.id = "rectDott" + (++this.iRect);
  if (color) {
    this.setColor(color);
    node.appendChild (this.makeDiv(x, y, w, h));
    if (strokeColor) node.style.border = '1px solid '+strokeColor;
  } 
  if (strokeColor) {
    if (stroke) this.setStroke(stroke);
    this.setColor(strokeColor);
    node.appendChild (this.drawLine(x, y, x + w, y));
    node.appendChild (this.drawLine(x + w, y, x + w, y + h));
    node.appendChild (this.drawLine(x, y + h, x + w, y + h));
    node.appendChild (this.drawLine(x, y, x, y + h));
  }
//  this.position.appendChild(node);
  return node;
};

//  ---------------------------------------------------------------------------
function jsgFont() {
  this.NONE   = 'none';
  this.NORMAL = 'normal';
  this.BOLD   = 'bold';
  this.ITALIC = 'italic';
}
var Font = new jsgFont();

//  ---------------------------------------------------------------------------
function jsgStroke() {
  this.DOTTED = -1;
}

//  ---------------------------------------------------------------------------

var Stroke = new jsgStroke();

//  ---------------------------------------------------------------------------
function jsGraphics() {
  this.id = 'jsGraphics';
}

//  ---------------------------------------------------------------------------

jsGraphics.prototype = new svgJs ();

//  ----------------------------------------------------------------------------
  jsGraphics.prototype.remove = function (node) {
//    alert (this.id+'.remove ('+node.id+')');
    if (!node) node = this.position;
    if (!node) return this;
//    var i = 0;
//    alert (++i+': '+this.id+'.remove ('+node.nodeName+'.'+node.id+') has '+node.childNodes.length+' childNodes');
    while (node.hasChildNodes()) {
      this.remove (node.lastChild);
      node.removeChild (node.lastChild);
    }
    return this;
  };

  //  --------------------------------------------------------------------------->
jsGraphics.prototype.initNative = function (wnd, cnv, width, height) {
  this.setStroke(1);
  this.setFont("'trebuchet ms', verdana,geneva,helvetica,sans-serif", "12px", Font.NONE, Font.NORMAL);
  this.color = "#000000";
//  this.htm = "";
  this.wnd = isUndefined(wnd) ? window : wnd;

  if (!jg_ok) _chkDHTM();
  if (jg_ok) {
    if (cnv) {
      if (typeof(cnv) == "string")
        this.cont = document.all ? (this.wnd.document.all[cnv] || null) : document.getElementById ? (this.wnd.document.getElementById(cnv) || null) : null;
      else
        if (cnv == window.document)
          this.cont = document.getElementsByTagName("body")[0];
        else // If cnv is a direct reference to a canvas DOM node (option suggested by Andreas Luleich)
          this.cont = cnv;
      // Create new canvas inside container DIV. Thus the drawing and clearing methods won't interfere with the container's inner html. Solution suggested by Vladimir.
      this.cnv = this.wnd.document.createElement("div");
      this.cnv.style.fontSize = 0;
      this.cont.appendChild(this.cnv);
      this.paint = jg_dom ? _pntCnvDom : _pntCnvIe;
    }
    else this.paint = _pntDoc;
  }
  else this.paint = _pntN;

  this.setPrintable(false);
  this.canvas = this.cnv;
  if (!this.canvas) {
    alert("###  error: sorry, the div-container: "+id+' does not exist. We will take document.body instead');
    this.canvas = document.body;
  }
  this.canvas.id = "canvas";
  return this.canvas;
};

  //  ----------------------------------------------------------------------------
  jsGraphics.prototype.makeContainer = function (id) {
    var node = document.createElement('div');
    node.id = id ? id : "container" + (++this.iContainer);
    this.position.appendChild(node);
    this.position = node;
    return this.position;
  }

  //  ----------------------------------------------------------------------------
  jsGraphics.prototype.setBackGroundColor = function (color) {
    this.backGroundNode.style.backgroundColor=color;
    return this.backGroundNode;
  };

  //  -------------------------------------------------------------------------
  jsGraphics.prototype.setStroke = function (x) {
    this.stroke = x;
    if (!(x + 1)) {
      this.drawLine = makeLineDott;
      this.makeOval = makeOvalDott;
      this.drawRect = makeRectDott;
    }
    else if (x - 1 > 0) {
      this.drawLine = makeLine2D;
      this.makeOval = makeOval2D;
      this.drawRect = makeRect;
    }
    else {
      this.drawLine = makeLine;
      this.makeOval = makeOval;
      this.drawRect = makeRect;
    }
  };

  //  -------------------------------------------------------------------------
  jsGraphics.prototype.setPrintable = function (arg) {
    this.printable = arg;
    if (jg_fast) {
      this.makeDiv = makeDivIe;
      this._htmRpc = arg ? _htmPrtRpc : _htmRpc;
    }
    else this.makeDiv = arg ? makeDivPrt : makeDiv;
  };

  //  -------------------------------------------------------------------------
  jsGraphics.prototype.setFont = function (family, size, decoration, weight) {
    if (family) this.fontFamily = family;
    if (size) this.fontSize = size;
    if (decoration) this.textDecoration = decoration;
    if (weight) this.fontWeight = weight;
  };

  //  -------------------------------------------------------------------------
  jsGraphics.prototype.drawPolyline = this.drawPolyLine = function (x, y) {
    var id = "path" + (++this.iPath);
    var fit = new this.fitToNode (id, x, y, this.stroke);
    var node = fit.node; x = fit.x; y = fit.y;
    for (var i=0; i< x.length-1; i++)
      node.appendChild (this.drawLine(x[i], y[i], x[i + 1], y[i + 1]));
//    this.position.appendChild(node);
    return node;
  };

  //  -------------------------------------------------------------------------
  jsGraphics.prototype.fitToNode = function (id, x, y, stroke) {
    var xMin = x.min();
    var xMax = x.max();
    var yMin = y.min();
    var yMax = y.max();
    this.x = x.minus(xMin);
    this.y = y.minus(yMin);
    this.node = new makeDiv(xMin, yMin, xMax-xMin+stroke, yMax-yMin+stroke);
    this.node.id = id;
  };

  //  -------------------------------------------------------------------------
  jsGraphics.prototype.fillRect = function (x, y, w, h) {
    var rect = this.makeDiv(x, y, w, h);
    rect.id = "rect" + (++this.iRect);
    return rect;
  };

  //  -------------------------------------------------------------------------
  jsGraphics.prototype.drawPolygon = function (x, y, id) {
    var node = this.drawPolyline (x, y, id ? id : "path" + (++this.iPath));
    node.appendChild (this.drawLine(x[x.length - 1], y[x.length - 1], x[0], y[0]));
//    this.position.appendChild(node);
    return node;
  };

  //  ----------------------------------------------------------------------------
  jsGraphics.prototype.drawCircle = function (x, y, r, color, opacity, id) {
    //  opacity, id will be ignored for now!
    if (color) this.setColor(color);
    return this.drawEllipse (x, y, 2*r, 2*r);
  };

  //  ----------------------------------------------------------------------------
  jsGraphics.prototype.changeCircle = function (node, x, y, r, color, opacity) {
//    alert (this.id+'.changeCircle ('+node.id+', '+x+', '+y+', '+r+', '+color+', '+opacity+')');
    if (r) {
      if (x != undefined) node.style.left = Math.max (x-r, 0)+'px';
      if (y != undefined) node.style.top  = Math.max (y-r, 0)+'px';
    }
    if (color != undefined)	
      node = this.changeStyle (node, 'color', color)    //  opacity, id will be ignored for now!
    return node;
  };

//  ---------------------------------------------------------------------------
  jsGraphics.prototype.changeStyle = function (node, rule, value) {
    if (!node) return this;
    if (node.hasChildNodes()) {
//      alert ('yes '+node.nodeName+'.'+node.id+' has '+node.childNodes.length+' childNodes');
      for (var i=0; i < node.childNodes.length; i++)
        this.changeStyle (node.childNodes[i], rule, value);
    } else {
//      alert ('no '+node.nodeName+'.'+node.id+' doesn\'t have childNodes');
      node.style[rule] = value;
    }
    return node;
  };

  //  ----------------------------------------------------------------------------
  jsGraphics.prototype.changeLine = function (node, x1, y1, x2, y2, stroke, color, opacity) {
    if (!node) return node;
    if (!node.hasChildNodes()) return node;
//    alert (this.id+'.changeLine'+node.id+', '+x1+', '+y1+', '+x2+', '+y2+', '+stroke+', '+color+', '+opacity+')');
    for (var i=0; i < node.childNodes.length; i++) {
      if (node.childNodes[i].hasChildNodes())
        this.changeLine (node, x1, y1, x2, y2, stroke, color, opacity);
      var dx = (Math.abs(x2-x1)+1);
      var dy = (Math.abs(y2-y1)+1);
      x1 = (x2-x1) < 0 ? x1 - dx : x1;
      y1 = (y2-y1) < 0 ? y1 - dy : y1;
      node.childNodes[i].style.left   = x1+'px';
      node.childNodes[i].style.top    = y1+'px';
      node.childNodes[i].style.width  = dx+'px';
      node.childNodes[i].style.height = dy+'px';
    }
    if (color) this.setColor (color);
    if (stroke) this.setStroke (stroke);
    if (opacity) node.setOpacity (opacity);
    return node;
  }

  //  ----------------------------------------------------------------------------
  jsGraphics.prototype.changeText = function (node, x, y, text, dx, dy, fontSize, color, anchor) {
    if (!node) return node;
//    alert(this.id + '.changeText: ' + node.id + ', ' + x + ', ' + y + ', ' + text + ', ' + dx + ', ' + dy + ', ' + fontSize + ', ' + color + ', ' + anchor + ')');
    if (x        != undefined) node.style.left=x+'px';
    if (y        != undefined) node.style.top =y+'px';
    if (text     != undefined) node.firstChild.nodeValue = text;
    if (fontSize != undefined) node.style.fontSize = fontSize;
    if (color    != undefined) node.style.color = color;
//    if (anchor != undefined) node.style. ...  anchor);
    return node;
  }

  //  -------------------------------------------------------------------------
  jsGraphics.prototype.drawEllipse = this.drawOval = function (x, y, w, h) {
    return this.makeOval(x, y, w, h);
  };

  //  ----------------------------------------------------------------------------
  jsGraphics.prototype.fillCircle = function (x, y, r, color, opacity, id) {
    //  opacity, id will be ignored for now!
    if (color) this.setColor(color);
    return this.fillEllipse (x, y, 2*r, 2*r);
  };

  //  -------------------------------------------------------------------------
  jsGraphics.prototype.fillEllipse = this.fillOval = function (left, top, w, h) {
    var node = document.createElement ('div');
    node.id = "circ" + (++this.iCirc);
    left -= w*0.5;
    top -= h*0.5;
    node = setDimension(node, left, top, w, h);
    left = 0;
    top  = 0;
    var a = w >> 1,
    b = h >> 1,
    wod = w & 1,
    hod = h & 1,
    cx = left + a,
    cy = top + b,
    x = 0,
    y = b,
    oy = b,
    aa2 = (a * a) << 1,
    aa4 = aa2 << 1,
    bb2 = (b * b) << 1,
    bb4 = bb2 << 1,
    st = (aa2 >> 1) * (1 - (b << 1)) + bb2,
    tt = (bb2 >> 1) - aa2 * ((b << 1) - 1),
    xl, dw, dh;
    if (w) while (y > 0) {
        if (st < 0) {
          st += bb2 * ((x << 1) + 3);
          tt += bb4 * (++x);
        }
        else if (tt < 0) {
          st += bb2 * ((x << 1) + 3) - aa4 * (y - 1);
          xl = cx - x;
          dw = (x << 1) + wod;
          tt += bb4 * (++x) - aa2 * (((y--) << 1) - 3);
          dh = oy - y;
          node.appendChild (this.makeDiv(xl, cy - oy, dw, dh));
          node.appendChild (this.makeDiv(xl, cy + y + hod, dw, dh));
          oy = y;
        }
        else {
          tt -= aa2 * ((y << 1) - 3);
          st -= aa4 * (--y);
        }
      }
    node.appendChild (this.makeDiv(cx - a, cy - oy, w, (oy << 1) + hod));
//    this.position.appendChild(node);
    return node;
  };

  //  ------------------------------------------------------------------------->
jsGraphics.prototype.fillArc = function (iL, iT, iW, iH, fAngA, fAngZ) {
    var a = iW >> 1,
      b = iH >> 1,
      iOdds = (iW & 1) | ((iH & 1) << 16),
      cx = iL + a,
      cy = iT + b,
      x = 0,
      y = b,
      ox = x,
      oy = y,
      aa2 = (a * a) << 1,
      aa4 = aa2 << 1,
      bb2 = (b * b) << 1,
      bb4 = bb2 << 1,
      st = (aa2 >> 1) * (1 - (b << 1)) + bb2,
      tt = (bb2 >> 1) - aa2 * ((b << 1) - 1),
    // Vars for radial boundary lines
    xEndA, yEndA, xEndZ, yEndZ, iSects = (1 << (Math.floor((fAngA %= 360.0) / 180.0) << 3)) | (2 << (Math.floor((fAngZ %= 360.0) / 180.0) << 3)) | ((fAngA >= fAngZ) << 16),
      aBndA = new Array(b + 1),
      aBndZ = new Array(b + 1);

    // Set up radial boundary lines
    fAngA *= Math.PI / 180.0;
    fAngZ *= Math.PI / 180.0;
    xEndA = cx + Math.round(a * Math.cos(fAngA));
    yEndA = cy + Math.round(-b * Math.sin(fAngA));
    makeLineVirt(aBndA, cx, cy, xEndA, yEndA);
    xEndZ = cx + Math.round(a * Math.cos(fAngZ));
    yEndZ = cy + Math.round(-b * Math.sin(fAngZ));
    makeLineVirt(aBndZ, cx, cy, xEndZ, yEndZ);

    while (y > 0) {
        if (st < 0) // Advance x
        {
          st += bb2 * ((x << 1) + 3);
          tt += bb4 * (++x);
        }
        else if (tt < 0) // Advance x and y
        {
          st += bb2 * ((x << 1) + 3) - aa4 * (y - 1);
          ox = x;
          tt += bb4 * (++x) - aa2 * (((y--) << 1) - 3);
          this.makeArcDiv(ox, y, oy, cx, cy, iOdds, aBndA, aBndZ, iSects);
          oy = y;
        }
        else // Advance y
        {
          tt -= aa2 * ((y << 1) - 3);
          st -= aa4 * (--y);
          if (y && (aBndA[y] != aBndA[y - 1] || aBndZ[y] != aBndZ[y - 1])) {
            this.makeArcDiv(x, y, oy, cx, cy, iOdds, aBndA, aBndZ, iSects);
            ox = x;
            oy = y;
          }
        }
      }
    this.makeArcDiv(x, 0, oy, cx, cy, iOdds, aBndA, aBndZ, iSects);
    if (iOdds >> 16) { // Odd height   
        if (iSects >> 16) // Start-angle > end-angle
        {
          var xl = (yEndA <= cy || yEndZ > cy) ? (cx - x) : cx;
          this.makeDiv(xl, cy, x + cx - xl + (iOdds & 0xffff), 1);
        }
        else if ((iSects & 0x01) && yEndZ > cy) this.makeDiv(cx - x, cy, x, 1);
      }
  };

  //  -------------------------------------------------------------------------
jsGraphics.prototype.fillPolygon = function (array_x, array_y) {
  /* fillPolygon method, implemented by Matthieu Haller.
   This javascript function is an adaptation of the gdImageFilledPolygon for Walter Zorn lib.
   C source of GD 1.8.4 found at http://www.boutell.com/gd/
   
   THANKS to Kirsten Schulz for the polygon fixes!
   
   The intersection finding technique of this code could be improved
   by remembering the previous intertersection, and by using the slope.
   That could help to adjust intersections to produce a nice interior_extrema. */

    var i;
    var y;
    var miny, maxy;
    var x1, y1;
    var x2, y2;
    var ind1, ind2;
    var ints;
    var xMax = 0;
    var yMax = 0;

    var fit = new this.fitToNode ("fillPolygon" + (++this.iShape), array_x, array_y, this.stroke);
    node = fit.node; 
    array_x = fit.x; 
    array_y = fit.y;

    var n = array_x.length;
    if (!n) return;

    miny = array_y[0];
    maxy = array_y[0];
    for (i = 1; i < n; i++) {
      if (array_y[i] < miny) miny = array_y[i];
      if (array_y[i] > maxy) maxy = array_y[i];
    }
    for (y = miny; y <= maxy; y++) {
      var polyInts = new Array();
      ints = 0;
      for (i = 0; i < n; i++) {
        if (!i) {
          ind1 = n - 1;
          ind2 = 0;
        }
        else {
          ind1 = i - 1;
          ind2 = i;
        }
        y1 = array_y[ind1];
        y2 = array_y[ind2];
        if (y1 < y2) {
          x1 = array_x[ind1];
          x2 = array_x[ind2];
        }
        else if (y1 > y2) {
          y2 = array_y[ind1];
          y1 = array_y[ind2];
          x2 = array_x[ind1];
          x1 = array_x[ind2];
        }
        else continue;

        //  Modified 11. 2. 2004 Walter Zorn
        if ((y >= y1) && (y < y2)) polyInts[ints++] = Math.round((y - y1) * (x2 - x1) / (y2 - y1) + x1);
        else if ((y == maxy) && (y > y1) && (y <= y2)) polyInts[ints++] = Math.round((y - y1) * (x2 - x1) / (y2 - y1) + x1);// -->
      }
      polyInts.sort(this._CompInt);
      var x = 0, w = 0, h = 1;
      for (i = 0; i < ints; i += 2) {
        x = polyInts[i];
        w = polyInts[i + 1] - polyInts[i] + 1;
        node.appendChild (this.makeDiv(x, y, w, 1)); 
        xMax = Math.max (xMax, x+w);
        yMax = Math.max (yMax, y+h);
      }
    }
    node = setDimension(node, 0, 0, xMax, yMax);
//    node.style.border = '1px solid black';
//    alert ('setDimension('+node.id+', '+0+', '+0+', '+(xMax)+', '+(yMax)+')');
//    this.position.appendChild(node);
    return node;
 };

  //  ------------------------------------------------------------------------->
  jsGraphics.prototype.drawText = function (x, y, text, dx, dy, fontSize, color, fontWeight, fontName, anchor, textPath) {
//    alert (this.id+'.drawText ('+x+', '+y+', '+text+', '+dx+', '+dy+', '+fontSize+', '+color+', '+fontWeight+', '+fontName+', '+anchor+', '+textPath+')');
    dx = dx == undefined ? this.dx : dx;
    dy = dy == undefined ? this.dy : dy;
    fontSize = fontSize == undefined ? this.fontSize : fontSize;
    color = color == undefined ? this.color : color;
    fontWeight = fontWeight == undefined ? this.fontWeight : fontWeight;
    fontName = fontName == undefined ? this.fontName : fontName;
    anchor = anchor == undefined ? this.anchor : anchor;
    return this.drawString (x, y, text, dx, dy, fontSize, color, fontWeight, fontName, anchor, textPath);
  };

  //  ------------------------------------------------------------------------->
  jsGraphics.prototype.drawString = function (x, y, text, dx, dy, fontSize, color, fontWeight, fontName, anchor, textPath) {
//    this.htm += '<div style="position:absolute;white-space:nowrap;' + 'left:' + x + 'px;' + 'top:' + y + 'px;' + 'font-family:' + this.fontFamily + ';' + 'font-size:' + this.fontSize + ';' + 'color:' + this.color + ';' + this.fontWeight + '">' + text + '<\/div>';
//  alert (this.id+'.drawString ('+x+', '+y+', '+text+', '+dx+', '+dy+', '+fontSize+', '+color+', '+fontWeight+', '+fontName+', '+anchor+', '+textPath+')');
    node = document.createElement('div');
    node.id = "text" + (++this.iText);
    node.style.position = 'absolute';
    node.style.whiteSpace = 'nowrap';
    node.style.left = x + 'px';
    node.style.top = y - Math.floor(fontSize * 1.0) + 'px';
    node.style.fontFamily = fontName ? fontName : this.fontFamily; // alert (fontSize+'pt');
    node.style.fontSize = fontSize ? fontSize+'pt' : this.fontSize;
    node.style.color = color ? color : this.color; 
    node.style.textDecoration = /*textDecoration ? textDecoration :*/ this.textDecoration; 
    node.style.fontWeight =  fontWeight ? fontWeight : this.fontWeight; 
//    if (!isSting(text)) alert (this.id+'.drawString: '+text+' is no Text');
    node.appendChild(document.createTextNode(text));
//    this.position.appendChild(node);
    return node;
  };

  //  -------------------------------------------------------------------------
  jsGraphics.prototype.drawStringRect = function (text, x, y, width, halign, fontSize, color, fontWeight, fontName, anchor) {
  // added by Rick Blommers, allows to specify the size of the text rectangle and to align the text both horizontally (e.g. right) and vertically within that rectangle.
//    this.htm += '<div style="position:absolute;overflow:hidden;' + 'left:' + x + 'px;' + 'top:' + y + 'px;' + 'width:' + width + 'px;' + 'text-align:' + halign + ';' + 'font-family:' + this.fontFamily + ';' + 'font-size:' + this.fontSize + ';' + 'color:' + this.color + ';' + this.fontWeight + '">' + text + '<\/div>';
    var node = document.createElement ('div');
    node.id = "textRect" + (++this.iText);
    node.style.position = 'absolute';
    node.style.overflow = 'hidden';
    node.style.left = x + 'px';
    node.style.top = y - Math.floor(fontSize * 1.0) + 'px';
    node.style.width = width + 'px';
    node.style.textAlign = halign;
    node.style.fontFamily = this.fontFamily = fontName;
    node.style.fontSize = this.fontSize = fontSize;
    node.style.color = this.color = color; 
    node.style.textDecoration = this.textDecoration; // = textDecoration; 
    node.style.fontWeight = this.fontWeight = fontWeight; 
    node.appendChild(document.createTextNode(text));
//    this.position.appendChild(node);
    return node;
  };

  //  -------------------------------------------------------------------------
  jsGraphics.prototype.drawImage = function (imgSrc, x, y, w, h, a) {
    var node = document.createElement ('div');
    node.id = "image" + (++this.iImage);
    node.style.position = 'absolute';
    node.style.left = x + 'px';
    node.style.top  = y + 'px'; 
    node.style.width  = w ? w + 'px' : '';
    node.style.height = h ? h + 'px' : '';
    var img = document.createElement('img');
    img.src = imgSrc;
    img.width  = w ? w + 'px' : '';
    img.height = h ? h + 'px' : '';
    img.a = a ? a : '';
    node.appendChild(img);
//    this.position.appendChild(node);
    return node;
  };

  //  ------------------------------------------------------------------------->
  jsGraphics.prototype.clear = function () {
    return this.position = null;
  };

  //  ------------------------------------------------------------------------->
  jsGraphics.prototype.makeOvalQds = function (cx, cy, x, y, w, h, wod, hod) {
    var node = document.createElement ('div');
    node.id = "oval" + (++this.iCirc);
    var xl = cx - x,
    xr = cx + x + wod - w,
    yt = cy - y,
    yb = cy + y + hod - h;
    if (xr > xl + w) {
      node.appendChild(this.makeDiv(xr, yt, w, h));
      node.appendChild(this.makeDiv(xr, yb, w, h));
    } else
      w = xr - xl + w;
    node.appendChild(this.makeDiv(xl, yt, w, h));
    node.appendChild(this.makeDiv(xl, yb, w, h));
//    this.position.appendChild(node);
    return node;
  };

  //  -------------------------------------------------------------------------
  jsGraphics.prototype.makeArcDiv = function (x, y, oy, cx, cy, iOdds, aBndA, aBndZ, iSects) {
    var xrDef = cx + x + (iOdds & 0xffff),
      y2, h = oy - y,
      xl, xr, w;

    if (!h) h = 1;
    x = cx - x;

    if (iSects & 0xff0000) // Start-angle > end-angle
    {
        y2 = cy - y - h;
        if (iSects & 0x00ff) {
          if (iSects & 0x02) {
            xl = Math.max(x, aBndZ[y]);
            w = xrDef - xl;
            if (w > 0) this.makeDiv(xl, y2, w, h);
          }
          if (iSects & 0x01) {
            xr = Math.min(xrDef, aBndA[y]);
            w = xr - x;
            if (w > 0) this.makeDiv(x, y2, w, h);
          }
        }
        else this.makeDiv(x, y2, xrDef - x, h);
        y2 = cy + y + (iOdds >> 16);
        if (iSects & 0xff00) {
          if (iSects & 0x0100) {
            xl = Math.max(x, aBndA[y]);
            w = xrDef - xl;
            if (w > 0) this.makeDiv(xl, y2, w, h);
          }
          if (iSects & 0x0200) {
            xr = Math.min(xrDef, aBndZ[y]);
            w = xr - x;
            if (w > 0) this.makeDiv(x, y2, w, h);
          }
        }
        else this.makeDiv(x, y2, xrDef - x, h);
      }
    else {
        if (iSects & 0x00ff) {
          if (iSects & 0x02) xl = Math.max(x, aBndZ[y]);
          else xl = x;
          if (iSects & 0x01) xr = Math.min(xrDef, aBndA[y]);
          else xr = xrDef;
          y2 = cy - y - h;
          w = xr - xl;
          if (w > 0) this.makeDiv(xl, y2, w, h);
        }
        if (iSects & 0xff00) {
          if (iSects & 0x0100) xl = Math.max(x, aBndA[y]);
          else xl = x;
          if (iSects & 0x0200) xr = Math.min(xrDef, aBndZ[y]);
          else xr = xrDef;
          y2 = cy + y + (iOdds >> 16);
          w = xr - xl;
          if (w > 0) this.makeDiv(xl, y2, w, h);
        }
      }
  };

  //  ----------------------------------------------------------------------------
  jsGraphics.prototype.pixelShift = function (node, x, y) {
    if (node) {
      node.style.position = 'absolute';
      if (typeof x != 'undefined') node.style.left = x + 'px';
      if (typeof y != 'undefined') node.style.top  = y + 'px';
    }
    return node;
  };

//  ---------------------------------------------------------------------------
jsGraphics.prototype.makeLineVirt = function (aLin, x1, y1, x2, y2) {
  var dx = Math.abs(x2 - x1);
  var dy = Math.abs(y2 - y1);
  var x = x1;
  var y = y1;
  var xIncr = (x1 > x2) ? -1 : 1;
  var yIncr = (y1 > y2) ? -1 : 1;
  var p, i = 0;
  if (dx >= dy) {
      var pr = dy << 1,
        pru = pr - (dx << 1);
      p = pr - dx;
      while (dx > 0) {
          --dx;
          if (p > 0) //  Increment y
          {
            aLin[i++] = x;
            y += yIncr;
            p += pru;
          }
          else p += pr;
          x += xIncr;
        }
    }
  else {
      var pr = dx << 1,
        pru = pr - (dy << 1);
      p = pr - dy;
      while (dy > 0) {
          --dy;
          y += yIncr;
          aLin[i++] = x;
          if (p > 0) //  Increment x
          {
            x += xIncr;
            p += pru;
          }
          else p += pr;
        }
    }
  for (var len = aLin.length, i = len - i; i;)
  aLin[len - (i--)] = x;
};

//  ---------------------------------------------------------------------------
jsGraphics.prototype._CompInt = function(x, y) {
  return (x - y);
}

//  -------------------------------------------------------------------------->
jsGraphics.prototype.add = function (node) {
  return this.position.appendChild(node);
};

//  ---------------------------------------------------------------------------
jsGraphics.prototype.setSize = function (node, width, height) {
  this.setStyle (node, 'width', width);
  this.setStyle (node, 'height', height);
  return node;
};

//  ---------------------------------------------------------------------------
jsGraphics.prototype.setStyle = function (node, attribute, value) {
  node.style[attribute] = Math.max(0, value) + 'px';
  return node;
};

//  -------------------------------------------------------------------------->
HTMLDivElement.prototype.x = function() {
  return parseInt(this.style.left, 10);
};
