/**
 * A factory class to create XML implementations of SVG elements.
 * @extends  DvtImplFactory
 * @class DvtXmlImplFactory  A factory class to create XML implementation objects.
 * @constructor  Creates XML implementations of SVG elements.
 */
var DvtXmlImplFactory = function (context) {
  this.Init(context);
}

DvtObj.createSubclass(DvtXmlImplFactory, DvtImplFactory, "DvtXmlImplFactory");

DvtXmlImplFactory.prototype.Init = function (context) {
  DvtXmlImplFactory.superclass.Init.call(this, context);
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newStage = function (root, id) {
  return new DvtXmlStage(root, id);
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newContainer = function (id) {
  return new DvtXmlContainer(id, 'g');
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newDefs = function () {
  return new DvtXmlContainer(null, 'defs');
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newArc = function (cx, cy, rx, ry, sa, ae, clos, id) {
  return new DvtXmlArc(cx, cy, rx, ry, sa, ae, clos, id);
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newCircle = function (cx, cy, r, id) {
  return new DvtXmlCircle(cx, cy, r, id);
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newImage = function (imageSrc, x, y, w, h, id) {
  return new DvtXmlImage(imageSrc, x, y, w, h, id);
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newLine = function (x1, y1, x2, y2, id) {
  return new DvtXmlLine(x1, y1, x2, y1, id);
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newOval = function (cx, cy, rx, ry, id) {
  return new DvtXmlOval(cx, cy, rx, ry, id);
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newPath = function (cmds, id) {
  return new DvtXmlPath(cmds, id);
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newPolyline = function (cmds, id) {
  return new DvtXmlPolyline(cmds, id);
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newPolygon = function (arPoints, id) {
  return new DvtXmlPolygon(arPoints, id);
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newRect = function (x, y, w, h, id) {
  return new DvtXmlRect(x, y, w, h, id);
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newText = function (textStr, x, y, id) {
  return new DvtXmlText(textStr, x, y, id);
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newParser = function () {
  return new DvtXmlImplParser();
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newTextArea = function (x, y, id) {
  return new DvtXmlTextArea(x, y, id);
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newTextFormatted = function (x, y, id) {
  return null;//new DvtXmlTextFormatted(x, y, id);
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newMarker = function (type, id, etype) {
  return new DvtXmlMarker(type, id, etype);
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.getDocumentUtils = function () {
  return DvtXmlDocumentUtils;
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.getImageLoader = function () {
  return DvtXmlImageLoader;
}

/**
 * @override
 */
DvtXmlImplFactory.prototype.newJsExt = function () {
  return new DvtXmlJsExt();
}
importPackage(Packages.javax.xml.parsers);
importPackage(Packages.org.w3c.dom);
importPackage(java.io);

/**
 * Wrapper class providing XML parsing functionality.
 * @class DvtXmlImplParser
 * @extends DvtObj
 * @constructor
 */
var DvtXmlImplParser = function() {
  var dbf = DocumentBuilderFactory.newInstance();
  dbf.setIgnoringElementContentWhitespace(true);
  dbf.setIgnoringComments(true);
  this._parser = dbf.newDocumentBuilder();
}

DvtObj.createSubclass(DvtXmlImplParser, DvtObj, "DvtXmlImplParser");

/**
 * Parses the XML string and returns the root node.
 * @param {string} xml The XML string to parse.
 * @return {DvtXmlNode} The root node of the XML document.
 */
DvtXmlImplParser.prototype.parse = function(xml) {
  var xmlString = java.lang.String.valueOf(xml);
  var xmlDoc = this._parser.parse(new ByteArrayInputStream(xmlString.getBytes()));
  var root = xmlDoc.getDocumentElement()
  return new DvtXmlImplNode(root);
}
/**
 * Wrapper class providing access to XML Nodes.
 * @extends DvtXmlNode
 * @class DvtXmlImplNode
 * @constructor
 * @param {Node} node the Node object
 */
var DvtXmlImplNode = function (node) {
  this._node = node;
}

DvtObj.createSubclass(DvtXmlImplNode, DvtXmlNode, "DvtXmlImplNode");

/**
 * @override
 */
DvtXmlImplNode.prototype.getAttribute = function (attr) {
  var nodeAttr = this._node.getAttribute(attr);
  var strNodeAttr = new String(nodeAttr).toString()
  if (!nodeAttr || !strNodeAttr) {
    return null;
  }
  else {
    return strNodeAttr;
  }
}

/**
 * @override
 */
DvtXmlImplNode.prototype.getFirstChild = function () {
  return new DvtXmlImplNode(this._node.getFirstChild());
}

/**
 * @override
 */
DvtXmlImplNode.prototype.getChildNodes = function () {
  var ret = [];

  var child = this._node.getFirstChild();
  while (child != null) {
    if (child.getNodeType() == Node.ELEMENT_NODE)
      ret.push(new DvtXmlImplNode(child));

    child = child.getNextSibling();
  }
  return ret;
}

/**
 * @override
 */
DvtXmlImplNode.prototype.getName = function () {
  return new String(this._node.getNodeName()).toString();
}

/**
 * @override
 */
DvtXmlImplNode.prototype.getAttributes = function () {
  var array = [];
  var attrList = this._node.getAttributes();
  var numAttrs = attrList.length;
  for (var i = 0;i < numAttrs;i++) {
    var attr = attrList.item(i);
    array.push( {
      name : new String(attr.getNodeName()).toString(), value : new String(attr.getNodeValue()).toString()
    });
  }
  return array;
}

/**
 * @override
 */
DvtXmlImplNode.prototype.getAllChildNodes = function () {
  var ret = [];
  var children = this._node.getChildNodes();
  for (var i = 0;i < children.length;i++)
    ret.push(new DvtXmlImplNode(children.item(i)));
  return ret;
}

/**
 * @override
 */
DvtXmlImplNode.prototype.getNodeValue = function () {
  return new String(this._node.getNodeValue()).toString();
}

/**
 * @override
 */
DvtDomXmlNode.prototype.getTextContent = function () {
  return new String(this._node.getTextContent()).toString();
}

//TODO: find a better place this method
DvtXmlImplNode._removeTextNodes = function (elem) {
  var child = this._node.getFirstChild();
  while (child != null) {
    if (child.getNodeType() == Node.TEXT_NODE)
      this._node.removeChild(child);
    child = child.getNextSibling();
  }
}

/**
 * @override
 */
DvtXmlImplNode.prototype.getElementsByTagName = function (name) {
  var ret = [];
  var nodes = this._node.getElementsByTagName(name);
  if (nodes) {
    for (var i = 0;i < nodes.length;i++) {
      if (nodes.item)
        ret.push(new DvtXmlImplNode(nodes.item(i)));
    }
  }
  return ret;
}
/**
 *  Provides a gateway for access to ADF functionality for XML.
 *  @class DvtXmlJsExt
 *  @extends DvtJsExt
 *  @constructor
 */
var DvtXmlJsExt = function () {
}

DvtObj.createSubclass(DvtXmlJsExt, DvtJsExt, "DvtXmlJsExt");

/**
 *  Sets a PPR property value.
 *  @param {String}  id  An id to be substituted in the function call.
 *  @param {String)  prop a property such as {@link DvtJsExt#PPR_ATTRIB_HSS}
 *  @param {String}  value  the property value.
 */
DvtXmlJsExt.prototype.sendPPRProperty = function (id, prop, value) {}

/**
 *   @param {String} id
 */
DvtXmlJsExt.prototype.sendPPR = function (id) {}

/**
 *   @param {String} id
 */
DvtXmlJsExt.prototype.sendPPRNonBlocking = function (id) {}

/**
 *   Performs the specified Javascript.
 *   @returns {unknown} the result, if any, of the Javascript execution.
 */
DvtXmlJsExt.prototype.callJs = function (js) {}

/**
 *   Returns the current ADF log level.
 *   @returns {number} the current ADF log level (such as {DvtJsExt#LOG_WARNING}).
 */
DvtXmlJsExt.prototype.getLogLevel = function () {
  return null;
}

/**
 *   Forwards a message to the ADF logger.
 *   @param  {String} msg the message to be logged.
 *   @param  {number} level the log level of the messsage.  If omitted
 *                          a value of {DvtJsExt#LOG_INFO} is assumed.
 */
DvtXmlJsExt.prototype.log = function (msg, level) {}

/**
 *   Forwards a message string to ADF DVT.
 *   @param  {String} msg the message to be sent.
 */
DvtXmlJsExt.prototype.msg = function (msg) {}

/**
 *   Forwards a performance message.
 *   @param  {String} msg the performance message to be sent.
 *   @param  {number} type  the performance type (such as {DvtJsExt#PERF_TIMING}).
 */

DvtXmlJsExt.prototype.perf = function (s, type) {}

DvtXmlJsExt.prototype.requestRefresh = function () {}

DvtXmlJsExt.prototype.dispatchEvent = function (callback, callbackObj, component, event) {
  DvtEventDispatcher.dispatchEvent(callback, callbackObj, component, event);
}
var DvtXmlFilterContext = function () {
  this.Init();
}

DvtObj.createSubclass(DvtXmlFilterContext, DvtObj, "DvtXmlFilterContext");

DvtXmlFilterContext.prototype.Init = function () {
  this._regionPctRect = new DvtRectangle(-10, -10, 120, 120);
  this._counter = 0;
  this._resultIdsUnder = [];
  this._resultIdsOver = [];
}

DvtXmlFilterContext.prototype.getRegionPctRect = function () {
  return this._regionPctRect;
}

DvtXmlFilterContext.prototype.getResultIdsUnder = function () {
  return this._resultIdsUnder;
}

DvtXmlFilterContext.prototype.getResultIdsOver = function () {
  return this._resultIdsOver;
}

DvtXmlFilterContext.prototype.createResultId = function (id) {
  if (!id) {
    id = "filtRes";
  }
  return (id + (this._counter++));
}
/**
 *   Static filter routines.
 *   @class DvtXmlFilterUtils
 *   @constructor
 */
var DvtXmlFilterUtils = function () {
}

DvtXmlFilterUtils._counter = 0;

DvtXmlFilterUtils.createFilter = function (effects, displayable) {
  var filt = DvtXmlShapeUtils.createElement('filter', DvtXmlFilterUtils.CreateFilterId());
  var filtContext = new DvtXmlFilterContext();
  for (var i = 0;i < effects.length;i++) {
    var effect = effects[i];
    if (effect) {
      DvtXmlFilterUtils.CreateFilterPrimitives(filt, effect, displayable, filtContext);
    }
  }

  // BUG #12805402: When bounding box of svg element has zero height or width, userSpaceOnUse must be used
  // Otherwise, the element will disappear
  var userSpaceOnUse = false;
  if (displayable) {
    var boundsRect = displayable.getDimensions();
    var width = boundsRect.width;
    var height = boundsRect.height;
    if (height == 0 || width == 0) {
      var stroke = displayable.getStroke();
      var adjustWidth = 10;
      if (stroke) {
        adjustWidth = stroke.getWidth();
      }
      var x = boundsRect.x;
      var y = boundsRect.y;

      // Firefox 4 requires the line to be bend slightly when feColorMatrix is used
      if (DvtXmlDocumentUtils.isFilterStraightLineAdjustmentNeeded()) {
        if (displayable instanceof DvtXmlPolyline) {
          var points = DvtArrayUtils.copy(displayable.getPoints());
          if (width == 0) {
            points[0] = points[0] + 0.01;
          }
          if (height == 0) {
            points[1] = points[1] + 0.01;
          }

          var bentPoints = DvtXmlShapeUtils.convertPointsArray(points);
          displayable.Svg['points'] = bentPoints;
        }
      }

      if (height == 0) {
        height = 2 * adjustWidth;
        y -= adjustWidth;
      }
      if (width == 0) {
        width = 2 * adjustWidth;
        x -= adjustWidth;
      }

      filt.Svg['x'] = x;
      filt.Svg['y'] = y;
      filt.Svg['width'] = width;
      filt.Svg['height'] = height;
      filt.Svg['filterUnits'] = 'userSpaceOnUse';
      userSpaceOnUse = true;
    }
  }
  if (!userSpaceOnUse) {
    if (filtContext.getRegionPctRect().x !=  - 10) {
      filt.Svg['x'] = filtContext.getRegionPctRect().x + '%';
    }
    if (filtContext.getRegionPctRect().y !=  - 10) {
      filt.Svg['y'] = filtContext.getRegionPctRect().y + '%';
    }
    if (filtContext.getRegionPctRect().w != 120) {
      filt.Svg['width'] = filtContext.getRegionPctRect().w + '%';
    }
    if (filtContext.getRegionPctRect().h != 120) {
      filt.Svg['height'] = filtContext.getRegionPctRect().h + '%';
    }

  }

  var numResultsUnder = filtContext.getResultIdsUnder().length;
  var numResultsOver = filtContext.getResultIdsOver().length;
  var elemMN;
  var j;

  var elemM = DvtXmlShapeUtils.createElement('feMerge');
  if (numResultsUnder > 0) {
    for (j = 0;j < numResultsUnder;j++) {
      elemMN = DvtXmlShapeUtils.createElement('feMergeNode');
      elemMN.Svg['in'] = filtContext.getResultIdsUnder()[j];
      elemM.addChild(elemMN);
    }
  }
  elemMN = DvtXmlShapeUtils.createElement('feMergeNode');
  elemMN.Svg['in'] = 'SourceGraphic';
  elemM.addChild(elemMN);
  if (numResultsOver > 0) {
    for (j = 0;j < numResultsOver;j++) {
      elemMN = DvtXmlShapeUtils.createElement('feMergeNode');
      elemMN.Svg['in'] = filtContext.getResultIdsOver()[j];
      elemM.addChild(elemMN);
    }
  }
  filt.addChild(elemM);

  return filt;
}

DvtXmlFilterUtils.CreateFilterPrimitives = function (filter, effect, displayable, filtContext) {
  if (effect instanceof DvtShadow) {
    DvtXmlShadowUtils.createFilterPrimitives(filter, effect, displayable, filtContext);
  }
  //Glow and Bevel not currently supported
}

DvtXmlFilterUtils.CreateFilterId = function () {
  return ("filt" + (DvtXmlFilterUtils._counter++));
}
/**
 *   A static class for gradient property manipulation.
 *   @class DvtXMLGradientUtils
 *   @constructor
 */
var DvtXmlGradientUtils = function () {
}

/**
 *  Static method to create the XML for a SVG element and apply gradient properties to it.
 *  @param {DvtFill} grad  Either a DvtGradientFill or DvtGradientStroke derivative to apply.
 *  @param {string} id The id for the gradient element.
 */
DvtXmlGradientUtils.createElem = function (grad, id) {
  var bLinear = ((grad instanceof DvtLinearGradientFill) || (grad instanceof DvtLinearGradientStroke));
  var elemGrad = new DvtXmlContainer(id, bLinear ? 'linearGradient' : 'radialGradient');

  var i;
  var arColors = grad.getColors();
  var arAlphas = grad.getAlphas();
  var arStops = grad.getStops();
  var arBounds = grad.getBounds();
  var len = arColors.length;

  for (i = 0;i < len;i++) {
    var elem = new DvtXmlContainer(null, 'stop');
    elem.Svg['offset'] = (arStops[i] * 100) + '%';
    var color = arColors[i];
    if (color) {
      var alpha = arAlphas[i];
      elem.Svg['stop-color'] = color;
      if (alpha != null)
        elem.Svg['stop-opacity'] = alpha;
    }
    elemGrad.addChild(elem);
  }

  var bUseObjBBox = (!arBounds || ((arBounds[0] == 0) && (arBounds[1] == 0) && (arBounds[2] == 0) && (arBounds[3] == 0)));

  if (bLinear) {
    var angle = grad.getAngle();
    var x1 = '0%';
    var y1 = '0%';
    var x2 = '100%';
    var y2 = '0%';
    var setGradientVector = true;
    if (bUseObjBBox) {
      if (angle === 45) {
        y1 = '100%';
        x2 = '100%';
      }
      else if (angle === 90) {
        y1 = '100%';
        x2 = '0%';
      }
      else if (angle === 135) {
        x1 = '100%';
        x2 = '0%';
        y2 = '100%';
      }
      else if (angle === 270) {
        x2 = '0%';
        y2 = '100%';
      }
      else if (angle !== 0) {
        angle =  - angle;
        elemGrad.Svg['gradientTransform'] = 'rotate(' + angle + ' ' + '.5 .5)';
        setGradientVector = false;
      }
    }
    else {
      elemGrad.Svg['gradientUnits'] = 'userSpaceOnUse';
      x1 = '0';
      y1 = '0.5';
      x2 = '1';
      y2 = '0.5';

      var scaleX = arBounds[2];
      var scaleY = arBounds[3];
      var translateX = arBounds[0];
      var translateY = arBounds[1];

      angle =  - angle;
      var rotateTransformStr = 'rotate(' + angle + ' ' + '.5 .5)'
      var scaleTransformStr = 'scale(' + scaleX + ' ' + scaleY + ')';
      var translateTransformStr = 'translate(' + translateX + ' ' + translateY + ')';
      var boundingBoxTransformStr = scaleTransformStr + ' ' + rotateTransformStr;

      if (translateX != 0 || translateY != 0) {
        boundingBoxTransformStr = translateTransformStr + ' ' + boundingBoxTransformStr;
      }
      elemGrad.Svg['gradientTransform'] = boundingBoxTransformStr;
    }

    if (setGradientVector) {
      elemGrad.Svg['x1'] = x1;
      elemGrad.Svg['y1'] = y1;
      elemGrad.Svg['x2'] = x2;
      elemGrad.Svg['y2'] = y2;
    }
  }
  else {
    //  Radial gradient
    if (!bUseObjBBox) {
      elemGrad.Svg['gradientUnits'] = 'userSpaceOnUse';
      elemGrad.Svg['cx'] = grad.getCx();
      elemGrad.Svg['cy'] = grad.getCy();
      elemGrad.Svg['fx'] = grad.getCx();
      elemGrad.Svg['fy'] = grad.getCy();
      elemGrad.Svg['r'] = grad.getRadius();
    }
  }
  return elemGrad;
}
/**
 * A static class for creating the XML for SVG pattern fills.
 * @class DvtXmlPatternUtils
 * @constructor
 */
var DvtXmlPatternUtils = function () {
}

/** @private @final @type String  */
DvtXmlPatternUtils._SM_WIDTH = 8;
/** @private @final @type String  */
DvtXmlPatternUtils._SM_HEIGHT = 8;
/** @private @final @type String  */
DvtXmlPatternUtils._LG_WIDTH = 16;
/** @private @final @type String  */
DvtXmlPatternUtils._LG_HEIGHT = 16;

/**
 *  Static method to create the XML for a SVG pattern element.
 *  @param {DvtPatternFill} patternFill The pattern fill object.
 *  @param {string} id  The pattern identifier.
 */
DvtXmlPatternUtils.createElem = function (patternFill, id) {
  var elemPat = new DvtXmlContainer(id, "pattern");
  var pattern = patternFill.getPattern();
  var bSmall = DvtXmlPatternUtils.IsSmallPattern(pattern);
  var ww;
  var hh;
  if (bSmall) {
    ww = DvtXmlPatternUtils._SM_WIDTH;
    hh = DvtXmlPatternUtils._SM_HEIGHT;
  }
  else {
    ww = DvtXmlPatternUtils._LG_WIDTH;
    hh = DvtXmlPatternUtils._LG_HEIGHT;
  }

  elemPat.Svg["x"] = 0;
  elemPat.Svg["y"] = 0;
  elemPat.Svg["width"] = ww;
  elemPat.Svg["height"] = hh;
  elemPat.Svg["patternUnits"] = "userSpaceOnUse";
  DvtXmlPatternUtils.CreatePatternElems(patternFill, elemPat);

  return elemPat;
}

/**
 * Determine if the pattern is large or small.
 *
 * @param {string} pattern The constant representing the pattern size.
 * @protected
 */
DvtXmlPatternUtils.IsSmallPattern = function (pattern) {
  return (pattern.charAt(0) === 's');
}

/**
 * Static method to create the XML for a SVG element and apply pattern properties to it.
 * @param {DvtPatternFill} patternFill  The pattern fill object.
 * @param {object} parentElem  The parent pattern DOM element.
 * @protected
 */
DvtXmlPatternUtils.CreatePatternElems = function (patternFill, parentElem) {
  var rightX;
  var bottomY;
  var w;
  var h;
  var halfW;
  var halfH;
  var elem;

  var pattern = patternFill.getPattern();
  var sColor = patternFill.getColor();
  var color = DvtColorUtils.getRGB(sColor);
  var alpha = DvtColorUtils.getAlpha(sColor);
  var sBackgroundColor = patternFill.getBackgroundColor();
  var backgroundColor = DvtColorUtils.getRGB(sBackgroundColor);
  var backgroundAlpha = DvtColorUtils.getAlpha(sBackgroundColor);

  var bSmall = DvtXmlPatternUtils.IsSmallPattern(pattern);
  if (bSmall) {
    rightX = DvtXmlPatternUtils._SM_WIDTH;
    bottomY = DvtXmlPatternUtils._SM_HEIGHT;
    w = DvtXmlPatternUtils._SM_WIDTH;
    h = DvtXmlPatternUtils._SM_HEIGHT;
  }
  else {
    rightX = DvtXmlPatternUtils._LG_WIDTH;
    bottomY = DvtXmlPatternUtils._LG_HEIGHT;
    w = DvtXmlPatternUtils._LG_WIDTH;
    h = DvtXmlPatternUtils._LG_HEIGHT;
  }

  if (backgroundColor && (backgroundAlpha > 0)) {
    elem = new DvtXmlContainer(null, "rect");
    elem.Svg["stroke"] = backgroundColor;
    elem.Svg["stroke-opacity"] = backgroundAlpha;
    elem.Svg["stroke-width"] = 1;
    elem.Svg["fill"] = backgroundColor;
    elem.Svg["fill-opacity"] = backgroundAlpha;
    elem.Svg["x"] = 0;
    elem.Svg["y"] = 0;
    elem.Svg["width"] = rightX;
    elem.Svg["height"] = bottomY;
    parentElem.addChild(elem);
  }

  if (pattern === DvtPatternFill.SM_DIAG_UP_LT || pattern === DvtPatternFill.LG_DIAG_UP_LT) {
    halfW = w / 2;
    halfH = h / 2;

    elem = new DvtXmlContainer(null, "path");
    elem.Svg["stroke"] = color;
    elem.Svg["stroke-opacity"] = alpha;
    elem.Svg["stroke-width"] = 1;
    elem.Svg["stroke-linecap"] = "square";
    elem.Svg["d"] = "M" + halfW + ",0" + "L" + rightX + "," + halfH + "M0," + halfH + "L" + halfW + "," + bottomY;
    parentElem.addChild(elem);
  }
  else if (pattern === DvtPatternFill.SM_DIAG_UP_RT || pattern === DvtPatternFill.LG_DIAG_UP_RT) {
    halfW = w / 2;
    halfH = h / 2;

    elem = new DvtXmlContainer(null, "path");
    elem.Svg["stroke"] = color;
    elem.Svg["stroke-opacity"] = alpha;
    elem.Svg["stroke-width"] = 1;
    elem.Svg["stroke-linecap"] = "square";
    elem.Svg["d"] = "M0," + halfH + "L" + halfW + ",0" + "M" + halfW + "," + bottomY + "L" + rightX + "," + halfH;
    parentElem.addChild(elem);
  }
  else if (pattern === DvtPatternFill.SM_CROSSHATCH || pattern === DvtPatternFill.LG_CROSSHATCH) {
    elem = new DvtXmlContainer(null, "path");
    elem.Svg["stroke"] = color;
    elem.Svg["stroke-opacity"] = alpha;
    elem.Svg["stroke-width"] = 1;
    elem.Svg["d"] = "M0,0" + "L" + rightX + "," + bottomY + "M" + rightX + ",0" + "L0," + bottomY;
    parentElem.addChild(elem);
  }
  else if (pattern === DvtPatternFill.SM_CHECK || pattern === DvtPatternFill.LG_CHECK) {
    halfW = w / 2;
    halfH = h / 2;

    elem = new DvtXmlContainer(null, "path");
    elem.Svg["stroke"] = color;
    elem.Svg["stroke-opacity"] = alpha;
    elem.Svg["stroke-width"] = 1;
    elem.Svg["fill"] = color;
    elem.Svg["fill-opacity"] = alpha;
    elem.Svg["d"] = "M" + halfW + ",0" + "L" + w + ",0" + "L" + w + "," + halfH + "L" + halfW + "," + halfH + "Z" + "M0," + halfH + "L" + halfW + "," + halfH + "L" + halfW + "," + h + "L0," + h + "Z";
    parentElem.addChild(elem);
  }
  else if (pattern === DvtPatternFill.SM_TRIANGLE_CHECK || pattern === DvtPatternFill.LG_TRIANGLE_CHECK) {
    elem = new DvtXmlContainer(null, "polygon");
    elem.Svg["stroke"] = color;
    elem.Svg["stroke-opacity"] = alpha;
    elem.Svg["stroke-width"] = 1;
    elem.Svg["fill"] = color;
    elem.Svg["fill-opacity"] = alpha;
    elem.Svg["points"] = "0," + bottomY + " " + rightX + ",0 " + rightX + "," + bottomY;
    parentElem.addChild(elem);
  }
  else if (pattern === DvtPatternFill.SM_DIAMOND_CHECK || pattern === DvtPatternFill.LG_DIAMOND_CHECK) {
    halfW = w / 2;
    halfH = h / 2;

    elem = new DvtXmlContainer(null, "polygon");
    elem.Svg["stroke"] = color;
    elem.Svg["stroke-opacity"] = alpha;
    elem.Svg["stroke-width"] = 1;
    elem.Svg["fill"] = color;
    elem.Svg["fill-opacity"] = alpha;
    elem.Svg["points"] = "0," + halfH + " " + halfW + ",0 " + rightX + "," + halfW + " " + halfW + "," + bottomY;
    parentElem.addChild(elem);
  }
}
/**
 *  A static class for drop shadow property manipulation.
 *  @class DvtSvgShadowUtils
 *  @constructor
 */
var DvtXmlShadowUtils = function () {
}

/**
 * @private
 * @final
 */
DvtXmlShadowUtils.RADS_PER_DEGREE = (Math.PI / 180);

/**
 *  Static method to create the XML for a SVG filter element and apply shadow properties to it.
 *  @param {DvtShadow} shadow The shadow to create the filter for.
 *  @param {DvtDisplayable} displayable The object to apply the shadow to.
 *  @returns {Object}  An object containing the xml for a SVG filter element.
 */
DvtXmlShadowUtils.createFilter = function (shadow, displayable) {
  var filt;

  if (!shadow.isLocked()) {
    var filtContext = new DvtXmlFilterContext();
    filt = new DvtXmlContainer(shadow._Id, 'filter');
    DvtXmlShadowUtils.createFilterPrimitives(filt, shadow, displayable, filtContext);

    var elemM = new DvtXmlContainer(null, 'feMerge');
    var elemMN1 = new DvtXmlContainer(null, 'feMergeNode');
    elemMN1.Svg['in'] = filtContext.getResultIdsUnder()[0];
    var elemMN2 = new DvtXmlContainer(null, 'feMergeNode');
    elemMN2.Svg['in'] = 'SourceGraphic';

    filt.addChild(elemM);
    elemM.addChild(elemMN1);
    elemM.addChild(elemMN2);
  }

  return filt;
}

/**
 * Helper method for creating a shadow filter element.
 * @param {Object} filt
 * @param {DvtShadow} shadow
 * @param {DvtDisplayable} displayable
 * @param {DvtXmlFilterContext} filtContext
 * @protected
 */
DvtXmlShadowUtils.createFilterPrimitives = function (filt, shadow, displayable, filtContext) {
  if (shadow._bInner) {
    DvtXmlShadowUtils.CreateInnerFilterPrimitives(filt, shadow, displayable, filtContext);
  }
  else {
    DvtXmlShadowUtils.CreateOuterFilterPrimitives(filt, shadow, displayable, filtContext);
  }
}

/**
 * Helper method for creating a shadow filter element.
 * @param {Object} filt
 * @param {DvtShadow} shadow
 * @param {DvtDisplayable} displayable
 * @param {DvtXmlFilterContext} filtContext
 * @protected
 */
DvtXmlShadowUtils.CreateOuterFilterPrimitives = function (filt, shadow, displayable, filtContext) {
  var rgba = shadow._rgba;
  var red = DvtColorUtils.getRed(rgba) / 255;
  var green = DvtColorUtils.getGreen(rgba) / 255;
  var blue = DvtColorUtils.getBlue(rgba) / 255;
  var alpha = DvtColorUtils.getAlpha(rgba);
  var strength = shadow._strength;

  var origBlurX = shadow._blurX;
  var origBlurY = shadow._blurY;

  var blurX = 0;
  var blurY = 0;
  if (shadow._blurX > 0) {
    blurX = Math.max(shadow._blurX / 3, 1);
  }
  if (shadow._blurY > 0) {
    blurY = Math.max(shadow._blurY / 3, 1);
  }
  var distance = shadow._distance;
  var angleDegs = shadow._angle;
  var angleRads = angleDegs * DvtXmlShadowUtils.RADS_PER_DEGREE;
  var dx = Math.cos(angleRads) * distance;
  var dy = Math.sin(angleRads) * distance;

  var boundsRect = displayable.getDimensions(displayable.getParent());
  if (boundsRect) {
    var absDistance = Math.abs(distance);
    var padLeft = 2 * origBlurX;
    var padRight = 2 * origBlurX;
    var padTop = 2 * origBlurY;
    var padBottom = 2 * origBlurY;
    if (distance > 0) {
      padLeft -= absDistance;
      padTop -= absDistance;
      padRight += absDistance;
      padBottom += absDistance;
    }
    else if (distance < 0) {
      padLeft += absDistance;
      padTop += absDistance;
      padRight -= absDistance;
      padBottom -= absDistance;
    }
    if (padLeft < 0) {
      padLeft = 0;
    }
    if (padTop < 0) {
      padTop = 0;
    }
    if (padRight < 0) {
      padRight = 0;
    }
    if (padBottom < 0) {
      padBottom = 0;
    }
    var ratioLeft = (padLeft / boundsRect.w) * 100;
    var ratioRight = (padRight / boundsRect.w) * 100;
    var ratioTop = (padTop / boundsRect.h) * 100;
    var ratioBottom = (padBottom / boundsRect.h) * 100;
    if (filtContext.getRegionPctRect().x >  - ratioLeft) {
      filtContext.getRegionPctRect().x =  - ratioLeft;
    }
    if (filtContext.getRegionPctRect().y >  - ratioTop) {
      filtContext.getRegionPctRect().y =  - ratioTop;
    }
    if (filtContext.getRegionPctRect().w < (100 + ratioLeft + ratioRight)) {
      filtContext.getRegionPctRect().w = (100 + ratioLeft + ratioRight);
    }
    if (filtContext.getRegionPctRect().h < (100 + ratioTop + ratioBottom)) {
      filtContext.getRegionPctRect().h = (100 + ratioTop + ratioBottom);
    }
  }
  // The bounding box does not take into accoutn stroke-width. Need to adjust for DvtLine objects
  if (displayable instanceof DvtXmlPolyline) {
    var strokeWidth = displayable.getStroke().getWidth();
    // If stroke is wider than 1 pixel, adjust y coordinate and height of shadow bounding box
    if (strokeWidth > 1) {
      filtContext.getRegionPctRect().h = filtContext.getRegionPctRect().h + strokeWidth;
      filtContext.getRegionPctRect().y = filtContext.getRegionPctRect().y - strokeWidth;
    }
  }

  var elemCM = new DvtXmlContainer(null, 'feColorMatrix');
  elemCM.Svg['in'] = 'SourceGraphic';
  elemCM.Svg['type'] = 'matrix';
  elemCM.Svg['values'] = '0 0 0 ' + red + ' 0 ' + '0 0 0 ' + green + ' 0 ' + '0 0 0 ' + blue + ' 0 ' + '0 0 0 ' + alpha * strength + ' 0';

  var elemGB = new DvtXmlContainer(null, 'feGaussianBlur');
  var stdDev = blurX;
  if (blurX !== blurY) {
    stdDev += " " + blurY;
  }
  elemGB.Svg['stdDeviation'] = stdDev;
  var elemGBResult = filtContext.createResultId('blur');
  elemGB.Svg['result'] = elemGBResult;

  var elemO = new DvtXmlContainer(null, 'feOffset');
  elemO.Svg['dx'] = dx;
  elemO.Svg['dy'] = dy;
  elemO.Svg['in'] = elemGBResult;
  var elemOResult = filtContext.createResultId('offset');
  elemO.Svg['result'] = elemOResult;

  filtContext.getResultIdsUnder().push(elemOResult);

  filt.addChild(elemCM);
  filt.addChild(elemGB);
  filt.addChild(elemO);
}

/**
 * Helper method for creating a shadow filter element.
 * @param {Object} filt
 * @param {DvtShadow} shadow
 * @param {DvtDisplayable} displayable
 * @param {DvtXmlFilterContext} filtContext
 * @protected
 */
DvtXmlShadowUtils.CreateInnerFilterPrimitives = function (filt, shadow, displayable, filtContext) {
  var blurX = Math.max(shadow._blurX / 2, 1);
  var blurY = Math.max(shadow._blurY / 2, 1);

  var elemF1 = new DvtXmlContainer(null, 'feFlood');
  elemF1.Svg['in'] = 'SourceGraphic';
  elemF1.Svg['flood-opacity'] = alpha;
  elemF1.Svg['flood-color'] = rgb;
  var elemF1Result = filtContext.createResultId('flood');
  elemF1.Svg['result'] = elemF1Result;

  var elemC1 = new DvtXmlContainer(null, 'feComposite');
  elemC1.Svg['operator'] = 'out';
  elemC1.Svg['in'] = elemF1Result;
  elemC1.Svg['in2'] = 'SourceGraphic';

  var elemGB = new DvtXmlContainer(null, 'feGaussianBlur');

  var stdDev = blurX;
  if (blurX !== blurY) {
    stdDev += " " + blurY;
  }
  elemGB.Svg['stdDeviation'] = stdDev;
  var elemGBResult = filtContext.createResultId('blur');
  elemGB.Svg['result'] = elemGBResult;

  var elemCM2 = new DvtXmlContainer(null, 'feColorMatrix');
  elemCM2.Svg['in'] = elemGBResult;
  elemCM2.Svg['type'] = 'matrix';
  elemCM2.Svg['values'] = '1 0 0 0 0 ' + '0 1 0 0 0 ' + '0 0 1 0 0 ' + '0 0 0 ' + strength + ' 0';
  var elemCM2Result = filtContext.createResultId('colMat');
  elemCM2.Svg['result'] = elemCM2Result;

  var elemO = new DvtXmlContainer(null, 'feOffset');
  elemO.Svg['dx'] = dx;
  elemO.Svg['dy'] = dy;
  elemO.Svg['in'] = elemCM2Result;
  var elemOResult = filtContext.createResultId('offset');
  elemO.Svg['result'] = elemOResult;

  var elemC2 = new DvtXmlContainer(null, 'feComposite');
  elemC2.Svg['operator'] = 'in';
  elemC2.Svg['in'] = elemOResult;
  elemC2.Svg['in2'] = 'SourceGraphic';
  var elemC2Result = filtContext.createResultId('comp');
  elemC2.Svg['result'] = elemC2Result;

  filtContext.getResultIdsOver().push(elemC2Result);

  filt.addChild(elemF1);
  filt.addChild(elemC1);
  filt.addChild(elemGB);
  filt.addChild(elemCM2);
  filt.addChild(elemO);
  filt.addChild(elemC2);
}
/**
  *   A static class for DvtXmlImage fill property manipulation.
  *   @class DvtXmlImageFillUtils
  *   @constructor
  */
var DvtXmlImageFillUtils = function () {}

/**
 *  Static method to create an SVG element and apply image fill properties
 *  to it.
 *  @param {DvtImageFill} THe image to create the pattern from.
 *  @param {string} The id of the pattern def to create.
 *  @return {DvtXmlContainer} The xml representation of an image pattern. 
 */
DvtXmlImageFillUtils.createElem = function (imageFill, id) {
  var src = imageFill.getSrc();
  var bound = imageFill.getBound();
  var image = new DvtXmlImage(src, bound.x, bound.y, bound.w, bound.h, id);

  var elemPat = DvtXmlShapeUtils.createElement("pattern", id);
  elemPat.Svg['x'] = bound.x;
  elemPat.Svg['y'] = bound.y;
  elemPat.Svg['width'] = bound.w;
  elemPat.Svg['height'] = bound.h;
  elemPat.Svg["patternUnits"] = "userSpaceOnUse";
  elemPat.addChild(image);

  return elemPat;
}
/**
 *  XML implementation of base displayable object DvtDisplayable.
 *  @extends DvtObj
 *  @class DvtXmlDisplayable is the XML implementation base class for all displayable
 *  objects (derived from {@link DvtXmlDisplayable}).
 *  Must be superclassed  - do not use directly - all derivatives of DvtXmlDisplayable
 *  should be created via a specific platform factory implementation.
 *  @constructor
 *  @param {String} id    The object ID (if undefined or null, '?' is used.
 *  @param {String} type  The SVG DOM element type.
 */
var DvtXmlDisplayable = function (id, type) {
  this._Init(id, type);
}

DvtObj.createSubclass(DvtXmlDisplayable, DvtObj, "DvtXmlDisplayable");

/**
 * Array of SVG attributes that should be transferred to the outer element.
 * @private
 */
DvtXmlDisplayable._ATTRS_TRANSFERABLE_TO_OUTER = ['clip-path']

DvtXmlDisplayable.prototype._Init = function (id, name) {
  this.Svg = new Object();
  if (id) {
    this._id = id;
    this.Svg["id"] = this._id;
  }
  this._name = name;
  this._Parent = null;
  this._bVisible = true;
  this._filter = null;
  this._pixelHinting = false;
  this._alpha = 1;
  this._bMouseEnabled = true;
  this._bOuterElem = false;
}

/**
 *   @returns {String}  the id of this shape.
 */
DvtXmlDisplayable.prototype.getId = function () {
  return this._id;
}
/**
 *   Sets the id of this shape.
 *   @param {String} id  The id for the shape.
 */
DvtXmlDisplayable.prototype.setId = function (id) {
  this._id = id;
  this.Svg["id"] = this._id;
}

/**
 * @returns {string} The SVG DOM element type.
 */
DvtXmlDisplayable.prototype.getNodeName = function () {
  return this._name;
}

/**
 *  @returns {Object}  the controlling (js) object.
 */
DvtXmlDisplayable.prototype.getObj = function () {
  return this._obj;
}

/**
 * Sets the controlling objects for this implementation object.
 * @param {Object}  The controlling (js) object.
 */
DvtXmlDisplayable.prototype.setObj = function (obj) {
  this._obj = obj;
}

/**
 *  @returns {Object} the (js) parent of this shape.
 */
DvtXmlDisplayable.prototype.getParent = function () {
  return this._obj.getParent();
}

/**
 *  Sets the (js) parent of this shape.
 *  @param {Object} parent
 */
DvtXmlDisplayable.prototype.setParent = function (parent) {
  this._obj.setParent(parent);
}

/**
 *  @returns {boolean} the current pixel hinting state.
 */
DvtXmlDisplayable.prototype.getPixelHinting = function () {
  return this._pixelHinting;
}

/**
 * Enables/disables pixel hinting.
 * @param {boolean}  bHint  true if pixel hinting should be interpreted/applied by the
 * implementation platform.
 */
DvtXmlDisplayable.prototype.setPixelHinting = function (bHint) {
  this._pixelHinting = bHint;
  if (bHint)
    this.Svg["shape-rendering"] = "crispEdges";
  else delete this.Svg["shape-rendering"];
}

/**
 *  Gets the visibility of this object.
 *  @returns {boolean}  True if the object is visible, else false.
 */
DvtXmlDisplayable.prototype.getVisible = function () {
  return this._bVisible;
}

/**
 *  Enables/disables the visibility of this object.
 *  @param {boolean}  bVis  True if the object is to be visible, else false if
 *  it is to be hidden.
 */
DvtXmlDisplayable.prototype.setVisible = function (bVis) {
  if (this._bVisible !== bVis) {
    this._bVisible = bVis;
    this.Svg["visibility"] = bVis ? "visible" : "hidden";
  }

}

/**
 *  Sets a clipping region for this object.
 *  @param {DvtClipPath}  cp  the DvtClipPath object specifying the clipping region.
 */
DvtXmlDisplayable.prototype.setClipPath = function (cp) {
  // Create an outer group if there is a matrix defined, since SVG applies transforms before clip paths.
  if (this._matrix)
    this.setOuterGroupElem();

  var id = cp.getId();
  if (id) {
    // essential to have an id to reference
    var context = this.getObj().getContext();

    if (DvtXmlShapeUtils.addClipPath(cp, context)) {
      // add to global defs
      this.Svg['clip-path'] = 'url(#' + id + ')';
    }
  }
}

DvtXmlDisplayable.prototype.addClipPath = function (cp, context) {
  return DvtXmlShapeUtils.addClipPath(cp, context);
}

/**
 * @return {DvtRectangle} The bounding box of the object given the target coordinate space.
 */
DvtXmlDisplayable.prototype.getDimensions = function (targetCoordinateSpace) {
  return DvtObjDimUtils.getDimensions(this, targetCoordinateSpace);
}

/**
 * @return {DvtRectangle} The bounding box of the object.
 */
DvtXmlDisplayable.prototype.getDimensions = function () {
  return DvtObjDimUtils.getDimensions(this, null);
}

/**
 * Returns true if any of the specified attribute names are present on the element.
 * @param {object} elem  The XML SVG element.
 * @param {array} attrNames The array of attribute names to look for.
 * @protected
 */
DvtXmlDisplayable.HasAttributes = function (elem, attrNames) {
  if (attrNames) {
    var numAttrs = attrNames.length;
    for (var i = 0;i < numAttrs;i++) {
      if (elem.Svg[attrNames[i]] != null)
        return true;
    }
  }
  return false;
}

/**
 * Transfer relevant attributes from the original XML SVG element to the new XML SVG element.
 * @param {object} fromElem  The XML SVG element.
 * @param {object} toElem  The new XML SVG element.
 * @param {array} attrNames The array of attribute names to transfer.
 * @protected
 */
DvtXmlDisplayable.TransferAttributes = function (fromElem, toElem, attrNames) {
  if (attrNames) {
    var attrName;
    var attrValue;
    var numAttrs = attrNames.length;
    for (var i = 0;i < numAttrs;i++) {
      attrName = attrNames[i];
      attrValue = fromElem.Svg[attrName];
      if (attrValue != null) {
        delete fromElem.Svg[attrName];
        toElem.Svg[attrName] = attrValue;
      }
    }
  }
}

/**
 * Sets a flag that this object should have an outer group element. Used for working around issues with filters and clip paths.
 */
DvtXmlDisplayable.prototype.setOuterGroupElem = function () {
  this._bOuterElem = true;
}

/**
 * @return {boolean} True if this object has an outer group element.
 */
DvtXmlDisplayable.prototype.hasOuterGroupElem = function () {
  return this._bOuterElem;
}

/**
 * No-op method for adding an event listener.
 * @param {String} type the event type
 * @param {String} useCapture whether the listener operates in the capture phase
 */
DvtXmlDisplayable.prototype.addListener = function (type, useCapture) {
}

/**
 * No-op method for removing an event listener.
 * @param {string} type the event type
 * @param {function} listener the function to call
 * @param {String} useCapture whether the listener operates in the capture phase
 */
DvtXmlDisplayable.prototype.removeListener = function (type, useCapture) {
}

/**
 *  Returns the alpha channel value.
 *  @type number
 *  @returns A value between 0 (invisible) and 1 (opaque).
 */
DvtXmlDisplayable.prototype.getAlpha = function () {
  return this._alpha;
}

/**
 *  Sets the alpha.
 *  @param {number} alpha  A value between 0 (invisible) and 1 (opaque).
 */
DvtXmlDisplayable.prototype.setAlpha = function (alpha) {
  //when animating alpha, small values are turned into strings like
  //"3.145e-8", which SVG incorrectly clamps to 1, so just cut off
  //small values here and make them 0
  if (alpha < 0.00001)
    alpha = 0;

  if (alpha !== this._alpha) {
    this._alpha = alpha;
    this.Svg["opacity"] = this._alpha;
  }
}

/**
 *   Set the matrix object to use to transform this container.
 *   @param {DvtMatrix} mat  The matrix object to apply.
 */
DvtXmlDisplayable.prototype.setMatrix = function (mat) {
  if (mat !== this._matrix) {
    if (!this._bOuterElem && DvtXmlDisplayable.HasAttributes(this, DvtXmlDisplayable._ATTRS_TRANSFERABLE_TO_OUTER))
      this.setOuterGroupElem();
    this._matrix = mat;
    if (mat) {
      var sMat = 'matrix(' + mat.getA() + ',' + mat.getC() + ',' + mat.getB() + ',' + mat.getD() + ',' + mat.getTx() + ',' + mat.getTy() + ')';
      this.Svg['transform'] = sMat;
    }
    else {
      var transformAttr = this.Svg['transform'];
      if (transformAttr) {
        delete this.Svg["transform"];
      }
    }
  }
}

/**
 * Method for applying draw effects like DvtGlow, DvtBevel, DvtShadow, etc.
 * @param {array} effects An array of filter effects to apply.
 */
DvtXmlDisplayable.prototype.applyDrawEffects = function (effects) {
  // Create an outer group if there is a matrix defined, since SVG applies transforms before filters.
  if(!this.hasOuterGroupElem() && this._matrix)
    this.setOuterGroupElem();

  // Remove current filter
  if (this._filter)
  {
    this.getObj().getContext().removeDefs(this._filter);
    this._filter = null;
    delete this.Svg['filter'];
  }
  
  // Add new filter if necessary
  if (effects && effects.length > 0)
  {
    this._filter = DvtXmlFilterUtils.createFilter(effects, this);
    this.getObj().getContext().appendDefs(this._filter);
    this.Svg['filter'] = 'url(#' + this._filter.getId() + ')';
  }
}
/**
 * Convert a point from stage coords to local coords.
 * @param {DvtPoint}  point  point in stage coords
 * @type DvtPoint
 */
DvtXmlDisplayable.prototype.stageToLocal = function (point) {
  var displayable = this.getObj();
  var pathToStage = displayable.getPathToStage();
  var mat;
  var retPoint = point;
  for (var i = pathToStage.length - 1;i >= 0;i--) {
    displayable = pathToStage[i];
    mat = displayable.getMatrix().clone();
    mat.invert();
    retPoint = mat.transformPoint(retPoint);
  }
  return retPoint;
}

/**
 * Convert a point from local coords to stage coords.
 * @param {DvtPoint}  point  point in local coords
 * @type DvtPoint
 */
DvtXmlDisplayable.prototype.localToStage = function (point) {
  var displayable = this.getObj();
  var pathToStage = displayable.getPathToStage();
  var mat;
  var retPoint = point;
  for (var i = 0;i < pathToStage.length;i++) {
    displayable = pathToStage[i];
    mat = displayable.getMatrix();
    retPoint = mat.transformPoint(retPoint);
  }
  return retPoint;
}

/*
 * Creates a copy of the svg content, wrapped by a new container
 */
DvtXmlDisplayable.prototype.createCopy = function () {
  //TODO PNG
}

/**
 * No-op method for dispatching an event after user interaction.
 * @param {string} eventType The event type to dispatch
 */
DvtXmlDisplayable.prototype.dispatchEvent = function (eventType) {
}

/**
 * Sets whether mouse events are enabled on this object.
 * @param {boolean} whether mouse events are enabled
 */
DvtXmlDisplayable.prototype.setMouseEnabled = function (bEnabled) {
  this._bMouseEnabled = bEnabled;
}

/**
 * Gets whether mouse events are enabled on this object.
 * @return {boolean}
 */
DvtXmlDisplayable.prototype.isMouseEnabled = function () {
  return this._bMouseEnabled;
}

/**
 * @returns {DvtCssStyle} The DvtCSSStyle of this object.
 */
DvtXmlDisplayable.prototype.getCSSStyle = function () {
  return this._cssStyle;
}

/**
 * Sets the DvtCSSStyle of this object.
 * @param {DvtCssStyle} style The DvtCSSStyle of this object.
 */
DvtXmlDisplayable.prototype.setCSSStyle = function (style) {
  this._cssStyle = style;
}

/**
 * Sets the cursor on this object.
 * @param {String} cursor type
 */
DvtXmlDisplayable.prototype.setCursor = function (cursorType) {
  //No-op
}

/**
 * Gets the cursor used on this object.
 * @type {String}
 */
DvtXmlDisplayable.prototype.getCursor = function () {
  return null;
}

/**
 * @return {string} The svg element tag for this object.
 * @protected
 */
DvtXmlDisplayable.prototype.GetSvgTag = function () {
  var svg = "<" + this._name;
  for (var element in this.Svg)
    svg += " " + element + '="' + this.Svg[element] + '"';
  return svg + " \/>";
}

/**
 * @return {string} The start svg element tag for this object.
 * @protected
 */
DvtXmlDisplayable.prototype.GetSvgStartTag = function () {
  var svg = "<" + this._name;
  for (var element in this.Svg)
    svg += " " + element + '="' + this.Svg[element] + '"';
  return svg + ">";
}

/**
 * @return {string} The end svg element tag for this object.
 * @protected
 */
DvtXmlDisplayable.prototype.GetSvgEndTag = function () {
  return "<\/" + this._name + ">";
}

/**
 * Returns the string xml representation of a SVG element.
 * @return {string}
 */
DvtXmlDisplayable.prototype.toSvg = function () {
  // subclasses may implement
}

/**
 * Sets the logical object for this DvtDisplayable.
 * @object {Object}
 */
DvtXmlDisplayable.prototype.setLogicalObj = function (obj) {
  this._logicalObject = obj;
}

/**
 * @return {string} The string representing the value of the svg <desc> element associated with this object or null if none.
 */
DvtXmlDisplayable.prototype.GetDesc = function () {
  if (this._logicalObject) {
    var desc;
    if (this._logicalObject.getDatatip)
      desc = this._logicalObject.getDatatip();
    if (!desc && this._logicalObject.getTooltip)
      desc = this._logicalObject.getTooltip();
    if (desc)
      return desc.replace("<br/>", ";");
  }
  return null;
}

/**
 * XML implementation of DvtContainer.
 * @extends DvtXmlDisplayable
 * @class DvtXmlContainer
 * @constructor
 * @param {String} id   An optional id for this object.
 * @param {String} type  The SVG element type.
 */
var DvtXmlContainer = function (id, type) {
  this._Init(id, type);
}

DvtObj.createSubclass(DvtXmlContainer, DvtXmlDisplayable, "DvtXmlContainer");

/**
 * Object initializer.
 * @param {String} id   An optional id for this object.
 * @param {String} type  The SVG element type.
 */
DvtXmlContainer.prototype._Init = function (id, type) {
  DvtXmlContainer.superclass._Init.call(this, id, type);
  this._bShapeContainer = (this instanceof DvtXmlShape);
  this._children = [];
}

/**
 * Array of SVG attributes that should be transferred from the shape
 * tag to the group when this shape becomes a group (i.e. when children
 * are added to it).
 * @protected
 */
DvtXmlContainer.AttributesTransferableToGroup = ['transform', 'vector-effect', 'opacity', 'style', 'visibility', 'pointer-events', 'clip-path'];

/**
 * @return {Array} The children for this container.
 */
DvtXmlContainer.prototype.getChildren = function () {
  return this._children;
}

/**
 * @return {number} The number of children for this container.
 */
DvtXmlContainer.prototype.getNumChildren = function () {
  return this._children.length;
}

/**
 * Adds the specifed object as a child of this container. The object is added to the end of the child list.
 * @param {DvtXmlDisplayable} obj The object to be added.
 */
DvtXmlContainer.prototype.addChild = function (obj) {
  this._children.push(obj);
}

/**
 *   Adds the specified object as a child of this container at the specified index. Returns
 *   immediately if the index position doesn't already exist in the child list.  If a currently
 *   occupied index is specified, the current child at that position and all subsequent children
 *   are moved one position higher in the list.
 *   @param {DvtXmlDisplayable} obj The object to be added.
 *   @param {number} index The index at which to add this object.
 */
DvtXmlContainer.prototype.addChildAt = function (obj, index) {
  this._children.splice(index, 0, obj);
}

/**
 * Retrieves a child at a given index
 * @param {number} index The index of the container child to retrieve.
 * @return {DvtXmlContainer} The child at the speicied index or null;
 */
DvtXmlContainer.prototype.getChildAt = function (index) {
  return this._children[index];
}

/**
 *   Removes the specified child object from this container.
 *   @param {DvtXmlDisplayable} obj The object to be removed.
 */
DvtXmlContainer.prototype.removeChild = function (obj) {
  var index = this._children.indexOf(obj);
  this._children.splice(index, 1);
}

/**
 * Removes all the children for this container.
 */
DvtXmlContainer.prototype.removeChildren = function () {
  this._children = [];
}

/**
 * Returns an array of SVG attributes that should be transferred from the shape
 * tag to the group when this shape becomes a group (when children are added to it).
 * @return {array}
 */
DvtXmlContainer.prototype.GetAttributesTransferableToGroup = function () {
  return DvtXmlContainer.AttributesTransferableToGroup;
}

DvtXmlContainer.prototype._createSvgGroupTag = function () {
  var outer = new DvtXmlContainer(this._id ? this._id + "_g" : null, "g");
  // Create another outer group if there is a matrix defined, since SVG applies transforms before filters.
  if (this.Svg.transform && this.Svg.filter) {
    DvtXmlDisplayable.TransferAttributes(this, outer, DvtXmlDisplayable._ATTRS_TRANSFERABLE_TO_OUTER);
  } else {
    DvtXmlDisplayable.TransferAttributes(this, outer, this.GetAttributesTransferableToGroup());
  }
  
  if (this.getOuterGroupElemMatrix) {
    var outerMatrix = this.getOuterGroupElemMatrix();
    if (outerMatrix) {
      outer.setMatrix(outerMatrix);
    }
  }
  return outer;
}

DvtXmlContainer.prototype._createSvgDescTag = function (descText) {
  //Assumes node with desc tag has no children
  var svg = '';
  var desc = new DvtXmlDisplayable(null, "desc");
  svg += desc.GetSvgStartTag();
  svg += descText;
  svg += desc.GetSvgEndTag();
  return svg;
}

DvtXmlContainer.prototype._createSvgChildrenTags = function () {
  //A child can be either a string or a DvtXmlContainer
  var svg = '';

  for (var i = 0;i < this._children.length;i++) {
    if (typeof (this._children[i]) != 'string')
      svg += this._children[i].toSvg();
    else 
      svg += this._children[i];
  }

  return svg;
}

/**
 * @override
 */
DvtXmlContainer.prototype.toSvg = function () {
  var svg = "";
  var name = this.getNodeName();
  var bCreateGroupTag = (this._bShapeContainer && this._children.length > 0 && name != 'text') || this.hasOuterGroupElem();

  //Don't add image tag if no width is specified. Indicates error loading image.
  //Assumes image tag has no children
  if (name == 'image' && !this.Svg.width) {
    return svg;
  }

  //Create outer group tag if needed
  var outerTag;
  if (bCreateGroupTag)
    outerTag = this._createSvgGroupTag();

  if (outerTag)
    svg += outerTag.GetSvgStartTag();

  svg += this.GetSvgStartTag();

  var descText = this.GetDesc();
  if (descText && this.isMouseEnabled()) {
    //Create self and desc tag
    svg += this._createSvgDescTag(descText);
  }

  if (this._bShapeContainer && name != 'text')//The children of shape containers are really children of the outer container
    svg += this.GetSvgEndTag();

  if (this._children.length > 0) {
    //Create self and children tags
    svg += this._createSvgChildrenTags();
  }

  if (!this._bShapeContainer || name == 'text')
    svg += this.GetSvgEndTag();

  if (outerTag)
    svg += outerTag.GetSvgEndTag();

  return svg;
}

/**
  *  XML implementation of DvtStage, representing the highest level container
  *  under a SVG DOM element.
  *  @extends DvtXmlContainer
  *  @class DvtXmlStage
  */
var DvtXmlStage = function (root, id) {
  this._Init(root, id);
}

DvtObj.createSubclass(DvtXmlStage, DvtXmlContainer, "DvtXmlStage");

DvtXmlStage.prototype._Init = function (root, id) {
  this._svgId = id;
  DvtXmlStage.superclass._Init.call(this, id, 'g');
}
/**
 * A base class for shapes implemented via XML.  Implements common DvtShape
 * drawing support for properties such as such as stroke and fill types and colors.
 * DvtXmlShape is intended to be subclassed.
 * @extends DvtXmlContainer
 * @class DvtXmlShape
 * @constructor
 * @param {string} id   An id for the object.
 * @param {string} type The SVG element type - e.g. 'circle', 'rect', etc.
 */
var DvtXmlShape = function (id, type) {
  this._Init(id, type);
}

DvtObj.createSubclass(DvtXmlShape, DvtXmlContainer, "DvtXmlShape");

DvtXmlShape.prototype._Init = function (id, type) {
  DvtXmlShape.superclass._Init.call(this, id, type);

  this._stroke = null;
  this._fill = null;
  this._bHollow = false;
  this.setFill(null);
}

 /**
 *  Sets the fill properties on this shape from the supplied fill object (a
 *  derivative of {@link DvtFill}).
 *  @param {DvtFill}  obj  A fill object. If null is specified, a transparent
 *  fill results.
 */
DvtXmlShape.prototype.setFill = function (fill) {
  this._fill = fill;

  if (!fill) {
    this.Svg["fill"] = 'none';
    delete this.Svg["fill-opacity"];
  }
  else if (fill instanceof DvtGradientFill) {
    this._setSpecialFill(fill, DvtXmlGradientUtils);
  }
  else if (fill instanceof DvtImageFill) {
    this._setSpecialFill(fill, DvtXmlImageFillUtils);
  }
  else if (fill instanceof DvtPatternFill) {
    this._setSpecialFill(fill, DvtXmlPatternUtils);
  }
  else {
    var color = fill.getColor();
    var alpha = fill.getAlpha();
    if (color != null && color.indexOf("rgba") !==  - 1) {
      color = DvtColorUtils.getRGB(color);
      // Use alpa in rgba value as a multiplier to the alpha set on the object as this is what svg does.
      if (alpha != null)
       alpha = DvtColorUtils.getAlpha(color) * alpha;
      else 
        alpha = DvtColorUtils.getAlpha(color);
    }
    this.Svg["fill"] = color;
    this.Svg["fill-opacity"] = alpha;
  }

}

/**
 * @private
 */
DvtXmlShape.prototype._setSpecialFill = function (fill, func) {
  var id = fill.getId();
  if (!fill.isLocked() && !id) {
    if (fill instanceof DvtPatternFill || fill instanceof DvtImageFill)
      id = DvtXmlShapeUtils.getUniqueId("Pat");
    else
      id = DvtXmlShapeUtils.getUniqueId('Gr');
    fill.setId(id);
  }
  if (!fill._defPresent) {
    var elem = fill._defElem;
    if (!elem)
      elem = func.createElem(fill, id);

    fill._defElem = elem;
    this.getObj().getContext().appendDefs(elem);
    fill._defPresent = true;
  }

  this.Svg['fill'] ='url(#' + id + ')';
  this.Svg['fill-opacity'] = '1';
}

/**
 *  Returns the fill object (derivative of {@link DvtFill}) applied to this shape.
 * @type DvtFill
 */
DvtXmlShape.prototype.getFill = function (fill) {
  return this._fill;
}

/**
 *  Sets the stroke properties on this shape from the supplied stroke object.
 *  If the stroke object is null, any existing stroke is removed.
 *  @param {DvtStroke}  obj  A stroke object.
 */
DvtXmlShape.prototype.setStroke = function (stroke) {
  this._stroke = stroke;
  
  if (!stroke) {
    this.Svg["stroke"] = 'none';
    delete this.Svg["stroke-opacity"];
    delete this.Svg["stroke-width"];
    delete this.Svg["stroke-dasharray"];
    delete this.Svg["stroke-linejoin"];
    delete this.Svg["stroke-linecap"];
    delete this.Svg["stroke-miterlimit"];
    return;
  }

  var strokeColor = this._stroke.getColor();
  var strokeAlpha = this._stroke.getAlpha();
  var strokeWidth = this._stroke.getWidth();
  var strokeType = this._stroke.getType();
  var lineJoin = this._stroke.getLineJoin();
  var lineEnd = this._stroke.getLineEnd();
  var miterLimit = this._stroke.getMiterLimit();
  
  if (strokeColor != null && strokeColor.indexOf("rgba") !==  - 1) {
    strokeColor = DvtColorUtils.getRGB(strokeColor);
    // Use alpa in rgba value as a multiplier to the alpha set on the object as this is what svg does.
    if (strokeAlpha != null)
     strokeAlpha = DvtColorUtils.getAlpha(strokeColor) * alpha;
    else 
      strokeAlpha = DvtColorUtils.getAlpha(strokeColor);
  }

  if (strokeColor != null)
    this.Svg["stroke"] = strokeColor;
  if (strokeAlpha != null)
    this.Svg["stroke-opacity"] = strokeAlpha;
  if (strokeWidth != null)
    this.Svg["stroke-width"] = strokeWidth;
  if (strokeType !== DvtStroke.SOLID)
    this.Svg["stroke-dasharray"] = this._stroke.getDash();
  if (lineJoin != null)
    this.Svg["stroke-linejoin"] = lineJoin;
  if (lineEnd != null)
    this.Svg["stroke-linecap"] = lineEnd;
  if (miterLimit != null)
    this.Svg["stroke-miterlimit"] = miterLimit;
}

/**
 * Returns the stroke object (derivative of {@link DvtStroke}) applied to this shape.
 * @type DvtStroke
 */
DvtXmlShape.prototype.getStroke = function () {
  return this._stroke;
}

/**  
 * Returns whether a shape is hollow.
 *  @returns {boolean} True if the shape is hollow
 */
DvtXmlShape.prototype.isHollow = function () {
  return this._bHollow;
}

/**  
 *  Changes the shape to an outline shape format.  Used for legends
 *  markers that represent a hidden state for the associated series risers.
 *  @param {String} fc Border color for hollow shape in format of #aarrggbb
 *  @param {number} strokeWidth Stroke width used for shapes that were transofrmed (optional)
 */
DvtXmlShape.prototype.setHollow = function (fc, strokeWidth) {
  // TODO PNG support
  if (!this._bHollow)
    this._bHollow = true;
  else 
    this._bHollow = false;
}

/**
 *  Creates a circular displayable shape - XML implementation of DvtCircle.
 *  @extends DvtSvgShape
 *  @class DvtXmlCircle is an XML implementation of DvtCircle and displays
 *  a circle.  Note:  this class should not be used directly, use DvtCircle.
 *   @constructor
 *   @param {number} cx  The center x position.
 *   @param {number} cy  The center y position.
 *   @param {number} r   The radius of the circle.
 *   @param {String} id  Optional ID for the shape (see {@link  DvtDisplayable#setId}).
 */
var DvtXmlCircle = function (cx, cy, r, id) {
  this._Init(cx, cy, r, id);
}

DvtObj.createSubclass(DvtXmlCircle, DvtXmlShape, "DvtXmlCircle");

/** @private */
DvtXmlCircle.prototype._Init = function (cx, cy, r, id, type) {
  DvtXmlCircle.superclass._Init.call(this, id, (type || 'circle'));

  this.setCx(cx);
  this.setCy(cy);
  this.setRadius(r);
}

/**
 *  @return {number} The center x position.
 */
DvtXmlCircle.prototype.getCx = function () {
  return this._cx;
}

/**
 *  Sets the x coordinate of the center.
 *  @param {number} cx  The center x position.
 */
DvtXmlCircle.prototype.setCx = function (cx) {
  if (cx !== this._cx) {
    this._cx = cx;
    this.Svg["cx"] = cx;
  }
}

/**
 *  Returns the y coordinate of the center.
 *  @type number
 */
DvtXmlCircle.prototype.getCy = function () {
  return this._cy;
}

/**
 *  Sets the y coordinate of the center.
 *  @param {number} cy  The center y position.
 *
 */
DvtXmlCircle.prototype.setCy = function (cy) {
  if (cy !== this._cy) {
    this._cy = cy;
    this.Svg["cy"] = cy;
  }
}

/**
 *  Gets the radius  of the circle.
 *  @type {Number}  The radius of the circle.
 */
DvtXmlCircle.prototype.getRadius = function () {
  return this._r;
}

/**
 *  Sets the radius  of the circle.
 *  @param {number} r   The radius of the circle.
 */
DvtXmlCircle.prototype.setRadius = function (r) {
  if (r !== this._r) {
    this._r = r;
    this.Svg["r"] = r;
  }
}
/**
  *   An XML implementation of DvtMarker Do not create directly, use DvtMarker.
  *   @extends DvtXmlShape
  *   @constructor
  *   @param {number} type  The marker type (such as {@link DvtMarker#CIRCLE}).
  *   @type  DvtXmlMarker
  */
var DvtXmlMarker = function (type, id, etype) {
  this._Init(type, id, etype);
}

DvtObj.createSubclass(DvtXmlMarker, DvtXmlShape, "DvtXmlMarker");

// The reference coords and sizes that the shapes will be initialized to.
DvtXmlMarker._REFERENCE_X = 0;
DvtXmlMarker._REFERENCE_Y = 0;
DvtXmlMarker._REFERENCE_W = 10;
DvtXmlMarker._REFERENCE_H = 10;

DvtXmlMarker.MARKER_CIRCLE_ELEM_NAME = "circle";
DvtXmlMarker.MARKER_ELLIPSE_ELEM_NAME = "ellipse";
DvtXmlMarker.MARKER_LINE_ELEM_NAME = "line";
DvtXmlMarker.MARKER_PATH_ELEM_NAME = "path";
DvtXmlMarker.MARKER_PATHOLYGON_ELEM_NAME = "polygon";
DvtXmlMarker.MARKER_PATHOLYLINE_ELEM_NAME = "polyline";
DvtXmlMarker.MARKER_RECT_ELEM_NAME = "rect";

/**
 *   @private
 */
DvtXmlMarker.prototype._Init = function (type, id, etype) {
  var elemType;
  if (etype) {
    elemType = etype;
  }
  else {
    elemType = (type === DvtMarker.CIRCLE ? 'circle' : (type === DvtMarker.SQUARE ? 'rect' : (type === DvtMarker.TRIANGLE_UP ? 'polygon' : (type === DvtMarker.TRIANGLE_DOWN ? 'polygon' : (type === DvtMarker.DIAMOND ? 'polygon' : (type === DvtMarker.PLUS ? 'polygon' : (type === DvtMarker.HUMAN ? 'path' : (type === DvtMarker.CUSTOM ? 'use' : 'rect'))))))));
  }
  DvtXmlMarker.superclass._Init.call(this, id, elemType);

  // Store the type
  this._markerType = type;

  //default scale of the marker used to force it to the reference size
  this._defaultScale = 1;

  // Bounding box
  this._boundsX = 0;
  this._boundsY = 0;
  this._boundsW = 0;
  this._boundsH = 0;
}

/**
 * Sets the position and size of the marker.
 * @param {number} x The top left x-coordinate of the marker's bounding rectangle.
 * @param {number} y The top left y-coordinate of the marker's bounding rectangle.
 * @param {number} w The width of the marker's bounding rectangle.
 * @param {number} h The height of the marker's bounding rectangle.
 * @param {DvtMarkerDef} markerDef
 */
DvtXmlMarker.prototype.setBounds = function (x, y, w, h, markerDef) {
  // Initialize the shape to the reference coords
  if (!this._shapeInitialized)
    this._initShape(this._markerType, markerDef, DvtXmlMarker._REFERENCE_X, DvtXmlMarker._REFERENCE_Y, DvtXmlMarker._REFERENCE_W, DvtXmlMarker._REFERENCE_H);

  // Transform the shape to the right size and position
  var dx = x - DvtXmlMarker._REFERENCE_X;
  var dy = y - DvtXmlMarker._REFERENCE_Y;

  var sx = w / DvtXmlMarker._REFERENCE_W;
  var sy = h / DvtXmlMarker._REFERENCE_H;

  // preserve aspect ratio
  var scale = Math.max(sx, sy);

  // Use a matrix to set the actual coords
  var mat = new DvtMatrix(this.getObj().getContext());
  mat.scale(scale, scale);
  mat.translate(dx, dy);
  // Make sure the child group elem is created, since this transform 
  // will be applied on top of the reference transform.
  if (!this._isMultiPaths())
    this.setOuterGroupElem();

  this.getObj().setMatrix(mat);

  this._boundsX = x;
  this._boundsY = y;
  this._boundsW = w;
  this._boundsH = h;
}

/**
 * Initializes the shape to the specified coordinates.
 * @param {number} type  The marker type (such as {@link DvtMarker#CIRCLE}).
 * @param {DvtMarkerDef} markerDef
 * @param {number} x The top left x-coordinate of the marker's bounding rectangle.
 * @param {number} y The top left y-coordinate of the marker's bounding rectangle.
 * @param {number} w The width of the marker's bounding rectangle.
 * @param {number} h The height of the marker's bounding rectangle.
 * @private
 */
DvtXmlMarker.prototype._initShape = function (type, markerDef, x, y, w, h) {
  // Only need to do this once
  this._shapeInitialized = true;

  var multiPathRoot;
  if (type === DvtMarker.CUSTOM || type === DvtMarker.HUMAN) {
    if (type === DvtMarker.CUSTOM) {
      multiPathRoot = this._setCustomMarker(markerDef, x, y, w, h);
    }
    else if (type === DvtMarker.HUMAN)
      this._setCmds(DvtMarkerDef.HUMAN_CMDS);

    // Calculate the scale factor to get to the right size
    var dim = DvtDisplayableUtils._getDimForced(this.getObj().getContext(), markerDef);
    var maxDim = Math.max(dim.w, dim.h);
    var scale = (dim.h === maxDim) ? (h / maxDim) : (w / maxDim);
    this._defaultScale = scale;

    // Calculate the transform to get to the right position
    var dx = x + ( -dim.x * scale) + (w - (dim.w * scale)) / 2;
    var dy = y + ( -dim.y * scale) + (h - (dim.h * scale)) / 2;
    var mat = new DvtMatrix(this.getObj().getContext());
    mat.scale(scale, scale);
    mat.translate(dx, dy);

    var obj = this.getObj();
    if (multiPathRoot) {
      obj = multiPathRoot;
    }
    obj.setMatrix(mat);

  }
  else if (type === DvtMarker.SQUARE) {
    this._setX(x);
    this._setY(y);
    this._setWidth(w);
    this._setHeight(h);
  }
  else if (type === DvtMarker.CIRCLE) {
    this._setCx(x + w / 2);
    this._setCy(y + h / 2);
    this._setRadius(w / 2);
  }
  else {
    var ar = [];
    var halfWidth = w / 2;

    if (type === DvtMarker.TRIANGLE_UP) {
      ar.push(x);
      ar.push(y + w);
      ar.push(x + w);
      ar.push(y + w);
      ar.push(x + halfWidth);
      ar.push(y);
      this._setPolygon(ar);
    }
    else if (type === DvtMarker.TRIANGLE_DOWN) {
      ar.push(x);
      ar.push(y);
      ar.push(x + w);
      ar.push(y);
      ar.push(x + halfWidth);
      ar.push(y + w);
      this._setPolygon(ar);
    }
    else if (type === DvtMarker.DIAMOND) {
      ar.push(x + halfWidth);
      ar.push(y);
      ar.push(x + w);
      ar.push(y + halfWidth);
      ar.push(x + halfWidth);
      ar.push(y + w);
      ar.push(x);
      ar.push(y + halfWidth);
      this._setPolygon(ar);
    }
    else if (type === DvtMarker.PLUS) {
      var nThird = w / 3;
      var nTwoThird = 2 * nThird;

      ar.push(x + nThird);
      ar.push(y);
      ar.push(x + nTwoThird);
      ar.push(y);
      ar.push(x + nTwoThird);
      ar.push(y + nThird);
      ar.push(x + w);
      ar.push(y + nThird);
      ar.push(x + w);
      ar.push(y + nTwoThird);
      ar.push(x + nTwoThird);
      ar.push(y + nTwoThird);
      ar.push(x + nTwoThird);
      ar.push(y + w);
      ar.push(x + nThird);
      ar.push(y + w);
      ar.push(x + nThird);
      ar.push(y + nTwoThird);
      ar.push(x);
      ar.push(y + nTwoThird);
      ar.push(x);
      ar.push(y + nThird);
      ar.push(x + nThird);
      ar.push(y + nThird);
      ar.push(x + nThird);
      ar.push(y);
      this._setPolygon(ar);
    }
  }
}

/**
 *  Returns the default scale of the marker used to force it to the
 *  reference size.
 *  @type number
 */
DvtXmlMarker.prototype.getDefaultScale = function () {
  return this._defaultScale;
}

/**
 *  Returns the type of the marker (such as {@link DvtMarker#CIRCLE}).
 *  @type number
 */
DvtXmlMarker.prototype.getType = function () {
  return this._markerType;
}

/**
 * @private
 */
DvtXmlMarker.prototype._setCx = function (cx) {
  this.Svg['cx'] = cx;
}

/**
 * @private
 */
DvtXmlMarker.prototype._setCy = function (cy) {
  this.Svg['cy'] = cy;
}

/**
 * @private
 */
DvtXmlMarker.prototype._setX = function (x) {
  this.Svg['x'] = x;
}

/**
 * @private
 */
DvtXmlMarker.prototype._setY = function (y) {
  this.Svg['y'] = y;
}

/**
 * @private
 */
DvtXmlMarker.prototype._setWidth = function (w) {
  this.Svg['width'] = w;
}

/**
 * @private
 */
DvtXmlMarker.prototype._setHeight = function (h) {
  this.Svg['height'] = h;
}

/**
 * @private
 */
DvtXmlMarker.prototype._setRadius = function (r) {
  this.Svg['r'] = r;
}

/**
 *   @private
 */
DvtXmlMarker.prototype._setPolygon = function (ar) {
  var sPoints = DvtXmlShapeUtils.convertPointsArray(ar);
  this.Svg['points'] = sPoints;
}

/**
 *   @private
 */
DvtXmlMarker.prototype._setCmds = function (cmds) {
  if (cmds !== this._cmds) {
    this._cmds = cmds;
    this.Svg['d'] = cmds;
  }
}

/**
 * @override
 */
DvtXmlMarker.prototype.GetAttributesTransferableToGroup = function () {
  // Don't transfer the 'transform' attr, since it affects the clip path for custom markers.
  var attrNames = DvtXmlContainer.AttributesTransferableToGroup.slice(0);
  var transformIndex = attrNames.indexOf('transform');
  attrNames.splice(transformIndex, 1);
  return attrNames;
}

/**
 * @override
 */
DvtXmlMarker.prototype.setMatrix = function (mat) {
  DvtXmlMarker.superclass.setMatrix.call(this, mat);
}

/**
 * @override
 */
DvtXmlMarker.prototype.setAlpha = function (alpha) {
  DvtXmlMarker.superclass.setAlpha.call(this, alpha);
}

/**
 * @override
 */
DvtXmlMarker.prototype.setFill = function (obj) {
  DvtXmlMarker.superclass.setFill.call(this, obj);
}

/**
 * @override
 */
DvtXmlMarker.prototype.setStroke = function (obj) {
  DvtXmlMarker.superclass.setStroke.call(this, obj);
}

/**
 * Sets whether mouse events are enabled on this object.
 * @param {boolean} whether mouse events are enabled
 */
DvtXmlMarker.prototype.setMouseEnabled = function (bEnabled) {
  DvtXmlMarker.superclass.setMouseEnabled.call(this, bEnabled);
}

/**  
 *  Changes the shape to an outline shape format.  Used for legend
 *  markers that represent a hidden state for the associated series risers.
 *  @param {String} color Border color for hollow shape in format of #aarrggbb
 *  @param {number} strokeWidth Stroke width used for shapes that were transofrmed (optional)
 *  @override
 */
DvtXmlMarker.prototype.setHollow = function (color, strokeWidth) {
  DvtXmlMarker.superclass.setHollow.call(this, color, strokeWidth);
}

/**
 * @private
 */
DvtXmlMarker.prototype._setCustomMarker = function (markerDef, x, y, w, h) {
  if (this._isMultiPaths()) {
    var root = this._cloneMultiPaths(markerDef);
    this.getObj().addChild(root);
    // return container of multi paths
    return root;
  }
  else {
    this._setSingleShape(markerDef, x, y, w, h);
    return null;
  }
}

/**
 * @private
 */
DvtXmlMarker.prototype._setSingleShape = function (markerDef, x, y, w, h) {
  var defImpl = markerDef.getImpl();
  var type = defImpl.getNodeName();

  if (type == DvtXmlMarker.MARKER_PATH_ELEM_NAME) {
    this._setCmds(defImpl._sCmds);
  }
  else if (type == DvtXmlMarker.MARKER_CIRCLE_ELEM_NAME || type == DvtXmlMarker.MARKER_ELLIPSE_ELEM_NAME) {
    this._setCx(markerDef.getCx());
    this._setCy(markerDef.getCy());
    this._setRadius(markerDef.getRadius());
  }

  else if (type == DvtXmlMarker.MARKER_LINE_ELEM_NAME) {
    this._setX1(defImpl.getX1());
    this._setX2(defImpl.getX2());
    this._setY1(defImpl.getY1());
    this._setY2(defImpl.getY2());
  }
  else if (type == DvtXmlMarker.MARKER_PATHOLYGON_ELEM_NAME) {
    this._setPoints(defImpl._sPoints);
  }
  else if (type == DvtXmlMarker.MARKER_PATHOLYLINE_ELEM_NAME) {
    this._setPoints(defImpl._sPoints);
  }
  else if (type == DvtXmlMarker.MARKER_RECT_TYPE_ELEM_NAME) {
    this._setX(markerDef.getX());
    this._setY(markerDef.getY());
    this._setWidth(markerDef.getWidth());
    this._setHeight(markerDef.getHeight());
  }

  var fill = defImpl.getFill();
  if (fill) {
    this.setFill(fill);
  }
  var alpha = defImpl.getAlpha();
  if (alpha) {
    this.setAlpha(alpha);
  }
  var stroke = defImpl.getStroke();
  if (stroke) {
    this.setStroke(stroke);
  }
}

/**
 *   @private
 */
DvtXmlMarker.prototype._setPoints = function (points) {
  if (points !== this._points) {
    this._points = points;
    this.Svg['points'] = points;
  }
}

/**
 * @private
 */
DvtXmlMarker.prototype._setX1 = function (x1) {
  this.Svg['x1'] = x1;
}

/**
 * @private
 */
DvtXmlMarker.prototype._setY1 = function (y1) {
  this.Svg['y1'] = y1;
}

/**
 * @private
 */
DvtXmlMarker.prototype._setX2 = function (x2) {
  this.Svg['x2'] = x2;
}

/**
 * @private
 */
DvtXmlMarker.prototype._setY2 = function (y2) {
  this.Svg['y2'] = y2;
}

/**
 * @private
 */
DvtXmlMarker.prototype._cloneMultiPaths = function (markerDef) {
  var context = this.getObj().getContext();
  var root = new DvtContainer(context, markerDef.getId() + "_x");

  var childCnt = markerDef.getNumChildren();
  var childDef;
  var child;
  for (var i = 0;i < childCnt;i++) {
    childDef = markerDef.getChildAt(i);
    child = new DvtPath(context, childDef.getCmds(), childDef.getId());

    if (childDef.getFill()) {
      child.setFill(childDef.getFill());
    }
    if (childDef.getAlpha()) {
      child.setAlpha(childDef.getAlpha());
    }
    if (childDef.getStroke()) {
      child.setStroke(childDef.getStroke());
    }
    root.addChild(child);
  }

  return root;
}

/**
 * @private
 */
DvtXmlMarker.prototype._isMultiPaths = function () {
  return this.getNodeName() == "g";
}

/**
 * @return {DvtRectangle} The bounding box for this object.
 */
DvtXmlMarker.prototype.getBounds = function () {
  return new DvtRectangle(this._boundsX, this._boundsY, this._boundsW, this._boundsH);
}

/**
 * Sets a transform matrix on a group element.
 * @param {DvtMatrix} mat The matrix representing the transform to be set.
 */
DvtXmlMarker.prototype.setOuterGroupElemMatrix = function (mat) {
  this._outerGroupMatrix = mat;
}

/**
 * @return {DvtMatrix} The transform matrix for this marker outer group element.
 */
DvtXmlMarker.prototype.getOuterGroupElemMatrix = function () {
  return this._outerGroupMatrix;
}

/**
 * @override
 */
DvtXmlMarker.prototype.setMatrix = function (mat) {
  if (!this._isMultiPaths() && this.hasOuterGroupElem()) { 
    this.setOuterGroupElemMatrix(mat);
  } else {
    DvtXmlMarker.superclass.setMatrix.call(this, mat);
  }
}
/**
  *   Creates a shape using SVG path commands implemented for SVG.
  *   @extends DvtSvgShape
  *   @class DvtSvgPath  Creates a shape using SVG path commands implemented for
  *   SVG.  Do not create directly, use {@link DvtPath}.
  *   @constructor  
  *   @param {Object} cmds  Optional string of SVG path command (see comment for
  *                         {@link DvtSvgPath#setCmds}),
  *                         or an array containing consecutive command and coordinate
  *                          entries (see comment for {@link DvtSvgPath#setCommands}).
  *   @param {String} id  Optional ID for the shape (see {@link  DvtDisplayable#setId}).
  */
var DvtXmlPath = function (cmds, id) {
  this._Init(cmds, id);
};

DvtObj.createSubclass(DvtXmlPath, DvtXmlShape, "DvtXmlPath");

/** @private */
DvtXmlPath.prototype._Init = function (cmds, id) {
  DvtXmlPath.superclass._Init.call(this, id, 'path');

  if (DvtArrayUtils.isArray(cmds)) {
    this.setCommands(cmds);
  }
  else {
    this.setCmds(cmds);
  }
};

/**
 *  Gets the path from a string of SVG commands in SVG "d" attribute format.
 *  @param {String} cmds A string containing the SVG commands sequences.
 */
DvtXmlPath.prototype.getCmds = function () {
  return this._sCmds;
};
/**
 *  Sets the path from a string of SVG commands in SVG "d" attribute format.
 *  @param {String} cmds A string containing the SVG commands sequences.
 */
DvtXmlPath.prototype.setCmds = function (cmds) {
  this._sCmds = cmds;
  if (cmds)
    this.Svg["d"] = cmds;
};

/**
 *  Gets the platform independent array of SVG path command sequences supplied
 *  by the last setCommands().
 *  @type Array
 */
DvtXmlPath.prototype.getCommands = function () {
  return this._aCmds;
};
/**
 *  Sets the path from a platform independent array of SVG path command sequences.
 *  @param {Array} ar  An array of SVG path command sequences.
 */
DvtXmlPath.prototype.setCommands = function (ar) {
  var sCmds = ar ? DvtPathUtils.getPathString(ar) : null;
  this._sCmds = sCmds;
  this._aCmds = ar;

  if (sCmds)
    this.Svg["d"] = sCmds;
}
/**
  *   XML implementation for DvtPolyline which creates a series of joined
  *   lines whose points are specified by an array of x,y pairs).
  *   @extends DvtXmlShape
  *   @class DvtXmlPolyline
  *   @constructor  
  *   @param {Array} arPoints  An array of point coordinates.
  *   @param {String} id  Optional ID for the shape (see {@link  DvtDisplayable#setId}).
  */
var DvtXmlPolyline = function (arPoints, id) {
  this._Init(arPoints, id);
}

DvtObj.createSubclass(DvtXmlPolyline, DvtXmlShape, "DvtXmlPolyline");

DvtXmlPolyline.prototype._Init = function (arPoints, id) {
  DvtXmlPolyline.superclass._Init.call(this, id, 'polyline');

  this.Svg['fill'] = 'none';
  this.setPoints(arPoints);
}

/**
 *   @return {Array} An array of x, y pairs of coordinates representing the polyline.
 */
DvtXmlPolyline.prototype.getPoints = function () {
  return this._arPoints;
}

/**
 *   Sets the polyline points from an array of x,y coordinate pairs.
 *   @param {Array} arPoints  An array of x, y pairs of coordinates.
 */
DvtXmlPolyline.prototype.setPoints = function (arPoints) {
  this._arPoints = arPoints;
  this._sPoints = DvtXmlShapeUtils.convertPointsArray(arPoints);
  this.Svg['points'] = this._sPoints;
}
/**
  *   XML implementation for DvtRect.
  *   @extends DvtSvgShape
  *   @class DvtSvgRect
  *   @constructor  
  *   May be specified as individual values or using a DvtRectangle object.
  */
var DvtXmlRect = function (x, y, w, h, id) {
  this._Init(x, y, w, h, id);
}

DvtObj.createSubclass(DvtXmlRect, DvtXmlShape, "DvtXmlRect");

DvtXmlRect.prototype._Init = function (x, y, w, h, id) {
  DvtXmlRect.superclass._Init.call(this, id, 'rect');

  this.setX(x);
  this.setY(y);
  this.setWidth(w);
  this.setHeight(h);
}

/**
 * @returns {number} The upper left x coordinate for this DvtRect.
 */
DvtXmlRect.prototype.getX = function () {
  return this._x;
}

/**
 * Sets the upper left x coordinate for this DvtRect.
 * @param {number} x
 */
DvtXmlRect.prototype.setX = function (x) {
  this._x = x;
  this.Svg["x"] = this._x;
}

/**
 * @returns {number} The upper left xy coordinate for this DvtRect.
 */
DvtXmlRect.prototype.getY = function () {
  return this._y;
}

/**
 * Sets the upper left y coordinate for this DvtRect.
 * @param {number} y
 */
DvtXmlRect.prototype.setY = function (y) {
  this._y = y;
  this.Svg["y"] = this._y;
}

/**
 * @return {number} The width of this DvtRect.
 */
DvtXmlRect.prototype.getWidth = function () {
  return this._w;
}

/**
 * Sets the width of this DvtRect.
 * @param {number} w
 */
DvtXmlRect.prototype.setWidth = function (w) {
  this._w = w;
  this.Svg["width"] = this._w;
}

/**
 * @returns {number} The height of this DvtRect.
 */
DvtXmlRect.prototype.getHeight = function () {
  return this._h;
}

/**
 * Sets the height of this DvtRect.
 * @param {number} h
 */
DvtXmlRect.prototype.setHeight = function (h) {
  this._h = h;
  this.Svg["height"] = this._h;
}

/**
 * @returns {number} The rotation x coordinate of this object.
 */
DvtXmlRect.prototype.getRx = function () {
  return this._rx;
}

/**
 * Sets the rotation x coordinate of this object.
 * @param {number} xy
 */
DvtXmlRect.prototype.setRx = function (rx) {
  this._rx = rx;
  this.Svg["rx"] = this._rx;
}

/**
 * @returns {number} The rotation y coordinate of this object.
 */
DvtXmlRect.prototype.getRy = function () {
  return this._ry;
}

/**
 * Sets the rotation y coordinate of this object.
 * @param {number} ry
 */
DvtXmlRect.prototype.setRy = function (ry) {
  this._ry = ry;
  this.Svg["ry"] = this._ry;
}

/**
 * Sets the DvtCSSStyle of this object.
 * @param {DvtCSSStyle} style The DvtCSSStyle of this object.
 */
DvtXmlRect.prototype.setCSSStyle = function (style) {
  this._style = style;
  if (this._style != null) {
    var val = this._style["background-color"];
    if (val) {
      if (val.indexOf("rgba") !==  - 1) {
        this.Svg["fill"] = DvtColorUtils.getRGB(val);
        this.Svg["alpha"] = DvtColorUtils.getAlpha(val);
      }
    }
    val = style["border-color"];
    if (val)
      this.Svg["stroke"] = val;
    val = style["border-width"];
    if (val)
      this.Svg["stroke-width"] = val;
  }
}
importPackage(Packages.java.awt);
importPackage(Packages.java.util);
importPackage(Packages.java.awt.font);
importPackage(Packages.java.awt.image);
importPackage(Packages.java.lang.number);
importPackage(Packages.java.lang.math);

/**
 * Creates an instance of DvtXmlText.
 * @class DvtXmlText
 * @extends DvtXmlShape
 * @constructor
 * @param textStr {string} the text string
 * @param x {number} x the x position
 * @param y {number} y the y position
 * @param {String} id  Optional ID for the shape (see {@link  DvtDisplayable#setId}).
 */
var DvtXmlText = function (textStr, x, y, id) {
  this._Init(textStr, x, y, id);
}

DvtObj.createSubclass(DvtXmlText, DvtXmlShape, "DvtXmlText");

DvtXmlText.prototype._Init = function (textStr, x, y, id) {
  DvtXmlText.superclass._Init.call(this, id, 'text');

  this._map = new Hashtable();

  this.setX(x);
  this.setY(y);
  this.setTextString(textStr);
  this.Svg["font-family"] = "tahoma, sans-serif";
  this._map.put(TextAttribute.FAMILY, "tahoma, sans-serif");
  this.Svg["fill"] = "rgb(0,0,0)"; 
  
//  if (DvtStyleUtils.isLocaleR2L() && (DvtAgent.getAgent().getPlatform() != DvtAgent.IE_PLATFORM))
//    this.Svg["unicode-bidi"] = "embed";
}

/**
 * Returns the text string for this text object.
 * @return {string} the text string
 */
DvtXmlText.prototype.getTextString = function () {
  return this._textStr;
}

/**
 * Sets the text string for this text object.
 * @param {string} textStr the text string
 */
DvtXmlText.prototype.setTextString = function (textStr) {
  this._textStr = textStr;
  this.removeChildren(); // Text shouldn't have any children. Just a child representing the text value of the object.
  this.addChild(textStr);
}

/**
 * Sets the text angle. See also {@link DvtXmlText#setRotatePoint}.
 * @param {number} a the angle in degrees. Positive angle rotate counter-clockwise.
 */
DvtXmlText.prototype.setAngle = function (a) {
  this._angle = (a % 360);
  if (this._angle > 0) {
    this._angle = 360 - this._angle;
    if (this._cx && this._cy)
      this.Svg["transform"] = "rotate(" + this._angle + " " + this._cx + "," + this._cy + ")";
  }
  this._map.put(TextAttribute.TRANSFORM, AffineTransform.getRotateInstance(Nath.toRadians(this._angle), this._cx, this._cy));
}

/**
 * Sets the rotation point for angle text (see {@link DvtXmlText#setAngle}).
 * @param {number} cx the rotation point x-coordinate.
 * @param {number} cy the rotation point y-coordinate.
 */
DvtXmlText.prototype.setRotatePoint = function (cx, cy) {
  this._cx = cx;
  this._cy = cy;
  if (this._angle > 0) {
    this.Svg["transform"] = "rotate(" + this._angle + " " + this._cx + "," + this._cy + ")";
    this._map.put(TextAttribute.TRANSFORM, AffineTransform.getRotateInstance(Nath.toRadians(this._angle), this._cx, this._cy));
  }
}

/**
 * Gets the x position for this text object.
 * @returns {number}  the x position
 */
DvtXmlText.prototype.getX = function () {
  return this._x;
}

/**
 * Sets the x position for this text object.
 * @param {number} x the x position
 */
DvtXmlText.prototype.setX = function (x) {
  this._x = x;
  this.Svg["x"] = this._x;
}

/**
 * Gets the y position for this text object.
 * @returns {number}  the y position
 */
DvtXmlText.prototype.getY = function () {
  return this._y;
}

/**
 * Sets the y position for this text object.
 * @param {number} y the y position
 */
DvtXmlText.prototype.setY = function (y) {
  this._y = y;
  this.Svg["y"] = this._y;
}

/**
 * Sets the font size.
 * @param {number} fontSize the font size
 */
DvtXmlText.prototype.setFontSize = function (fontSize) {
  this.Svg["font-size"] = fontSize;
  this._map.put(TextAttribute.SIZE, fontSize);
}

/**
 * Aligns text to horizontal start
 */
DvtXmlText.prototype.alignStart = function () {
  this.Svg["text-anchor"] = "start";
}

/**
 * Aligns text to horizontal middle
 */
DvtXmlText.prototype.alignMiddle = function () {
  this.Svg["text-anchor"] = "middle";
}

/**
 * Aligns text to horizontal end
 */
DvtXmlText.prototype.alignEnd = function () {
  this.Svg["text-anchor"] = "end";
}

/**
 * Aligns text to vertical top
 */
DvtXmlText.prototype.alignTop = function () {
  // Current Batik version does not support dominant-baseline. Approximation used instead.
  //  this.Svg["dominant-baseline"] = "text-before-edge";
  this.Svg["baseline-shift"] = "-100%";
}

/**
 * Aligns text to vertical center
 */
DvtXmlText.prototype.alignCenter = function () {
  // Current Batik version does not support dominant-baseline. Approximation used instead.
  //  this.Svg["dominant-baseline"] = "middle";
  this.Svg["baseline-shift"] = "-25%";
}

/**
 * Aligns text to vertical bottom
 */
DvtXmlText.prototype.alignBottom = function () {
  // Current Batik version does not support dominant-baseline. Approximation used instead.
  //  this.Svg["dominant-baseline"] = "text-after-edge";
  this.Svg["baseline-shift"] = "-15%";
}

/**
 * Aligns text to vertical default
 */
DvtXmlText.prototype.alignBaseline = function () {
  delete this.Svg["dominant-baseline"];
}

/**
 * Sets the text string for this text object.
 * @param {string} text the text string
 */
DvtXmlText.prototype.setText = function (text) {
  this.setTextString(text);
}

/**
 * @return the text string for this text object.
 */
DvtXmlText.prototype.getText = function () {
  return this._textStr;
}

/**
 * Sets the DvtCSSStyle of this object.
 * @param {DvtCSSStyle} style The DvtCSSStyle of this object.
 */
DvtXmlText.prototype.setCSSStyle = function (style) {
  DvtXmlText.superclass.setCSSStyle.call(this, style);
  if (style) {
    var val = style.color;
    if (val) {
      if (val.indexOf("rgba") !==  - 1) {
        this.Svg["fill"] = DvtColorUtils.getRGB(val);
        this.Svg["alpha"] = DvtColorUtils.getAlpha(val);
      }
    }

    val = style["font-family"];
    if (val) {
      this.Svg["font-family"] = val;
      this._map.put(TextAttribute.FAMILY, val);
    }

    val = style["font-size"];
    if (val) {
      this.Svg["font-size"] = val;
      this._map.put(TextAttribute.SIZE, parseFloat(val));
    }

    val = style["font-style"];
    if (val) {
      this.Svg["font-style"] = val;
      if (val == "italic" || val == "oblique")
        this._map.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
    }

    val = style["font-weight"];
    if (val) {
      this.Svg["font-weight"] = val;
      this._map.put(TextAttribute.WEIGHT, parseFloat(val));
    }

    val = style["text-decoration"];
    if (val) {
      this.Svg["text-decoration"] = val;
      if (val == "underline")
        this._map.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
    }
  }
}

DvtXmlText.prototype._createTSpan = function(text) {
  var tspan  = DvtXmlShapeUtils.createElement('tspan', null);
  this.addChild(tspan);

  var baseline = this.Svg['dominant-baseline'];
  if (baseline)
      tspan.Svg["dominant-baseline"] = baseline;
  var anchor = this.Svg['text-anchor'];
  if (anchor)
      tspan.Svg["text-anchor"] = anchor;
  
  // add text node
  tspan.addChild(text);
  return tspan;
}

/**
 * @override
 */
DvtXmlText.prototype.getDimensions = function () {
  var font = new Font(this._map);
  var bi = new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);
  var g = bi.createGraphics();
  var metrics = g.getFontMetrics(font);
  var rect = metrics.getStringBounds(this._textStr, g);
  return new DvtRectangle(this._x, this._y, rect.getWidth(), rect.getHeight());
}
/**
 *   XML implementation for DvtImage.
 *   @constructor
 *   Maybe specified as individual values or using a DvtImage object.
 *   e.g. Image = new DvtImage(context,'pic'png', 10, 10, 50, 100);  or
 *   Image = new DvtImage(context, myImage);   where myImage = new DvtImage(context,'pic.png', 10, 10, 50, 100);
 */
var DvtXmlImage = function (src, x, y, w, h, id) {
  this._Init(src, x, y, w, h, id);
}

DvtObj.createSubclass(DvtXmlImage, DvtXmlShape, "DvtXmlImage");

/**
 * @private
 */
DvtXmlImage.prototype._Init = function (src, x, y, w, h, id) {
  DvtXmlImage.superclass._Init.call(this, id, 'image');
  this.setImage(src, x, y, w, h);
}

/**
 *  @return {number} The height of the rectangle
 */
DvtXmlImage.prototype.getHeight = function () {
  return this._h;
}

/**
 *  Sets the height of the image.
 *  @param {number} h  The height of the image.
 */
DvtXmlImage.prototype.setHeight = function (h) {
  if (h !== this._h) {
    this._h = h;
    this.Svg['height'] = this._h;
  }
}

/**
 *  @return {DvtPoint} The x, y coordinates of the upper left corner of the image.
 */
DvtXmlImage.prototype.getPos = function () {
  return new DvtPoint(this._x, this._y);
}

/**
 *  Sets the x and y coordinates of the upper left corner of the image.
 *  @param {number} x  The x coordinate.
 *  @param {number} y  The y coordinate.
 */
DvtXmlImage.prototype.setPos = function (x, y) {
  this.setX(x);
  this.setY(y);
}

/**
 *  @return {number} The x coordinate of the upper left corner of the image.
 */
DvtXmlImage.prototype.getX = function () {
  return this._x;
}

/**
 *  Sets the x coordinate of the upper left corner of the image.
 *  @param {number} x  The x coordinate.
 */
DvtXmlImage.prototype.setX = function (x) {
  if (x !== this._x) {
    this._x = x;
    this.Svg['x'] = this._x;
  }
}

/**
 *  @return {number} The y coordinate of the upper left corner of the image.
 */
DvtXmlImage.prototype.getY = function () {
  return this._y;
}

/**
 *  Sets the y coordinate of the upper left corner of the image.
 *  @param {number} y  The y coordinate.
 */
DvtXmlImage.prototype.setY = function (y) {
  if (y !== this._y) {
    this._y = y;
    this.Svg['y'] = this._y;
  }
}

/**
 *  @return {number} The width of the image.
 */
DvtXmlImage.prototype.getWidth = function () {
  return this._w;
}

/**
 *  Sets the width of the image.
 *  @param {number} w  The width of the image.
 */
DvtXmlImage.prototype.setWidth = function (w) {
  if (w !== this._w) {
    this._w = w;
    this.Svg['width'] = this._w;
  }
}

/**
 *  Sets the src of the image.
 *  @param {number} src  The src of the image.
 */
DvtXmlImage.prototype.setSrc = function (src) {
  if (src != this._src) {
    this._src = src;
    var imageInfo = DvtXmlImageLoader.getImageInfo(src);
    if (imageInfo)
      this.Svg['xlink:href'] = imageInfo.uri;
  }
}

/**
 *   Sets the position and size and src of the image
 *   Maybe specified as individual values or using a DvtImage object.
 *   e.g. Image = factory.newImage('pic'png', 10, 10, 50, 100);  or
 *   Image = factory.newImage(myImage);   where myImage = new DvtImage('pic.png', 10, 10, 50, 100);
 */
DvtXmlImage.prototype.setImage = function (src, x, y, w, h) {
  if (src instanceof DvtImage) {
    this.setSrc(src.src);
    this.setPos(src.x, src.y);
    this.setWidth(src.w);
    this.setHeight(src.h);
  }
  else {
    this.setSrc(src);
    this.setPos(x, y);
    this.setWidth(w);
    this.setHeight(h);
  }
  
  this.Svg['preserveAspectRatio'] = 'none';
}
/**
 *  Creates an arc (a portion of an ellipse or circle) implemented by SVG.
 *  @extends DvtXmlShape
 *  @class  DvtXmlArc  Creates an arc (a portion of an ellipse or circle)
 *  implemented by SVG.  Do not create directly, use DvtArc.
 *  @constructor
 *  @param {number} cx  The center x position.
 *  @param {number} cy  The center y position.
 *  @param {number} rx  The horizontal radius of the ellipse.
 *  @param {number} ry  The vertical radius of the ellipse. (use the same value as
 *                      the horizontal radius if a circular arc.)
 *  @param {number} sa  The starting angle in degrees (following the normal anti-clockwise is positive convention).
 *  @param {number} ae  The angle extent in degrees (following the normal anti-clockwise is positive convention).
 *  @param {String} clos  An optional closure type for the arc. Closure types are {@link DvtArc#OPEN} (the default),
 *                        {@link DvtArc#CHORD} and {@link DvtArc#PIE}.
 *   @param {String} id  Optional ID for the shape (see {@link  DvtDisplayable#setId}).
 */
var DvtXmlArc = function (cx, cy, rx, ry, sa, ae, clos, id) {
  this._Init(cx, cy, rx, ry, sa, ae, clos, id);
}

DvtObj.createSubclass(DvtXmlArc, DvtXmlShape, "DvtXmlArc");

/** 
 * @private
 */
DvtXmlArc.prototype._addClosure = function (p) {
  if (this._ct === DvtArc.CHORD) {
    p += ' z';
  }
  else if (this._ct === DvtArc.PIE) {
    p += ' L ' + this._cx + ',' + this._cy + ' z';
  }
  else if (this._ct === DvtArc.OPEN) {
    this.setFill(null);
  }

  return p;
}

/**
 *   @private
 */
DvtXmlArc.prototype._createArc = function () {
  if (this._bInInit) {
    // don't need to do this until end of Init()
    return;
  }

  var sa = (this._sa * DvtMath.RADS_PER_DEGREE);
  var ae = (this._ae * DvtMath.RADS_PER_DEGREE);

  var x1 = this._cx + (this._rx * Math.cos(sa));// get arc
  var y1 = this._cy - (this._ry * Math.sin(sa));// end points
  var x2 = this._cx + (this._rx * Math.cos(sa + ae));
  var y2 = this._cy - (this._ry * Math.sin(sa + ae));

  var nLargeArc = (Math.abs(this._ae) > 180) ? '1' : '0';
  var nSweepFlag = (this._ae > 0) ? '0' : '1';// 0 == svg +ve angle
  var path = "M " + x1 + " " + y1 + " A " + this._rx + "," + this._ry + " " + "0" + " " + nLargeArc + "," + nSweepFlag + " " + x2 + "," + y2;
  path = this._addClosure(path);

  this.Svg['d'] = path;
  if (this._stroke !== null) {
    this.setStroke(this._stroke);
  }
}

/**
 *  Returns the angle subtended by the arc.
 *  @returns {number}  The angle subtended by the arc (following the normal anti-clockwise
 *  is positive convention).
 */
DvtXmlArc.prototype.getAngleExtent = function () {
  return this._ae;
}

/**
 *  Returns the angle subtended by the arc.
 *  @returns {number}  The angle subtended by the arc.
 *  is positive convention).
 */
DvtXmlArc.prototype.setAngleExtent = function (ae) {
  ae = (ae || 0);
  if (this._ae !== ae) {
    if (ae === 360) {
      // bug 12723079
      ae = 359.99;// cannnot use any precision higher than this!
    }

    this._ae = ae;
    this._createArc();
  }
}

/**
 *  Returns the start angle for an arc.
 *  @return {number}  The starting angle (following the normal anti-clockwise
 *  is positive convention).
 */
DvtXmlArc.prototype.getAngleStart = function () {
  return this._sa;
}

/**
 *  Sets the start angle of the arc.
 *  @param {number}  The starting angle (following the normal anti-clockwise
 *  is positive convention).
 */
DvtXmlArc.prototype.setAngleStart = function (sa) {
  sa = (sa || 0);
  if (this._sa !== sa) {
    this._sa = sa;
    this._createArc();
  }
}

/**
 *    Returns the closure type of the arc.
 *    @type String
 *    @return {string} The closure type, such as {@link DvtArc#OPEN}
 */
DvtXmlArc.prototype.getClosure = function () {
  return this._ct;
}

/**
 *  Sets the closure type of the arc.
 *  @param {String} ct   The closure type,  such as {@link DvtArc#OPEN}
 */
DvtXmlArc.prototype.setClosure = function (ct) {
  if (ct !== this._ct) {
    this._ct = ct;
    this._createArc();
  }

}

/** 
 * @private 
 */
DvtXmlArc.prototype._Init = function (cx, cy, rx, ry, sa, ae, clos, id) {
  DvtXmlArc.superclass._Init.call(this, id, 'path');

  this._sa = 0;
  this._ae = 0;

  ry = (ry || rx);

  this._bInInit = true;// performance - avoid multiple createArc()'s
  this.setCx(cx);
  this.setCy(cy);
  this.setRx(rx);
  this.setRy(ry);
  this.setAngleStart(sa);
  this.setAngleExtent(ae);
  this.setClosure(clos || DvtArc.OPEN);
  this._bInInit = false;// finally allow createArc to work.
  this._createArc();

}

/**
 *  Defines the position and extent of the arc.
 *  @param {number} sa  The starting angle in degrees (following the normal
 *  anti-clockwise is positive convention).
 *  @param {number} ae  The angle extent in degrees (following the normal
 *  anti-clockwise is positive convention).
 */
DvtXmlArc.prototype.setArc = function (sa, ae) {
  this.setAngleStart(sa);
  this.setAngleExtentStart(ae);
}

/**
 *  @return {number} The x coordinate of the center.
 */
DvtXmlArc.prototype.getCx = function () {
  return this._cx;
}

/**
 *  Sets the x coordinate of the center.
 *  @param {number} cx  The center x position.
 */
DvtXmlArc.prototype.setCx = function (cx) {
  if (cx !== this._cx) {
    this._cx = cx;
    this.Svg['cx'] = cx;
  }
}

/**
 *  Returns the y coordinate of the center.
 *  @type number
 */
DvtXmlArc.prototype.getCy = function () {
  return this._cy;
}

/**
 *  Sets the y coordinate of the center.
 *  @param {number} cy  The center y position.
 *
 */
DvtXmlArc.prototype.setCy = function (cy) {
  if (cy !== this._cy) {
    this._cy = cy;
    this.Svg['cy'] = cy;
  }
}

/**
 *  @return {number} The horizontal radius of the ellipse.
 */
DvtXmlArc.prototype.getRx = function () {
  return this._rx;
}

/**
 *  Sets the horizontal radii of the ellipse.
 *  @param {number} rx  The horizontal radius of the ellipse.
 */
DvtXmlArc.prototype.setRx = function (rx) {
  if (rx !== this._rx) {
    this._rx = rx;
    this.Svg['rx'] = this._rx;
  }
}

/**
 *  @return {number} The vertical radius of the ellipse.
 */
DvtXmlArc.prototype.getRy = function () {
  return this._ry;
}

/**
 *  Sets the vertical radius of the ellipse.
 *  @param {number} ry  The vertical radius of the ellipse.
 */
DvtXmlArc.prototype.setRy = function (ry) {
  if (ry !== this._ry) {
    this._ry = ry;
    this.Svg['ry'] = this._ry;
  }
}
/**
 *   Creates an XML implementation of a line segment drawn from (x1, y1) to (x2, y2).
 *   An object of this class must not created directly, use {@link DvtLine}.
 *   @extends DvtXmlShape
 *   @class DvtXmlLine
 *   @constructor
 *   @param {number} x1  An x end-position of the line.
 *   @param {number} y1  The associated y end-point (for x1).
 *   @param {number} x2  The other end-point's x coordinate.
 *   @param {number} y2  The y coordinate associated with x2.
 *   @param {String} id  Optional ID for the shape (see {@link  DvtDisplayable#setId}).
 */
var DvtXmlLine = function (x1, y1, x2, y2, id) {
  this._Init(x1, y1, x2, y2, id);
}

DvtObj.createSubclass(DvtXmlLine, DvtXmlShape, "DvtXmlLine");

/**
 * @private
 */
DvtXmlLine.prototype._Init = function (x1, y1, x2, y2, id) {
  DvtXmlLine.superclass._Init.call(this, id, 'line');

  this.Svg['fill'] = 'none';
  this.setX1(x1);
  this.setY1(y1);
  this.setX2(x2);
  this.setY2(y2);
  this._bHollow = false;
}

/**
 *  @return {number} The beginning x coordinate of the line.
 */
DvtXmlLine.prototype.getX1 = function () {
  return this._x1;
}

/**
 * Sets the beginning x coordinate of the line.
 * @param {number} x1 The beginning x coordiante of the line.
 */
DvtXmlLine.prototype.setX1 = function (x1) {
  if (x1 !== this._x1) {
    this._x1 = x1;
    this.Svg['x1'] = this._x1;
  }
}

/**
 *  @return {number} The beginning y coordinate of the line.
 */
DvtXmlLine.prototype.getY1 = function () {
  return this._y1;
}

/**
 * Sets the beginning y coordinate of the line.
 * @param {number} y1 The beginning y coordiante of the line.
 */
DvtXmlLine.prototype.setY1 = function (y1) {
  if (y1 !== this._y1) {
    this._y1 = y1;
    this.Svg['y1'] = this._y1;
  }
}

/**
 *  @return {number} The ending x coordinate of the line.
 */
DvtXmlLine.prototype.getX2 = function () {
  return this._x2;
}

/**
 * Sets the ending x coordinate of the line.
 * @param {number} x2 The ending x coordiante of the line.
 */
DvtXmlLine.prototype.setX2 = function (x2) {
  if (x2 !== this._x2) {
    this._x2 = x2;
    this.Svg['x2'] = this._x2;
  }
}

/**
 *  @return {number} The ending y coordinate of the line.
 */
DvtXmlLine.prototype.getY2 = function () {
  return this._y2;
}

/**
 * Sets the ending y coordinate of the line.
 * @param {number} y2 The ending y coordiante of the line.
 */
DvtXmlLine.prototype.setY2 = function (y2) {
  if (y2 !== this._y2) {
    this._y2 = y2;
    this.Svg['y2'] = this._y2;
  }
}

/**
 * @override
 */
DvtXmlLine.prototype.setHollow = function () {
  //TODO
}

/**
 * @override
 */
DvtXmlLine.prototype.isHollow = function () {
  return this._bHollow;
}
/**
 *   Creates an elliptical shape implemented by SVG.
 *   @extends DvtXmlCircle
 *   @class  DvtXmlOval
 *   @constructor
 *   @param {number} cx  The center x position.
 *   @param {number} cy  The center y position.
 *   @param {number} rx  The horizontal radius of the ellipse.
 *   @param {number} ry  The vertical radius of the ellipse.
 *   @param {String} id  Optional ID for the shape (see {@link  DvtDisplayable#setId}).
 */
var DvtXmlOval = function (cx, cy, rx, ry, id) {
    this._Init(cx, cy, rx, ry, id);
}

DvtObj.createSubclass(DvtXmlOval, DvtXmlCircle, "DvtXmlOval");

/**
 * @private
 */
DvtXmlOval.prototype._Init = function (cx, cy, rx, ry, id) {
    DvtXmlOval.superclass._Init.call(this, cx, cy, rx, id, 'ellipse');

    this.setRx(rx);
    this.setRy(ry);
    this.setRadius(null);
}

/**
 *  @return {number} The horizontal radius of the ellipse.
 */
DvtXmlOval.prototype.getRx = function () {
    return this._rx;
}

/**
 *  Sets the horizontal radii of the ellipse.
 *  @param {number} rx  The horizontal radius of the ellipse.
 */
DvtXmlOval.prototype.setRx = function (rx) {
    if (rx !== this._rx) {
        this._rx = rx;
        this._elem.setAttributeNS(null, 'rx', this._rx);
    }
}

/**
 *  @return {number} The vertical radius of the ellipse.
 */
DvtXmlOval.prototype.getRy = function () {
    return this._ry;
}

/**
 *  Sets the vertical radius of the ellipse.
 *  @param {number} ry  The vertical radius of the ellipse.
 */
DvtXmlOval.prototype.setRy = function (ry) {
    if (ry !== this._ry) {
        this._ry = ry;
        this._elem.setAttributeNS(null, 'ry', this._ry);
    }
}
/**
 * Creates an instance of DvtXmlTextArea.
 * @extends DvtXmlShape
 * @class DvtXmlTextArea
 * @param {String} id  Optional ID for the shape (see {@link  DvtDisplayable#setId}).
 */
var DvtXmlTextArea = function (x, y, id) {
  this._Init(x, y, id);
}

DvtObj.createSubclass(DvtXmlTextArea, DvtXmlText, "DvtXmlTextArea");

/**
 * Initializes this instance of DvtTextArea.
 * @param x {number} x the x position
 * @param y {number} y the y position
 * @param id {string} the id for this object
 */
DvtXmlTextArea.prototype._Init = function (x, y, id) {
  //remove this if graph is ok with the text alignment changes
  if (x === undefined && y === undefined) {
    x = 0;
    y = 0;
    this._notGraph = true;
  }

  DvtXmlTextArea.superclass._Init.call(this, "", x, y, id);

  // the adjustment to the amount of space between lines
  this._leading = 0;
}

/**
 * Sets the text string for this textArea object.
 * @param {array} single line text or multiline text
 */
DvtXmlTextArea.prototype.setText = function (multilines) {
  var singleLine;
  if (DvtArrayUtils.isArray(multilines)) {
    if (multilines.length == 1)
      singleLine = multilines[0];
  }
  else {
    singleLine = multilines;
  }

  //Clear current text children and add new text line(s)
  this.removeChildren();

  if ((this.getNumChildren() === 1 || this.getNumChildren() === 0) && singleLine) {
    // Update the text node if it is already created
    this.addChild(singleLine);
  }
  else {
    var x = this.Svg['x'];
    var y = parseFloat(this.Svg['y']);

    if (singleLine) {
      this._addLine(singleLine, x, y);
    }
    else {
      // apply text-align on multi-line text
      var textAlign = this._getTextAlign();
      if (textAlign == "end") {
        x = this.getObj()._getMaxTextWidth();
      }
      else if (textAlign == "middle") {
        x += this.getObj()._getMaxTextWidth() / 2;
      }
      y = 0;
      for (var i = 0;i < multilines.length;i++) {
        if (DvtStyleUtils.isLocaleR2L() || textAlign) {
          this._addTextLine(multilines[i], x, y * i, textAlign);
        }
        else {
          var line = this._addLine(multilines[i], x, y);
        }
        if (i == 0) {
          y = this.getObj()._getMaxTextHeight();
          if (!y)
            y = this.getDimensions().h;
          //Bug with Batik where dy might be measuring from the bottom of the text. Need to confirm.
          //Current workaround is to set dy as the height of the text initially.
          if (line)
            line.Svg.dy = y + this.getLeading();
        }
      }
    }
  }
}

/**
 * @return {string} The text string for this textArea object.
 */
DvtXmlTextArea.prototype.getText = function () {
  var children = this.getChildren();
  var child;
  var text = "";
  for (var i = 0; i < children.length; i++) {
    child = children[i];
    // Child of a DvtXmlTextArea can be a string representing the text string for the node, tspan which contains a child
    // which is the text string for the node, or a DvtText
    if (typeof (child) == 'string')
      text += child;
    else if (child.getText)
      text += child.getText();
    else if (child.getNodeName() == 'tspan')
      text += child.getChildAt(0);
  }
  return text;
}

/**
 * Returns the amount of vertical space, in pixels, between lines
 * @return {number} the amount of vertical space (called leading) between lines
 */
DvtXmlTextArea.prototype.getLeading = function () {
  return this._leading;
}

/**
 * Sets the amount of vertical space, in pixels, between lines
 * @param {number} leading amount of vertical space, in pixels, between lines
 */
DvtXmlTextArea.prototype.setLeading = function (leading) {
  this._leading = leading;
}

DvtXmlTextArea.prototype._addLine = function (newLineText, x, dy) {
  var newText = this._createTSpan(newLineText);
  newText.Svg['x'] = x;
  newText.Svg['dy'] = dy + this.getLeading();
  return newText;
}

DvtXmlTextArea.prototype._addTextLine = function (newLineText, x, dy, textAlign) {
  var newText = new DvtXmlText(newLineText, x, dy, null);
  var textNode = this.getChildAt(1);

  var attr = textNode.Svg['dominant-baseline'];
  if (attr)
    newText.Svg["dominant-baseline"] = attr;

  attr = textAlign ? textAlign : textNode.Svg['text-anchor'];
  if (attr)
    newText.Svg["text-anchor"] = attr;
  attr = textNode.Svg['font-family'];
  if (attr)
    newText.Svg["font-family"] = attr;
  attr = textNode.Svg['font-size'];
  if (attr)
    newText.Svg["font-size"] = attr;
  attr = textNode.Svg['fill'];
  if (attr) {
    if (attr.indexOf("rgba") !==  - 1) {
      newText.Svg["fill"] = DvtColorUtils.getRGB(attr);
      newText.Svg["alpha"] = DvtColorUtils.getAlpha(attr);
    }
  }
  attr = textNode.Svg['unicode-bidi'];
  if (attr && DvtStyleUtils.isLocaleR2L())
    newText.Svg["unicode-bidi"] = attr;

  this.addChild(newText);
}

DvtXmlTextArea.prototype._getTextAlign = function () {
  var val;
  //remove the test if graph is ok with the text alignment changes
  if (this._notGraph) {
    var style = this.getCSSStyle();

    // text alignment
    val = style["text-align"];
    if (val == "left") {
      val = "start";
    }
    else if (val == "right")
      val = "end";
    else if (val == "center")
      val = "middle";

    else if (DvtStyleUtils.isLocaleR2L()) {
      val = "end";
    }
  }
  return val;
}

/**
 * @override
 */
DvtXmlTextArea.prototype.getDimensions = function () {
  var font = new Font(this._map);
  var bi = new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);
  var g = bi.createGraphics();
  var metrics = g.getFontMetrics(font);

  var maxWidth = 0;
  var maxHeight = 0;
  var minX = this._x;
  var rect;

  var children = this.getChildren();
  var child;
  var previousLineHeight = 0;
  var currentLineHeight = 0;
  for (var i = 0;i < children.length;i++) {
    child = children[i];
    // Child of a DvtXmlTextArea can be a string representing the text string for the node, tspan which contains a child
    // which is the text string for the node, or a DvtText
    if (typeof (child) == 'string') {
      rect = metrics.getStringBounds(child, g);
      maxWidth = Math.max(maxWidth, rect.getWidth());
      currentLineHeight = rect.getHeight();
      previousLineHeight = currentLineHeight;
      maxHeight += currentLineHeight;
    }
    else if (child.getText) {
      //DvtText element
      rect = metrics.getStringBounds(child.getText(), g);
      maxWidth = Math.max(maxWidth, rect.getWidth() + (child.Svg.x - minX));
      currentLineHeight = rect.getHeight() + child.Svg.y;
      previousLineHeight = currentLineHeight;
      maxHeight += currentLineHeight;
    }
    else if (child.getNodeName() == 'tspan') {
      //DvtXmlContainer
      rect = metrics.getStringBounds(child.getChildAt(0), g);
      maxWidth = Math.max(maxWidth, rect.getWidth() + (child.Svg.x - minX));
      currentLineHeight = rect.getHeight() + (child.Svg.dy - previousLineHeight);
      previousLineHeight = currentLineHeight;
      maxHeight += currentLineHeight;
    }
  }

  return new DvtRectangle(this._x, this._y, maxWidth, maxHeight);
}
/**
 * Creates an instance of DvtXmlTextFormatted.
 * @extends DvtXmlShape
 * @class DvtXmlTextFormatted
 * @param {String} id  Optional ID for the shape (see {@link  DvtDisplayable#setId}).
 */
var DvtXmlTextFormatted = function (x, y, id) {
    this._Init(x, y, id);
}

DvtObj.createSubclass(DvtXmlTextFormatted, DvtXmlText, "DvtXmlTextFormatted");

DvtXmlTextFormatted.BOLD = "b";
DvtXmlTextFormatted.ITALIC = "i";

/**
 * Initializes this instance of DvtTextFormatted.
 * @param text {string} the text string
 * @param x {number} x the x position
 * @param y {number} y the y position
 * @param id {string} the id for this object
 */
DvtXmlTextFormatted.prototype._Init = function (x, y, id) {
    DvtXmlTextFormatted.superclass._Init.call(this, "", x, y, id);
}

/**
 * Sets the text string for this textArea object.
 * @param {array} single line text or multiline text
 */
DvtXmlTextFormatted.prototype.setText = function (text) {
    // parse the formatted text
    var obj = this.getObj();
    var parser = new DvtXmlParser(obj.getContext());

    // wrap around the text with a tag to make the dom parser happy
    var newText = "<root>" + text + "</root>";
    var node = parser.parse(newText);

    if (node) {
        var childNodes = node.getChildNodes();

        for (var i = 0; i < childNodes.getLength(); i++) {
            var child = childNodes.item(i);
            if (child) {
              if (child.getTagName() == '#text')
                this._createTextNode(child.getNodeValue());
              else
                this._handleMarkup(child);
            }
        }
    }

}

// handle html markup
DvtXmlTextFormatted.prototype._handleMarkup = function (child) {
    // create tspan
    var tspan = this._createTSpan(child.getNodeValue());

    // element
    var nodeName = child.getTagName();
    if (nodeName == DvtXmlTextFormatted.BOLD) {
        tspan.Svg['font-weight'] = 'bold';
    }
    else if (nodeName == DvtXmlTextFormatted.ITALIC) {
        tspan.Svg['font-style'] = 'italic';
    }
}
/**
 *   Creates a polygon from an array of (x,y) coordinates.
 *   XML implementation for DvtPolygon which creates a shape of connected line segments.
 *   @extends DvtXmlShape
 *   @class DvtXmlPolygon
 *   @constructor
 *   @param {Array} arPoints  An array of x, y pairs of coordinates.
 *   @param {String} id  Optional ID for the shape (see {@link  DvtDisplayable#setId}).
 */
var DvtXmlPolygon = function (arPoints, id) {
  this._Init(arPoints, id);
};

DvtObj.createSubclass(DvtXmlPolygon, DvtXmlShape, "DvtXmlPolygon");

/** 
 * @private
 */
DvtXmlPolygon.prototype._Init = function (arPoints, id) {
  DvtXmlPolygon.superclass._Init.call(this, id, 'polygon');

  this.setPoints(arPoints);

}

/**
 *   @return {array} The array of x, y coordinate pairs that describe the shape of the polygon.
 */
DvtXmlPolygon.prototype.getPoints = function () {
  return this._arPoints;
}

/**
 *   Sets the polygon points from an array of x,y coordinate pairs.
 *   @param {Array} arPoints  An array of x, y pairs of coordinates.
 */
DvtXmlPolygon.prototype.setPoints = function (arPoints) {
  this._arPoints = arPoints;
  this._sPoints = DvtXmlShapeUtils.convertPointsArray(arPoints);
  this.Svg['points'] = this._sPoints;
}
/**
 *   Static shape utility functions.
 *   @class DvtXmlShapeUtils
 *   @constructor
 */
var DvtXmlShapeUtils = function () {
}

DvtXmlShapeUtils._uniqueSeed = 0;// for unique Id creation

/**
 * Creates a unique ID string
 * @param {String} sPrefix  Optional string used as a prefix for the generated ID. If 
 *                          omitted, the ID generated will be prefixed with '$'.
 * @returns {String} A unique ID string.
 */
DvtXmlShapeUtils.getUniqueId = function (sPrefix) {
  return (sPrefix ? sPrefix : '$') + DvtXmlShapeUtils._uniqueSeed++;
}

/**
 *  Adds a clipping region to the global defs element.
 *  @param {DvtClipPath}  cp  the DvtClipPath object specifying the clipping region(s).
 *  @param {DvtContext} context The context to add the clip path to.
 *  @returns {boolean}    true if the clipping paths was successfully added, else false.
 */
DvtXmlShapeUtils.addClipPath = function(cp, context) {
  var bRet = false ;

  var id = cp.getId() ;
  if (! id)
    return  bRet;    // essential to have an id to reference

  var elemDefs = context.getDefs() ; 
  if (! elemDefs)
    return bRet;

  // Check if clipping path for this id is already defined.
  var elemClip = null ;
  var defsChildren = elemDefs.getChildren() ;
  var len = defsChildren.length ;

  for (var i = 0; i < len; i++) {
     var el = defsChildren[i] ;
     if (el.id === id) {
       elemClip = el ;
      break ;
    }
  }
  
  if (elemClip) {
    bRet = true ;
  }
  else {
    elemClip  = DvtXmlShapeUtils.createElement('clipPath', id) ;
    context.appendDefs(elemClip) ;

    var regions = cp.getRegionCount() ;
    
    for (var i = 0; i < regions; i++) {
       var region = cp.getRegion(i) ;

       if (region) {
         var  elem = null ;
         if (region.type === DvtClipPath.RECT) {
            elem = DvtXmlShapeUtils.createElement('rect', id) ;
            elem.Svg['x'] = region.x;
            elem.Svg['y'] = region.y;
            elem.Svg['width'] = region.w;
            elem.Svg['height'] = region.h;
         }
         else if (region.type === DvtClipPath.ELLIPSE) {
            elem = DvtXmlShapeUtils.createElement('ellipse', id) ;
            elem.Svg['cx'] = region.cx;
            elem.Svg['cy'] = region.cy;
            elem.Svg['rx'] = region.rx;
            elem.Svg['ry'] = region.ry;
         }

         if (elem) {
           elemClip.addChild(elem) ;
         }
         bRet = true;
       }

    }
  }
  return bRet ;
}

/**
 * Converts an array of x,y coordinate pairs.
 * @param {array} arPoints the array of points
 * @returns {Array}  the string usable by SVG polygons and polylines
 */
DvtXmlShapeUtils.convertPointsArray = function(arPoints) {
  var len = arPoints.length ;   // convert to svg space separated list
  var s = '' ;

  for (var i = 0; i < len; i++) {
    if (i > 0) {
      s += ' ' ;
    }
    s += arPoints[i] ;
  }
  return s;
}

/**
 * Creates an XML element
 * @param {string} name The name of the XML element
 * @param {string} id The id of the XML element
 * @return {DvtObj} 
 */
DvtXmlShapeUtils.createElement = function(type, id) {
  return new DvtXmlContainer(id, type);
}
importPackage(Packages.java.awt.image);
importPackage(Packages.java.io);
importPackage(Packages.javax.imageio);
importPackage(Packages.javax.faces.context);
importPackage(Packages.java.net);
importPackage(Packages.oracle.adfinternal.view.faces.bi.renderkit.imageView);

var DvtXmlImageLoader = { _cache: {} };

DvtXmlImageLoader.addBubbleEventListener = function(element, type, listener) {
  return false;
}

/**
 * Load an image.
 * 
 * @param src URL of the image to load
 * @param onComplete function to call when the image is loaded
 * 
 * @return image if image is already loaded and onComplete
 *         function is null, otherwise null
 */
DvtXmlImageLoader.loadImage = function(src, onComplete) {
  var entry = DvtXmlImageLoader.getImageInfo(src);
  
  if (entry) {
    if (onComplete)
      onComplete(entry);
    return entry;
  } else {
    return null;
  }
}

DvtXmlImageLoader._isRelativeURL = function(uri) {
  return (uri.indexOf(':') < 0);
}

DvtXmlImageLoader._getURL = function(externalContext, file) {
  var protocol = externalContext.getRequestScheme(); //i.e. http or https
  var host = InetAddress.getLocalHost().getHostAddress();
  var port = externalContext.getRequestServerPort();
  return new URL(protocol, host, port, file);
}

/**
 * Load a new image if needed and retruns the uri, width, height of the image or null if it could not be loaded.
 * 
 * @param src URL of the image to load
 */
DvtXmlImageLoader.getImageInfo = function(src) {

  if (!this._cache[src]) {
    var uri = src;
    var image;
    var context = FacesContext.getCurrentInstance();
    var externalContext = context.getExternalContext();
    
    // Remove context path if it exists. getReourceAsStream won't work with it for some reason.
    var contextPath = externalContext.getRequestContextPath();
    if (uri.search(contextPath) == 0) {
      uri = uri.replace(contextPath, "");
    }
    
    //Make sure there is a leading slash. RenderUtils.getResourceURL requires whereas, it is sometimes left out
    //as in DvtImageLAFUtils so the browser can load it.
    if (uri.charAt(0) != "/")
      uri = "/"+uri;
        
    var stream = externalContext.getResourceAsStream(uri);
    if (stream) { //Case 1: Application image. Load from external context
      image = ImageIO.read(stream);
      uri = externalContext.getResource(uri);
    } else { //Case 2: Internal image. Add host, port, and protocol to interal relative URL
      uri = DvtXmlImageLoader._getURL(externalContext, RenderUtils.getResourceURL(context, uri));
      try {
        image = ImageIO.read(uri);
      } catch (err) {
        image = null;
      }
    }
    
    if (image) {
      var imageInfo = new Object();
      imageInfo['uri'] = uri;
      imageInfo["width"] =  image.getWidth();
      imageInfo["height"] = image.getHeight();
      this._cache[src] = imageInfo;
    }
  }
  
  return this._cache[src]
}
/**
 * No-Op Document APIs.
 * @class DvtXmlDocumentUtils
 */
var DvtXmlDocumentUtils = function () {
}

DvtXmlDocumentUtils.elementFromPoint = function (posX, posY) {
    return null;
}

DvtXmlDocumentUtils.getStageRelativePosition = function (stage, x, y) {
    return new DvtPoint(x, y);
}

DvtXmlDocumentUtils.getPageRelativePosition = function (stage, x, y) {
    return new DvtPoint(x, y);
}

DvtXmlDocumentUtils.getStageAbsolutePosition = function (stage) {
    return new DvtPoint(x, y);
}

DvtXmlDocumentUtils.isFilterSupported = function (stage) {
    return false;
}

DvtXmlDocumentUtils.isStrokeTimeoutRequired = function () {
    return false;
}

DvtXmlDocumentUtils.isEventAvailableOutsideClip = function () {
    return false;
}

DvtXmlDocumentUtils.isFilterStraightLineAdjustmentNeeded = function () {
    return false;
}

DvtXmlDocumentUtils.fixWebkitFilters = function (svgDomElement) {
}

DvtXmlDocumentUtils.fixWebkitFiltersForDisplayable = function (displayable) {
}

DvtXmlDocumentUtils.cancelDomEvent = function (e) {
}
